Home > front end >  HTML5 Canvas game not working as expected
HTML5 Canvas game not working as expected

Time:12-09

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.

CodePudding user response:

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>

  • Related