Search code examples
javascriptcollision-detectionpixel

How to do pixel-perfect collision detection of a player and the walls (JavaScript Game)


I'm making a 2D game in JavaScript. For it, I need to be able to "perfectly" check collision between my players (the game has two players, open the picture please) and the walls! I mean, I have a function that actually works, but when I make them jump against the walls they pass through the walls and keep moving until they reach another area or even leave the canvas!

Also, if they are falling down and I make them collide with a wall, they just stop there which is also pretty bad! I really need help with that! It's a university project and I have to finish it really soon!

My game looks like this

The collision detection function I have is here:

    function blockRectangle (objA, objB) {
      var distX = (objA.x + objA.width / 2) - (objB.x + objB.width / 2);
      var distY = (objA.y + objA.height / 2) - (objB.y + objB.height / 2);

      var sumWidth = (objA.width + objB.width) / 2;
      var sumHeight = (objA.height + objB.height) / 2;

      if (Math.abs(distX) < sumWidth && Math.abs(distY) < sumHeight) {
        var overlapX = sumWidth - Math.abs(distX);
        var overlapY = sumHeight - Math.abs(distY);

        if (overlapX > overlapY) {
          objA.y = distY > 0 ? objA.y + overlapY : objA.y - overlapY;
        }
        else {
          objA.x = distX > 0 ? objA.x + overlapX : objA.x - overlapX;
        }
      }
    }

I did the walls with a maze and I'm using a for cycle to check the collisions with all of the walls I have saved in an array! As you can see here:

    for (var i in walls) {
      var wall = walls[i];
      
      if ((player.x < (wall.x + wall.width)) && ((player.x + player.width) > wall.x) && (player.y < (wall.y + wall.height)) && ((player.height + player.y) > wall.y)) {
        player.falling = false;
      }
      blockRectangle(player, wall);
    }

Please help me! Thank you all!


Solution

  • In your case I doubt a pixel perfect collision is required.

    You can maintain a boolean matrix to store the position of solid objects. Solid objects like walls or players. Then in every frame you can check if your player is trying to move to a position where there is a solid object, if it is then stop it. You don't have to create grid of width x height in pixels, but rather choose a largest block (single element in the grid) in which each solid object reasonably occupies most of the block.

    For example you can choose block size to be player_width / 2 x player_height /2.

    See following image with grid

    enter image description here

    Another simple way could be to just check the background pixel color. Since your game is simple, background and object colors are different. So you just have to check if the player is trying to move somewhere where pixel color is not of background, thus there is a solid object and player should stop. You don't have to test for a lot of pixels, just 1 pixel in the direction the player is trying to move. (1 for horizontal and 1 for vertical). This however can not be used if you don't have a clear background color. Background color here is kind of the boolean grid for us in the previous suggestion.