问题描述
这是我的乒乓球比赛。
一旦球击中左侧3次,比赛就结束了。
我想要一种可以在游戏结束后重置游戏并可以开始新游戏的解决方案。
但是我发现很难做,也许是因为画布的行为异常。 这个问题有解决办法吗?
并且重置鼠标悬停后,该东西也会停止工作。
- 请注意,我在HTML文件点击事件中的游戏开始和游戏结束消息框都使用了相同的功能。
let canvas = document.getElementById("canvas"); let canvasX = 0,canvasY = 0; canvas.width = window.innerWidth - 100; canvas.height = window.innerHeight - 100; // Game logic let tick; let gameEnd = false; let mistakeCount = 0; let playerHeights = 150; let executed = false; let ctx = canvas.getContext("2d"); ctx.fillStyle = "blue"; // canvas let cw = canvas.width; let ch = canvas.height; ctx.fillRect(canvasX,canvasY,cw,ch); // player who is playing let playerPos = ch / 2; ctx.fillStyle = "white"; ctx.fillRect(10,playerPos,10,playerHeights); // ball position let ballX = cw / 2,ballY = ch / 2,ballHorizontalDirection = true,//right side ballAngle = 5; // The amount of pixels the ball has to move upwards ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(ballX,ballY,2 * Math.PI); ctx.fill(); ctx.closePath(); // computer player let computerPos = ch / 2; ctx.fillStyle = "white"; ctx.fillRect(cw - 20,computerPos,playerHeights); function gameloop(buttonId) { document.addEventListener("mousemove",(e) => { // e.clientX,e.clientY playerPos = e.clientY; }); document.getElementById(buttonId).style.display = "none"; let i = 0; draw(); } function resetTheGame() { cancelAnimationFrame(tick); document.getElementById("gameover").style.display = "flex"; executed = false; gameEnd = false; mistakeCount = 0; playerPos = ch / 2; ballX = cw / 2; ballY = ch / 2; ballHorizontalDirection = true; //right side ballAngle = 5; computerPos = ch / 2; } function checkForPlayerCollision() { if (ballX <= 25 && ballY < playerPos + playerHeights && ballY > playerPos) { ballHorizontalDirection = !ballHorizontalDirection; let firstHalf = playerPos + playerHeights / 2; if (ballY > firstHalf + 20) { ballAngle = 5; } else if (ballY > firstHalf - 20 && ballY < firstHalf + 20) { ballAngle = 0; } else { ballAngle = -5; } } if (ballX >= cw - 20) { ballHorizontalDirection = !ballHorizontalDirection; } } function selectBallPosition() { if (ballHorizontalDirection) { ballX += 5; } else { ballX -= 5; } } function gameEnds() { if (!executed) { if (ballX >= cw || ballX <= 5) { if (mistakeCount == 2) { alert("Game End"); executed = true; resetTheGame(); return true; } ballHorizontalDirection = !ballHorizontalDirection; mistakeCount++; return false; } return false; } return true; } function setPlayerPositions() { if (playerPos + playerHeights >= ch - 40 || playerPos <= 20) { playerPos = playerPos; } if (computerPos + playerHeights >= ch - 20 || computerPos <= 20) { computerPos = computerPos; } } function checkForTopBottomCollision() { if (ballY <= 10 || ballY >= ch - 20) { ballAngle = -1 * ballAngle; } } function draw() { cancelAnimationFrame(tick); ctx.clearRect(10,ch); // context ctx.fillStyle = "blue"; ctx.fillRect(10,ch); // player ctx.fillStyle = "white"; ctx.fillRect(10,playerHeights); ballY += ballAngle; // computer ctx.fillStyle = "white"; ctx.fillRect(cw - 20,ballY - 20,playerHeights); // ball ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(ballX,2 * Math.PI); ctx.fill(); ctx.closePath(); // frame ctx.fillStyle = "gray"; ctx.beginPath(); ctx.linewidth = "20"; ctx.rect(0,ch); ctx.stroke(); // dotted line in between ctx.beginPath(); ctx.linewidth = "1"; ctx.setLineDash([20,5]); ctx.moveto(cw / 2,0); ctx.lineto(cw / 2,ch); ctx.stroke(); ctx.setLineDash([]); ctx.closePath(); // score board for player ctx.fillStyle = "skyblue"; ctx.font = "100px Arial,Helvetica,sans-serif"; ctx.fillText("0",cw / 2 - 150,ch / 2 + 35); // score board for computer ctx.fillText(mistakeCount,cw / 2 + 100,ch / 2 + 35); if (!gameEnd) { tick = requestAnimationFrame(draw); selectBallPosition(); setPlayerPositions(); checkForPlayerCollision(); checkForTopBottomCollision(); gameEnd = gameEnds(); } }
* { margin: 0; padding: 0; Box-sizing: border-Box; font-family: Arial,sans-serif; } body { width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; background: rgba(0,255,0.5); } #gameover { display: none; width: 100vw; height: 100vh; align-items: center; justify-content: center; flex-direction: column; background-color: rgba(247,14,0.7); } #start { position: fixed; z-index: 1; width: 100vw; height: 100vh; line-height: 100vh; text-align: center; font-size: xx-large; background-color: rgba(14,247,0.7); }
<head> <Meta charset="UTF-8"> <Meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="style.css"> </head> <body> <div id="start" onclick="gameloop('start')"> Click any where to continue </div> <div id="gameover" onclick="gameloop('gameover')"> Game Over! <br> Click any where to continue </div> <canvas id="canvas"></canvas> <script src="script.js"></script> </body>
解决方法
所以基本上我已经自己解决了这个问题。 除了使用单独的“ gameover” div来显示游戏结束,我还可以使用下面的给定代码。
@register.filter
从初始代码对代码所做的更改是
let canvas = document.getElementById("canvas");
let canvasX = 0,canvasY = 0;
canvas.width = window.innerWidth - 100;
canvas.height = window.innerHeight - 100;
// Game logic
let tick;
let gameEnd = false;
let mistakeCount = 0;
let playerHeights = 150;
let ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
// canvas
let cw = canvas.width;
let ch = canvas.height;
ctx.fillRect(canvasX,canvasY,cw,ch);
// player who is playing
let playerPos = ch / 2;
ctx.fillStyle = "white";
ctx.fillRect(10,playerPos,10,playerHeights);
// ball position
let ballX = cw / 2,ballY = ch / 2,ballHorizontalDirection = true,//right side
ballAngle = 5; // The amount of pixels the ball has to move upwards
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(ballX,ballY,2 * Math.PI);
ctx.fill();
ctx.closePath();
// computer player
let computerPos = ch / 2;
ctx.fillStyle = "white";
ctx.fillRect(cw - 20,computerPos,playerHeights);
function gameloop(buttonId) {
document.addEventListener("mousemove",(e) => {
// e.clientX,e.clientY
playerPos = e.clientY;
});
document.getElementById(buttonId).style.display = "none";
let i = 0;
draw();
}
function resetTheGame() {
mistakeCount = 0;
ballX = cw / 2;
ballY = ch / 2;
ballHorizontalDirection = true;
}
function checkForPlayerCollision() {
if (ballX <= 25 && ballY < playerPos + playerHeights && ballY > playerPos) {
ballHorizontalDirection = !ballHorizontalDirection;
let firstHalf = playerPos + playerHeights / 2;
if (ballY > firstHalf + 20) {
ballAngle = 5;
} else if (ballY > firstHalf - 20 && ballY < firstHalf + 20) {
ballAngle = 0;
} else {
ballAngle = -5;
}
}
if (ballX >= cw - 20) {
ballHorizontalDirection = !ballHorizontalDirection;
}
}
function selectBallPosition() {
if (ballHorizontalDirection) {
ballX += 5;
} else {
ballX -= 5;
}
}
function gameEnds() {
if (ballX >= cw || ballX <= 5) {
if (mistakeCount == 2) {
resetTheGame();
return true;
}
ballHorizontalDirection = !ballHorizontalDirection;
mistakeCount++;
return false;
}
return false;
}
function setPlayerPositions() {
if (playerPos + playerHeights >= ch - 40 || playerPos <= 20) {
playerPos = playerPos;
}
if (computerPos + playerHeights >= ch - 20 || computerPos <= 20) {
computerPos = computerPos;
}
}
function checkForTopBottomCollision() {
if (ballY <= 10 || ballY >= ch - 20) {
ballAngle = -1 * ballAngle;
}
}
function draw() {
cancelAnimationFrame(tick);
ctx.clearRect(10,ch);
// context
ctx.fillStyle = "blue";
ctx.fillRect(10,ch);
// player
ctx.fillStyle = "white";
ctx.fillRect(10,playerHeights);
ballY += ballAngle;
// computer
ctx.fillStyle = "white";
ctx.fillRect(cw - 20,ballY - 20,playerHeights);
// ball
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(ballX,2 * Math.PI);
ctx.fill();
ctx.closePath();
// frame
ctx.fillStyle = "gray";
ctx.beginPath();
ctx.lineWidth = "20";
ctx.rect(0,ch);
ctx.stroke();
// dotted line in between
ctx.beginPath();
ctx.lineWidth = "1";
ctx.setLineDash([20,5]);
ctx.moveTo(cw / 2,0);
ctx.lineTo(cw / 2,ch);
ctx.stroke();
ctx.setLineDash([]);
ctx.closePath();
// score board for player
ctx.fillStyle = "skyblue";
ctx.font = "100px Arial,Helvetica,sans-serif";
ctx.fillText("0",cw / 2 - 150,ch / 2 + 35);
// score board for computer
ctx.fillText(mistakeCount,cw / 2 + 100,ch / 2 + 35);
if (!gameEnd) {
tick = requestAnimationFrame(draw);
selectBallPosition();
setPlayerPositions();
checkForPlayerCollision();
checkForTopBottomCollision();
gameEnd = gameEnds();
} else {
cancelAnimationFrame(tick);
ctx.clearRect(0,ch);
// context
ctx.fillStyle = "blue";
ctx.fillRect(0,ch);
ctx.fillStyle = "skyblue";
ctx.font = "50px Arial,sans-serif";
ctx.fillText("You Lose!",cw / 4,ch / 2);
ctx.fillText("Click to continue",ch / 2 + 100);
canvas.addEventListener("click",() => {
tick = requestAnimationFrame(draw);
gameEnd = false;
canvas.removeEventListener("click");
});
}
}
并在此处添加一个else循环?
function resetTheGame() {
mistakeCount = 0;
ballX = cw / 2;
ballY = ch / 2;
ballHorizontalDirection = true;
}