I'm trying to make a video game like ping pong.
I've drawn the paddle and the ball using the rect()
and arc()
functions respectively. These are drawn on the HTML <canvas>
element. Event handlers are attached to the document for the up and down arrow keys. These allow to be able to move the paddle. The ball's x and y coordinates are changed after 10 milliseconds using the setInterval()
function.
The issue I'm having is that sometimes the ball gets trapped in the paddle and starts moving in a zigzag fashion inside it.
How can I fix this? I want to change the x velocity of the ball as soon as it hits the front of the paddle and its y velocity if it hits its sides.
Here's my code:
<!-- 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);
});
答案 0 :(得分:0)
Maybe:
<!-- 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);
});
I added an escapePaddle()
function that basically moves the ball until it is not colliding with the paddle. Then I added to all the paddle collision test conditions.