我正在尝试制作像乒乓球这样的视频游戏。
我分别使用rect()
和arc()
函数绘制了桨和球。这些是在HTML <canvas>
元素上绘制的。事件处理程序附加到文档中的向上和向下箭头键。这些允许能够移动桨。使用setInterval()
功能在10毫秒后更改球的x和y坐标。
我遇到的问题是,有时球会被困在桨中,并开始以锯齿形的方式在其中运动。
我怎样才能解决这个问题?我想在击中球拍的前部时立即更改球的x速度,如果击中其侧面则更改其y速度。
这是我的代码:
<!-- index.html -->
<html>
<head>
<link type="text/css" rel="stylesheet" href="stylesheet.css"/>
</head>
<body>
<canvas id="my-canvas" height="300px" width="400px"></canvas>
<script src="jquery-3.1.1.min.js"></script>
<script src="script.js"></script>
</body>
</html>
/* stylesheet.css */
body {
background-color: #f00;
}
canvas {
background-color: #fff;
}
/* script.js */
$(document).ready(function () {
var canvas = $("#my-canvas")[0];
var ctx = canvas.getContext("2d");
var paddleHeight = 8;
var paddleWidth = 70;
var paddleY = (canvas.height - paddleWidth) / 2;
var ballRadius = 8;
var ballX = canvas.width / 2;
var ballY = canvas.height / 2;
var xDir = 2;
var yDir = -2;
var upPressed = false;
var downPressed = false;
$(document).keydown(function (e) {
switch (e.which) {
case 38:
upPressed = true;
break;
case 40:
downPressed = true;
}
});
$(document).keyup(function (e) {
switch (e.which) {
case 38:
upPressed = false;
break;
case 40:
downPressed = false;
}
});
function drawPaddle () {
ctx.beginPath();
ctx.rect(0, paddleY, paddleHeight, paddleWidth);
ctx.fillStyle = "#0f0";
ctx.fill();
ctx.closePath();
}
function drawBall () {
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#00f";
ctx.fill();
ctx.closePath();
}
function draw () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPaddle();
ballX += xDir;
ballY += yDir;
// Collision detection with the sides of the canvas
if (ballY == canvas.height - ballRadius || ballY == ballRadius) {
yDir = -yDir;
} else if (ballX == ballRadius || ballX == canvas.width - ballRadius) {
xDir = -xDir;
}
// Collision detection with the front of the paddle
if (ballX == paddleHeight + ballRadius && ballY >= paddleY && ballY <= paddleY + paddleWidth) {
xDir = -xDir;
}
// Collision detection with the top side of the paddle
if (ballX < paddleHeight + ballRadius && ballY < paddleY && ballY >= paddleY - ballRadius) {
yDir = -yDir;
}
// Collision detection with the bottom side of the paddle
if (ballX < paddleHeight + ballRadius && ballY > paddleY + paddleWidth && ballY <= paddleY + paddleWidth + ballRadius) {
yDir = -yDir;
}
drawBall();
// Paddle moving logic
if (downPressed && paddleY < canvas.height - paddleWidth) {
paddleY += 7;
} else if (upPressed && paddleY > 0) {
paddleY -= 7;
}
}
setInterval(draw, 10);
});
最佳答案
也许:
<!-- index.html -->
<html>
<head>
<link type="text/css" rel="stylesheet" href="stylesheet.css"/>
</head>
<body>
<canvas id="my-canvas" height="300px" width="400px"></canvas>
<script src="jquery-3.1.1.min.js"></script>
<script src="script.js"></script>
</body>
</html>
/* stylesheet.css */
body {
background-color: #f00;
}
canvas {
background-color: #fff;
}
/* script.js */
$(document).ready(function () {
var canvas = $("#my-canvas")[0];
var ctx = canvas.getContext("2d");
var paddleHeight = 8;
var paddleWidth = 70;
var paddleY = (canvas.height - paddleWidth) / 2;
var ballRadius = 8;
var ballX = canvas.width / 2;
var ballY = canvas.height / 2;
var xDir = 2;
var yDir = -2;
var upPressed = false;
var downPressed = false;
$(document).keydown(function (e) {
switch (e.which) {
case 38:
upPressed = true;
break;
case 40:
downPressed = true;
}
});
$(document).keyup(function (e) {
switch (e.which) {
case 38:
upPressed = false;
break;
case 40:
downPressed = false;
}
});
function escapePaddle() {
// I copy and pasted your collision logic and composed a super long condition. Brace yourself...
while ((ballX == paddleHeight + ballRadius && ballY >= paddleY && ballY <= paddleY + paddleWidth) || (ballX < paddleHeight + ballRadius && ballY < paddleY && ballY >= paddleY - ballRadius) || (ballX < paddleHeight + ballRadius && ballY > paddleY + paddleWidth && ballY <= paddleY + paddleWidth + ballRadius)) {
ballX+= xDir;
ballY += yDir;
}
}
function drawPaddle () {
ctx.beginPath();
ctx.rect(0, paddleY, paddleHeight, paddleWidth);
ctx.fillStyle = "#0f0";
ctx.fill();
ctx.closePath();
}
function drawBall () {
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#00f";
ctx.fill();
ctx.closePath();
}
function draw () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPaddle();
ballX += xDir;
ballY += yDir;
// Collision detection with the sides of the canvas
if (ballY == canvas.height - ballRadius || ballY == ballRadius) {
yDir = -yDir;
} else if (ballX == ballRadius || ballX == canvas.width - ballRadius) {
xDir = -xDir;
}
// Collision detection with the front of the paddle
if (ballX == paddleHeight + ballRadius && ballY >= paddleY && ballY <= paddleY + paddleWidth) {
xDir = -xDir;
escapePaddle();
}
// Collision detection with the top side of the paddle
if (ballX < paddleHeight + ballRadius && ballY < paddleY && ballY >= paddleY - ballRadius) {
yDir = -yDir;
escapePaddle();
}
// Collision detection with the bottom side of the paddle
if (ballX < paddleHeight + ballRadius && ballY > paddleY + paddleWidth && ballY <= paddleY + paddleWidth + ballRadius) {
yDir = -yDir;
escapePaddle();
}
drawBall();
// Paddle moving logic
if (downPressed && paddleY < canvas.height - paddleWidth) {
paddleY += 7;
} else if (upPressed && paddleY > 0) {
paddleY -= 7;
}
}
setInterval(draw, 10);
});
我添加了一个
escapePaddle()
函数,该函数基本上将球移动到不与球拍碰撞为止。然后我添加了所有桨碰撞测试条件。