Skip to content

Commit aca3ead

Browse files
committed
add multiTouch support
1 parent a84e752 commit aca3ead

File tree

3 files changed

+190
-77
lines changed

3 files changed

+190
-77
lines changed

07-Ping-Pong-Game/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
<head>
55
<title>Ping Pong Game</title>
6+
<meta charset="UTF-8">
67
<meta name="viewport" content="user-scalable=no maximum-scale=1.0">
78

89
<!-- Add the Bootstrap CSS file -->
@@ -28,7 +29,7 @@
2829
</style>
2930
</head>
3031

31-
<body>
32+
<body oncontextmenu="return false" onselectstart="return false">
3233
<div class="container">
3334
<canvas id="canvas" width="600" height="400"></canvas>
3435
</div>

07-Ping-Pong-Game/script.js

Lines changed: 185 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ addEventListener("load", (event) => {
3434
var ballRadius = 10;
3535
var ballX = canvas.width / 2;
3636
var ballY = canvas.height / 2;
37-
var ballSpeedX = 5;
38-
var ballSpeedY = 5;
37+
var ballSpeedX = 4;
38+
var ballSpeedY = 4;
3939

4040
// Define paddle properties
4141
var paddleHeight = 80;
@@ -203,6 +203,25 @@ function draw() {
203203
// Draw scores
204204
ctx.fillText("Score: " + leftPlayerScore, 10, 20);
205205
ctx.fillText("Score: " + rightPlayerScore, canvas.width - 70, 20);
206+
return;
207+
//debug
208+
const lineHeight = 20;
209+
const startY = canvas.height / 2 - (debugInfo.length * lineHeight) / 2;
210+
211+
ctx.save();
212+
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
213+
ctx.fillRect(0, startY - 10, canvas.width, debugInfo.length * lineHeight + 20);
214+
215+
ctx.font = '16px Arial';
216+
ctx.fillStyle = 'white';
217+
ctx.textAlign = 'center';
218+
219+
debugInfo.forEach((info, index) => {
220+
ctx.fillText(info, canvas.width / 2, startY + index * lineHeight);
221+
});
222+
drawDebugInfo();
223+
224+
206225
}
207226

208227
// Game loop
@@ -342,31 +361,28 @@ var touchYstartLeft = null;
342361
var previousPositionLeft = canvas.height / 2 - paddleHeight;
343362
var touchYstartRight = null;
344363
var previousPositionRight = canvas.height / 2 - paddleHeight;
364+
const canvasBounds = canvas.getBoundingClientRect();
365+
const canvasMiddle = canvasBounds.width/2+canvasBounds.left;
366+
345367
function actionStart(e) {
346368
//e.preventDefault();
347369
//判断是鼠标左键点击还是触摸
348370
if(!gameRunning ) { return; }
349-
var leftPt = { pageX: canvas.width, pageY: 0 }, rightPt = { pageX: 0, pageY: 0 };
371+
var leftPt = { pageX: canvas.width, pageY: -1 }, rightPt = { pageX: 0, pageY: -1 };
350372

351-
if (e.touches && e.touches.length > 1) {//如果是触摸
352-
e.touches.forEach(element => {//记录左半边,最左边的点
353-
if (element.pageX - canvas.offsetLeft < canvas.width / 2) {
354-
leftPt = element.pageX < leftPt.pageX ? element : leftPt;
373+
if (e.touches && e.touches.length >= 1) {//如果是触摸
374+
for(var i = 0; i < e.touches.length; i++){//记录左半边,最左边的点
375+
if (e.touches[i].pageX < canvasMiddle) {
376+
leftPt = e.touches[i].pageX < leftPt.pageX ? e.touches[i] : leftPt;
355377
} else {//记录右半边,最右边的点
356-
rightPt = element.pageX > rightPt.pageX ? element : rightPt;
378+
rightPt = e.touches[i].pageX > rightPt.pageX ? e.touches[i] : rightPt;
357379
}
358-
});
359-
if (touchYstartLeft == null) { touchYstartLeft = leftPt.pageY; }
360-
if (touchYstartRight == null) { touchYstartRight = rightPt.pageY; }
361-
return;
362-
} else if (e.touches && e.touches.length == 1) {//如果是单点触摸
363-
if (e.touches[0].pageX - canvas.offsetLeft < canvas.width / 2) {
364-
if (touchYstartLeft == null) { touchYstartLeft = e.touches[0].pageY; }
365-
} else {
366-
if (touchYstartRight == null) { touchYstartRight = e.touches[0].pageY; }
367380
}
368-
} else {//如果是鼠标 touchXstart等于鼠标的x坐标
369-
if (e.pageX - canvas.offsetLeft < canvas.width / 2) {
381+
if (touchYstartLeft == null && leftPt.pageY != -1 ) { touchYstartLeft = leftPt.pageY; }
382+
if (touchYstartRight == null && rightPt.pageY != -1) { touchYstartRight = rightPt.pageY; }
383+
return;
384+
} else {//如果是鼠标 touchXstart等于鼠标的x坐标
385+
if (e.pageX <canvasMiddle) {
370386
if (touchYstartLeft == null) { touchYstartLeft = e.pageY; }
371387
} else {
372388
if (touchYstartRight == null) { touchYstartRight = e.pageY; }
@@ -388,73 +404,166 @@ function actionEnd(e) {
388404
previousPositionLeft = leftPaddleY;
389405
}
390406
}
407+
408+
// 全局变量,用于存储调试信息
409+
let debugInfo = [];
410+
const DEBUG_AREA_SIZE = 480;
411+
const LINE_HEIGHT = 20;
412+
const MAX_LINES = Math.floor(DEBUG_AREA_SIZE / LINE_HEIGHT);
413+
let debugScrollY = 0;
414+
391415
function actionMove(e) {
392416
e.preventDefault(); // 防止页面滚动
393-
if (touchYstartRight !== null || touchYstartLeft !== null && gameRunning) {
394-
var distLeft, distRight;
395-
if (e.touches && e.touches.length > 1) { // 多点触摸
396-
//初始化为画布中间位置
397-
let leftPt = {pageX:canvas.offsetLeft + canvas.width / 2,pageY:0};
398-
let rightPt = {pageX:canvas.offsetLeft + canvas.width / 2,pageY:0};
399-
ballColor = 'red';
400-
for (let i = 1; i < e.touches.length; i++) {
401-
if (e.touches[i].pageX < leftPt.pageX- canvas.offsetLeft) {
402-
leftPt = e.touches[i];
403-
404-
}
405-
if (e.touches[i].pageX > rightPt.pageX- canvas.offsetLeft) {
406-
rightPt = e.touches[i];
407-
408-
}
409-
}
417+
if (gameRunning) {
418+
if (e.touches) { // 触摸事件
419+
handleTouchMove(e);
420+
} else { // 鼠标事件
421+
handleMouseMove(e);
422+
}
423+
}
424+
}
410425

411-
if (touchYstartLeft !== null && leftPt.pageX - canvas.offsetLeft < canvas.width / 2) {
412-
distLeft = leftPt.pageY - touchYstartLeft;
413-
leftPaddleY = previousPositionLeft + distLeft;
414-
leftPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, leftPaddleY));
415-
ballColor = 'blue';
426+
function handleTouchMove(e) {
427+
let leftTouch = null;
428+
let rightTouch = null;
429+
430+
// 清除之前的调试信息
431+
clearDebugInfo();
432+
433+
// 遍历所有触摸点,找出最左和最右的触摸点,并记录调试信息
434+
for (let i = 0; i < e.touches.length; i++) {
435+
let touch = e.touches[i];
436+
let touchX = touch.pageX;
437+
let touchY = touch.pageY;
438+
439+
// 添加调试信息
440+
addDebugInfo(`Touch ${i}: (${Math.round(touchX)}, ${Math.round(touchY)})`);
441+
442+
if (touchX < canvasMiddle) { // 左半边
443+
if (!leftTouch || touchX < leftTouch.pageX ) {
444+
leftTouch = touch;
416445
}
417-
418-
if (touchYstartRight !== null && rightPt.pageX - canvas.offsetLeft > canvas.width / 2) {
419-
distRight = rightPt.pageY - touchYstartRight;
420-
rightPaddleY = previousPositionRight + distRight;
421-
rightPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, rightPaddleY));
422-
ballColor = 'green';
446+
447+
} else { // 右半边
448+
if (!rightTouch || touchX > rightTouch.pageX ) {
449+
rightTouch = touch;
423450
}
451+
452+
}
453+
}
454+
try{addDebugInfo(`leftTouch: (${leftTouch.pageX}, ${leftTouch.pageY}, ${touchYstartLeft})`);}catch(e){}
455+
try{addDebugInfo(`rightTouch: (${rightTouch.pageX}, ${rightTouch.pageY}, ${touchYstartRight})`);}catch(e){}
456+
457+
// 更新左侧滑板位置
458+
try{if (leftTouch && touchYstartLeft !== null) {
459+
let distLeft = leftTouch.pageY - touchYstartLeft;
460+
leftPaddleY = previousPositionLeft + distLeft;
461+
leftPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, leftPaddleY));
462+
addDebugInfo(`distLeft: (${distLeft})`);
463+
}}catch(e){}
464+
465+
// 更新右侧滑板位置
466+
try{if (rightTouch && touchYstartRight !== null) {
467+
let distRight = rightTouch.pageY - touchYstartRight;
468+
rightPaddleY = previousPositionRight + distRight;
469+
rightPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, rightPaddleY));
470+
addDebugInfo(`distRight: (${distRight})`);
471+
}}catch(e){}
472+
}
424473

425-
} else if (e.touches && e.touches.length == 1) { // 单点触摸
426-
let touch = e.touches[0];
427-
if (touch.pageX - canvas.offsetLeft < canvas.width / 2) {
428-
if (touchYstartLeft !== null) {
429-
distLeft = touch.pageY - touchYstartLeft;
430-
leftPaddleY = previousPositionLeft + distLeft;
431-
leftPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, leftPaddleY));
432-
}
433-
} else {
434-
if (touchYstartRight !== null) {
435-
distRight = touch.pageY - touchYstartRight;
436-
rightPaddleY = previousPositionRight + distRight;
437-
rightPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, rightPaddleY));
438-
}
439-
}
440-
} else { // 鼠标移动
441-
if (e.pageX - canvas.offsetLeft < canvas.width / 2) {
442-
if (touchYstartLeft !== null) {
443-
distLeft = e.pageY - touchYstartLeft;
444-
leftPaddleY = previousPositionLeft + distLeft;
445-
leftPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, leftPaddleY));
446-
}
447-
} else {
448-
if (touchYstartRight !== null) {
449-
distRight = e.pageY - touchYstartRight;
450-
rightPaddleY = previousPositionRight + distRight;
451-
rightPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, rightPaddleY));
452-
}
453-
}
474+
function handleMouseMove(e) {
475+
let mouseX = e.pageX;
476+
let mouseY = e.pageY;
477+
478+
// 添加鼠标位置到调试信息
479+
clearDebugInfo();
480+
addDebugInfo(`Mouse: (${Math.round(mouseX)}, ${Math.round(mouseY)})`);
481+
482+
if (mouseX < canvasMiddle) {
483+
if (touchYstartLeft !== null) {
484+
let distLeft = mouseY - touchYstartLeft;
485+
leftPaddleY = previousPositionLeft + distLeft;
486+
leftPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, leftPaddleY));
487+
}
488+
} else {
489+
if (touchYstartRight !== null) {
490+
let distRight = mouseY - touchYstartRight;
491+
rightPaddleY = previousPositionRight + distRight;
492+
rightPaddleY = Math.max(0, Math.min(canvas.height - paddleHeight, rightPaddleY));
493+
}
494+
}
495+
}
496+
497+
function clearDebugInfo() {
498+
return;
499+
debugInfo = [];
500+
debugScrollY = 0;
501+
}
502+
503+
function addDebugInfo(info) {
504+
return;
505+
debugInfo.push(info);
506+
if (debugInfo.length > MAX_LINES) {
507+
debugScrollY += LINE_HEIGHT;
508+
if (debugScrollY >= DEBUG_AREA_SIZE) {
509+
debugScrollY = 0;
454510
}
455511
}
456512
}
457513

