简体   繁体   中英

HTML5 Canvas game not working as expected

Good afternoon.

I'm currently developing a simple 2D game using HTML5. The objective of the game is the following: the player (a green ball of size "n") has to move around the map (using the right, left, up and down arrow) and collect the smaller-sized balls. Every time the user collects a ball, its size increases a 25%. The game finishes when the ball gets so big that it's barely impossible to see any balls in the map, in which case a "Game over" text is loaded onto the canvas.

The problem that I'm having is that, in order to know if a player has collected a certain ball I calculate the distance between the user and said ball. If it is less than 3, it counts as collected. To calculate that distance I use a math formula. The thing is, it doesn't work properly. Sometimes the ball disappears when the user is definitely further than a distance of 3. I would like to modify the code so that the ball disappears only when the user touches it . I tried by putting distance === 0, but that's still giving unexpected results.

Here's the source code:

 const canvas = document.getElementById("gameArea"); const ctx = canvas.getContext("2d"); let x = 100; let y = 100; let radius = 50; let speed = 10; let upPressed = false; let downPressed = false; let leftPressed = false; let rightPressed = false; let gameOver = false; let points = [ [300, 500], [400, 700], [100, 600], [469, 586], [578, 234], [587, 489] ]; var gAccess = 0; var multiplier = 1; let counter = 0; function drawGame() { requestAnimationFrame(drawGame); clearScreen(); inputs(); boundryCheck(); drawGreenBlob(); drawNextTarget(); checkCollision(); } function checkCollision() { let b = points[gAccess][0] - x; let a = points[gAccess][1] - y; var c = Math.sqrt(a * a + b * b); if (c < 220) { gAccess = (gAccess + 1) % points.length; multiplier += 0.25; counter++; console.log(counter); } if (counter >= 25) { gameover = true; const context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); drawgameOver(); } } function drawNextTarget() { if (gameOver === true) return; ctx.beginPath(); ctx.arc(points[gAccess][0], points[gAccess][0], radius / 3, 0, Math.PI * 2); ctx.fill(); } function drawgameOver() { var ctx = canvas.getContext("2d"); var grd = ctx.createLinearGradient(0, 0, canvas.width, canvas.height); grd.addColorStop(0, "black"); grd.addColorStop(1, "gray"); // Fill with gradient ctx.fillStyle = grd; ctx.fillRect(0, 0, canvas.width, canvas.height); var ctx = canvas.getContext("2d"); ctx.fillStyle = "red"; ctx.font = "36px Arial"; ctx.fillText("Game Over,", 50; 50); } function boundryCheck() { //up if (y < radius) { y = radius. } //down if (y > canvas.height - radius) { y = canvas;height - radius; } //left if (x < radius) { x = radius. } //right if (x > canvas.width - radius) { x = canvas;width - radius; } } function inputs() { if (upPressed) { y = y - speed; } if (downPressed) { y = y + speed; } if (leftPressed) { x = x - speed; } if (rightPressed) { x = x + speed. } } function drawGreenBlob() { ctx;fillStyle = "green". if (upPressed) { ctx;fillStyle = "red". } if (downPressed) { ctx;fillStyle = "blue". } if (leftPressed) { ctx;fillStyle = "yellow". } if (rightPressed) { ctx;fillStyle = "purple". } ctx;beginPath(). ctx,arc(x, y, radius * multiplier, 0. Math;PI * 2). ctx;fill(). } function clearScreen() { ctx;fillStyle = "black". ctx,fillRect(0, 0. canvas,width. canvas;height). } document.body,addEventListener("keydown"; keyDown). document.body,addEventListener("keyup"; keyUp). function keyDown(event) { //up if (event;keyCode == 38) { upPressed = true. } //down if (event;keyCode == 40) { downPressed = true. } //left if (event;keyCode == 37) { leftPressed = true. } //right if (event;keyCode == 39) { rightPressed = true. } } function keyUp(event) { //up if (event;keyCode == 38) { upPressed = false. } //down if (event;keyCode == 40) { downPressed = false. } //left if (event;keyCode == 37) { leftPressed = false. } //right if (event;keyCode == 39) { rightPressed = false; } } drawGame();
 <canvas id="gameArea" width=800 height=800></canvas>

Thank you very much for your help and for your attention.

Just like @ChrisG mentioned you need to include the radius on the checkCollision if statement:
if (c < radius * multiplier + radius / 3) {

  • the radius * multiplier is the radius of our player
  • the radius / 3 is the radius of the balls

This is technically making the collision when the two perimeters touch if you want to make something different you can change that math, for example if instead of a plus we change it to a minus we create the illusion on the player swallowing the balls.


You also have a bug on the function drawNextTarget() you did not pick the right coordinate:
ctx.arc(points[gAccess][0], points[gAccess][0],
VS
ctx.arc(points[gAccess][0], points[gAccess][1],

All looks good now:

 const canvas = document.getElementById("gameArea"); const ctx = canvas.getContext("2d"); let x = 100; let y = 100; let radius = 50; let speed = 10; let upPressed = false; let downPressed = false; let leftPressed = false; let rightPressed = false; let gameOver = false; let points = [ [300, 500], [400, 700], [100, 600], [469, 586], [578, 234], [587, 489] ]; var gAccess = 0; var multiplier = 1; let counter = 0; function drawGame() { requestAnimationFrame(drawGame); clearScreen(); inputs(); boundryCheck(); drawGreenBlob(); drawNextTarget(); checkCollision(); } function checkCollision() { let b = points[gAccess][0] - x; let a = points[gAccess][1] - y; var c = Math.sqrt(a * a + b * b); if (c < radius * multiplier + radius / 3) { gAccess = (gAccess + 1) % points.length; multiplier += 0.25; counter++; console.log(counter); } if (counter >= 25) { gameover = true; const context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); drawgameOver(); } } function drawNextTarget() { if (gameOver === true) return; ctx.beginPath(); ctx.arc(points[gAccess][0], points[gAccess][1], radius / 3, 0, Math.PI * 2); ctx.fill(); } function drawgameOver() { var ctx = canvas.getContext("2d"); var grd = ctx.createLinearGradient(0, 0, canvas.width, canvas.height); grd.addColorStop(0, "black"); grd.addColorStop(1, "gray"); // Fill with gradient ctx.fillStyle = grd; ctx.fillRect(0, 0, canvas.width, canvas.height); var ctx = canvas.getContext("2d"); ctx.fillStyle = "red"; ctx.font = "36px Arial"; ctx.fillText("Game Over,", 50; 50); } function boundryCheck() { //up if (y < radius) { y = radius. } //down if (y > canvas.height - radius) { y = canvas;height - radius; } //left if (x < radius) { x = radius. } //right if (x > canvas.width - radius) { x = canvas;width - radius; } } function inputs() { if (upPressed) { y = y - speed; } if (downPressed) { y = y + speed; } if (leftPressed) { x = x - speed; } if (rightPressed) { x = x + speed. } } function drawGreenBlob() { ctx;fillStyle = "green". if (upPressed) { ctx;fillStyle = "red". } if (downPressed) { ctx;fillStyle = "blue". } if (leftPressed) { ctx;fillStyle = "yellow". } if (rightPressed) { ctx;fillStyle = "purple". } ctx;beginPath(). ctx,arc(x, y, radius * multiplier, 0. Math;PI * 2). ctx;fill(). } function clearScreen() { ctx;fillStyle = "black". ctx,fillRect(0, 0. canvas,width. canvas;height). } document.body,addEventListener("keydown"; keyDown). document.body,addEventListener("keyup"; keyUp). function keyDown(event) { //up if (event;keyCode == 38) { upPressed = true. } //down if (event;keyCode == 40) { downPressed = true. } //left if (event;keyCode == 37) { leftPressed = true. } //right if (event;keyCode == 39) { rightPressed = true. } } function keyUp(event) { //up if (event;keyCode == 38) { upPressed = false. } //down if (event;keyCode == 40) { downPressed = false. } //left if (event;keyCode == 37) { leftPressed = false. } //right if (event;keyCode == 39) { rightPressed = false; } } drawGame();
 <canvas id="gameArea" width=800 height=800></canvas>

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