Search code examples
javascriptcollision-detectioncollisiondetection

How to add collision detection?


I'm using Javascript to make a simple game. I'm currently trying to add collision detection to the player, in order to make something happen when the player is within a certain range from a coin. I've tried subtracting the x and y coords of the player from the coin, I've also tried a for loop to detect the difference in proxomity between the coin and the player, and now I am trying to use the range() function. I have not been able to make any of these methods work in order to achieve my goal. Any help would be greatly appreciated.

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

//set player, background and coin info
const player = new Image();
player.src = "down.png";
const background = new Image();
background.src = "landscape.png";
const coin = new Image();
coin.src = "coin.png"

//create player
function drawSprite(img, sX, sY, sW, sH, dX, dY, dW, dH){
    ctx.drawImage(img, sX, sY, sW, sH, dX, dY, dW, dH);
}

//create score
var score = 0
function drawScore() {
    ctx.font = "10px Arial";
    ctx.fillStyle = "#FFFFFF";
    ctx.fillText("Score: " + score, 254, 12);
}

//controls
var xPos = 0;
var yPos = 0;
var playerWidth = 30;
var playerHeight = 52;
const speed = 6;
function movement(e){
    if (e.keyCode == 37){
      xPos -= speed;
      player.src = "left.png";
    }
    else if (e.keyCode == 38){
      yPos -= speed;
      player.src = "up.png";
    }
    else if (e.keyCode == 39){
      xPos += speed;
      player.src = "right.png"; 
    }
    else if (e.keyCode == 40){
      yPos += speed;
      player.src = "down2.png";
    }

    if (xPos < 0)
      xPos = 0;

    if (xPos > canvas.width - playerWidth)
      xPos = canvas.width - playerWidth;

    if (yPos < 0)
      yPos = 0;

    if (yPos > canvas.height - playerHeight)
      yPos = canvas.height - playerHeight;
}

document.onkeydown = movement;

function idle(){
    player.src = "down.png";
}

document.onkeyup = setInterval(idle, 0600);

//collision detection
if (player.xPos == range((coin.x - 6), (coin.x + 6))){
    //do something;
}

//animation
function animate(){
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
    ctx.drawImage(coin, 100, 50, 40, 35);
    drawSprite(player, 0, 0, 30, 52, xPos, yPos, 30, 52);
    drawScore();
    requestAnimationFrame(animate);
}
animate();


Solution

  • I do highly recommend you change your player and coin to objects and assign their parameters within those objects. This make doing this kind of stuff more dynamic and easier to understand.

    For your current code you can write something like

    function collision() {
      if (
        xPos + playerWidth < 100 ||
        xPos > 140 ||
        yPos + playerHeight < 50 ||
        yPos > 50 + 35
      ) {
        return;
      }
      console.log(true)
    }
    

    The number are the x, y, width, and height you assigned to the coin when it was drawn.

    A better way to write this code would be to have your player and coin as an object.

    let player = {
      x: 0,
      y: 0,
      width: 30,
      height: 52
    }
    
    let coin = {
      x: 100,
      y: 50,
      width: 40,
      height: 35,
    }
    

    As you build your game you will find it easier to access and change values this way. I am just simply console logging true when they collide.

    const canvas = document.getElementById("canvas");
    const ctx = canvas.getContext("2d");
    
    //set player, background and coin info
    const playerImg = new Image();
    playerImg.src =
      "https://www.pngitem.com/pimgs/m/157-1571473_pac-man-png-pacman-png-illustration-transparent-png.png";
    const background = new Image();
    background.src =
      "https://image.freepik.com/free-vector/desert-day-game-background_7814-292.jpg";
    const coinImg = new Image();
    coinImg.src = "https://image.pngaaa.com/391/204391-small.png";
    
    //create player
    function drawSprite(img, sX, sY, sW, sH, dX, dY, dW, dH) {
      ctx.drawImage(img, sX, sY, sW, sH, dX, dY, dW, dH);
    }
    
    //create score
    var score = 0;
    function drawScore() {
      ctx.font = "10px Arial";
      ctx.fillStyle = "#FFFFFF";
      ctx.fillText("Score: " + score, 254, 12);
    }
    
    //controls
    
    let player = {
      x: 0,
      y: 0,
      width: 30,
      height: 52
    };
    
    let coin = {
      x: 100,
      y: 50,
      width: 40,
      height: 35
    };
    
    const speed = 6;
    function movement(e) {
      if (e.keyCode == 37) {
        player.x -= speed;
        //  player.src = "left.png";
      } else if (e.keyCode == 38) {
        player.y -= speed;
        //  player.src = "up.png";
      } else if (e.keyCode == 39) {
        player.x += speed;
        //  player.src = "right.png";
      } else if (e.keyCode == 40) {
        player.y += speed;
        //  player.src = "down2.png";
      }
    
      if (player.x < 0) player.x = 0;
    
      if (player.x > canvas.width - player.width)
        player.x = canvas.width - player.width;
    
      if (player.y < 0) player.y = 0;
    
      if (player.y > canvas.height - player.height)
        player.y = canvas.height - player.height;
    }
    
    document.onkeydown = movement;
    
    function collision() {
      if (
        player.x + player.width < coin.x ||
        player.x > coin.x + coin.width ||
        player.y + player.height < coin.y ||
        player.y > coin.y + coin.height
      ) {
        return;
      }
      console.log(true);
    }
    
    //document.onkeyup = setInterval(idle, 0600);
    
    //animation
    function animate() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(background, 0, 0, canvas.width, canvas.height);
      ctx.drawImage(coinImg, coin.x, coin.y, coin.width, coin.height);
      drawSprite(
        playerImg,
        0,
        0,
        30,
        52,
        player.x,
        player.y,
        player.width,
        player.height
      );
      drawScore();
      collision();
      requestAnimationFrame(animate);
    }
    animate();
    <canvas id="canvas"></canvas>

    Ignore the pics. I just grabbed random ones form google.