514+
function drawDebugInfo() {
515+
const ctx = canvas.getContext('2d');
516+
const startX = (canvas.width - DEBUG_AREA_SIZE) / 2;
517+
const startY = (canvas.height - DEBUG_AREA_SIZE) / 2;
518+
519+
ctx.save();
520+
521+
// 绘制调试区域背景
522+
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
523+
ctx.fillRect(startX, startY, DEBUG_AREA_SIZE, DEBUG_AREA_SIZE);
524+
525+
// 设置裁剪区域
526+
ctx.beginPath();
527+
ctx.rect(startX, startY, DEBUG_AREA_SIZE, DEBUG_AREA_SIZE);
528+
ctx.clip();
529+
530+
ctx.font = '16px Arial';
531+
ctx.fillStyle = 'white';
532+
ctx.textAlign = 'left';
533+
534+
debugInfo.forEach((info, index) => {
535+
let y = startY + index * LINE_HEIGHT - debugScrollY;
536+
if (y < startY) {
537+
y += DEBUG_AREA_SIZE;
538+
}
539+
ctx.fillText(info, startX + 10, y + LINE_HEIGHT);
540+
});
541+
542+
ctx.restore();
543+
}
544+
545+
// 在您的主绘制函数中添加这个函数调用
546+
//function draw() {
547+
// ... 您现有的绘制代码 ...
548+
549+
// const ctx = canvas.getContext('2d');
550+
// const lineHeight = 20;
551+
// const startY = canvas.height / 2 - (debugInfo.length * lineHeight) / 2;
552+
553+
// ctx.save();
554+
// ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
555+
// ctx.fillRect(0, startY - 10, canvas.width, debugInfo.length * lineHeight + 20);
556+
557+
// ctx.font = '16px Arial';
558+
// ctx.fillStyle = 'white';
559+
// ctx.textAlign = 'center';
560+
561+
// debugInfo.forEach((info, index) => {
562+
// ctx.fillText(info, canvas.width / 2, startY + index * lineHeight);
563+
// });
564+
// drawDebugInfo();
565+
//}
566+
458567
// 事件监听器
459568
document.addEventListener('touchstart', actionStart, { passive: false });
460569
document.addEventListener('touchend', actionEnd);

07-Ping-Pong-Game/style.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,7 @@ canvas {
4141
body {
4242
overscroll-behavior-y: contain;
4343
max-height: 80vh;
44+
user-select: none;
45+
-moz-user-select: none;
46+
-o-user-select: none;
4447
}

0 commit comments

Comments
 (0)