简体   繁体   中英

Javascript Canvas Breakout Collision Detection Issue

I'm coding a breakout game in JavaScript and have an issue with the paddle collision detection.

On running the program, all collisions of the ball with the paddle are fine until the first time it misses. At this point the program sets the ball back in the center and sends it off again. However this time around the paddle surface is being ignored yet the code beyond that point to determine the ball has left the boundary is working as when the ball leaves the screen the next time it is still reset.

There is a jsFiddle of the code is here .

I've tried several if/else variations to mend it but can't figure out why the code is ignored at a later point.

Code snippet

 var canvas = document.querySelector("canvas"); var surface = canvas.getContext("2d"); var button = document.querySelector("button"); button.addEventListener("click", playGame, false); //Game results var score = 0; var lives = 4; var gameOver = false; //Create a ball object var ball = { radius: 10, x: canvas.height - 30, y: canvas.width/2, dx: 3, dy: -3, }; //Create a paddle object var paddle = { width: 75, height: 10, x: (canvas.width -75)/2, y: canvas.height - 10 }; //add key controls document.addEventListener("keydown", keydownHandler, false); document.addEventListener("keyup", keyupHandler, false); var moveLeft = false; var moveRight = false; function playGame() { requestAnimationFrame (playGame, canvas); render(); moveBall(); movePaddle(); } function render() { //Clear the canvas surface surface.clearRect(0,0,canvas.width,canvas.height); drawBall(); drawPaddle(); //Keep ball within boundary if(ball.x + ball.dx < 0 + ball.radius || ball.x + ball.dx > canvas.width - ball.radius ) { //Reverse the direction of the ball in x direction ball.dx = -ball.dx; } if(ball.y + ball.dy < 0 + ball.radius ) { //Reverse the direction of the ball in the y direction ball.dy = -ball.dy; } //Make ball bounce of top surface of paddle if(Math.floor(ball.y) === Math.floor(canvas.height - ball.radius - paddle.height) && ball.x + ball.radius > paddle.x && ball.x - ball.radius < paddle.x + paddle.width) { //ball has hit paddle ball.dy = -ball.dy; } if (ball.y + ball.dy > canvas.height + ball.radius) { //ball has gone outside area console.log('Out of Bounds'); //Set new ball position ball.y = canvas.height -30; ball.x = canvas.width/2; ball.dy = -ball.dy; } } function drawBall() { surface.beginPath(); surface.arc(ball.x,ball.y,ball.radius,0, Math.PI*2); surface.fillStyle = "yellow"; surface.fill(); surface.closePath(); } function drawPaddle() { surface.beginPath(); surface.rect(paddle.x, paddle.y, paddle.width, paddle.height); surface.fillStyle = "lightblue"; surface.fill(); surface.closePath(); } function movePaddle() { if (moveLeft && paddle.x > 0) { paddle.x -= 7; } if (moveRight && paddle.x + paddle.width < canvas.width) { paddle.x +=7; } } function moveBall() { //Give ball a starting velocity ball.x += ball.dx; ball.y += ball.dy; } function keydownHandler(event) { if(event.keyCode === 37) { moveLeft = true; } if(event.keyCode === 39) { moveRight = true; } } function keyupHandler(event) { if(event.keyCode === 37) { moveLeft = false; } if(event.keyCode === 39) { moveRight = false; } } function scoreboard() { surface.font = "20px Arial"; surface.fillStyle = "#00FF00"; surface.fillText("Score: " + score, 8, 20); surface.fillText("Lives: " + lives, 730, 20); } 
 canvas { background-color: #000; border: 3px solid green; } 
 <canvas id="myCanvas" width="800" height="480"></canvas> <button>Run</button> 

I got there in the end.

My code was expecting an exact match of the ball surface on the paddle surface. However, as the increments are 3 pixels at a time there is a point where the ball surface is just above the paddle surface and on the next frame it is just beyond it.

I fixed by amending to a "greater than paddle surface and less than canvas area" condition.

Updated fiddle https://jsfiddle.net/Geejayz/bnLbzgg0/6/ :

 var canvas = document.querySelector("canvas"); var surface = canvas.getContext("2d"); var button = document.querySelector("button"); button.addEventListener("click", playGame, false); //Game results var score = 0; var lives = 4; var gameOver = false; //Create a ball object var ball = { radius: 10, x: canvas.height - 30, y: canvas.width/2, dx: 3, dy: -3, }; //Create a paddle object var paddle = { width: 75, height: 10, x: (canvas.width -75)/2, y: canvas.height - 10 }; //add key controls document.addEventListener("keydown", keydownHandler, false); document.addEventListener("keyup", keyupHandler, false); var moveLeft = false; var moveRight = false; function playGame() { requestAnimationFrame (playGame, canvas); render(); moveBall(); movePaddle(); } function render() { //Clear the canvas surface surface.clearRect(0,0,canvas.width,canvas.height); drawBall(); drawPaddle(); //Keep ball within boundary if(ball.x + ball.dx < 0 + ball.radius || ball.x + ball.dx > canvas.width - ball.radius ) { //Reverse the direction of the ball in x direction ball.dx = -ball.dx; } if(ball.y + ball.dy < 0 + ball.radius ) { //Reverse the direction of the ball in the y direction ball.dy = -ball.dy; } //Make ball bounce of top surface of paddle if(ball.y > canvas.height - ball.radius - paddle.height && ball.y < canvas.height - ball.radius && ball.x + ball.radius > paddle.x && ball.x - ball.radius < paddle.x + paddle.width) { //ball has hit paddle ball.dy = -ball.dy; } if (ball.y + ball.dy > canvas.height + ball.radius) { //ball has gone outside area console.log('Out of Bounds'); //Set new ball position ball.y = canvas.height -30; ball.x = canvas.width/2; ball.dy = -ball.dy; } } function drawBall() { surface.beginPath(); surface.arc(ball.x,ball.y,ball.radius,0, Math.PI*2); surface.fillStyle = "yellow"; surface.fill(); surface.closePath(); } function drawPaddle() { surface.beginPath(); surface.rect(paddle.x, paddle.y, paddle.width, paddle.height); surface.fillStyle = "lightblue"; surface.fill(); surface.closePath(); } function movePaddle() { if (moveLeft && paddle.x > 0) { paddle.x -= 7; } if (moveRight && paddle.x + paddle.width < canvas.width) { paddle.x +=7; } } function moveBall() { //Give ball a starting velocity ball.x += ball.dx; ball.y += ball.dy; } function keydownHandler(event) { if(event.keyCode === 37) { moveLeft = true; } if(event.keyCode === 39) { moveRight = true; } } function keyupHandler(event) { if(event.keyCode === 37) { moveLeft = false; } if(event.keyCode === 39) { moveRight = false; } } function scoreboard() { surface.font = "20px Arial"; surface.fillStyle = "#00FF00"; surface.fillText("Score: " + score, 8, 20); surface.fillText("Lives: " + lives, 730, 20); } 
 canvas { background-color: #000; border: 3px solid green; } 
 <canvas id="myCanvas" width="800" height="480"></canvas> <button>Run</button> 

(Also thanks to AgataB and zow for the edits - it has been a while since I posted. I probably still haven't gotten this post perfect either.).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM