Search code examples
javascripthtmlhtml5-canvas2dcollision

How do I create 2d object collision from every side(top,left,bottom,right) properly


Just adding this for the people not looking to read a whole bunch of text, at least read this and look at the picture to understand my question;
I have collision set up between the "player" and "objects", so that when the "player" hits the "Left" of the "object" the "player" is put to the "Left" of the "object". (this is what i want). But I would like the player to be able to hit any side ("top","left","right","bottom") of the object and be placed appropriately. Block collision example image So looking at the image above, basically I am trying to create collision between the black square and the rest of the objects. The black square is the "player" object, the gray squares are numberd "wall" objects, and the red square is the "next level" object. I have accomplished this, but it is kind of messy and when it comes to moving the wall objects, the player collision no longer works as I would like it too. So anyway here is my "walls" codes:

var canvasWalls1 = document.getElementById('canvasWalls');
var ctxWalls1 = canvasWalls.getContext('2d');
var walls1 = new Walls1();
var imgSprite = new Image();
imgSprite.src = 'sprite.png';
imgSprite.addEventListener('load',init,false);

WallLeft.prototype.draw = function (){
    ctxWalls1.drawImage(imgSprite,this.srcX,this.srcY,this.width,this.height,this.drawX,this.drawY,this.width,this.height);
this.checkHitPlayer();
};
WallLeft.prototype.checkHitPlayer = function() {
if (this.drawX > player1.drawX &&
this.drawX <= player1.drawX + player1.width &&
this.drawY >= player1.drawY &&
this.drawY < player1.drawY + player1.height) {
player1.isUpKey = false;
player1.isDownKey = false;
player1.isRightKey = false;
player1.isLeftKey = false;
player1.drawX = this.drawX - player1.width - 0.05;
player1.drawY = this.drawY - 0.05;      }
}; 

I just copied the same code for wall1,2,3,.. etc. I'm sure there is a better way of doing this is if anybody could maybe suggest a better one? I'v tried drawing the same sprite in 2 different places, but can't figure out how to properly achieve this. The main reason I have different "walls" objects is because I need to draw the "player" object In a different position depending on where the "player" collides with the "wall" object. If the player flys in from the Left, player1.drawX = walls1.drawX - player width. But if the player flys in from the top, player1.drawY = walls1.drawY + player1.height. The reason I need all collisions to be able to happen on any "wall" object, Is because i re-use all of the "wall" objects whenever the "player" object reaches the "finish". If i knew of a better system, maybe I could continue using the collision system I have. anyways here is what happens when the "player" hits the "finish" object:

Finish.prototype.checkHitPlayer = function() {
if (this.drawX >= player1.drawX &&
this.drawX <= player1.drawX + player1.width &&
this.drawY >= player1.drawY &&
this.drawY <= player1.drawY + player1.height) {
increaseLevel();
} };
function increaseLevel() {
Level+=1;
if (Level===2) {
drawlevel2(); }
function drawlevel2()
{
player1.drawX = 288;
player1.drawY = 160;
walls1.drawX = 448;
walls1.drawY = 160;
walls2.drawX = 416;
walls2.drawY = 320;
walls3.drawX = 192;
walls3.drawY = 288;
finish1.drawX = 224
finish1.drawY = 96;
}

Again I have accomplished collision between the "player" and the "walls", but only by creating a separate function for every "wall", which doesn't work when I want to draw the "walls" in different places. I apologize if this seems like a lot to read, I tried to only include the relevant code. Any help/suggestions is much appreciated.


Solution

  • So I figured out a method that works for what I am trying to do. I can't use something like (player1.x >= wall1.x && player1.Y===walls1.Y) Or things similair because when it came down to having 4 objects on differents sides of the player... The player's X value would have to be higher than a wall and lower than another. Same as the Y value. (this also makes it kind of choppy.) Anyways here is what I used:

    Player.prototype.checkHitWall = function() {
    this.TopY = this.drawY; this.BottomY = this.drawY + this.height; this.LeftX = this.drawX; this.RightX = this.drawX + this.width;
    if (this.LeftX===walls1.x + walls1.width - 16 && this.drawY===walls1.y) //If player  flys in from the RIGHT of wall1
    {
    player1.isUpKey = false; player1.isDownKey = false; player1.isRightKey = false; player1.isLeftKey = false;
    upkey = false;
    rightkey = false;
    downkey = false;
    leftkey = true;
    this.drawX = walls1.x + walls1.width;
    this.drawY = walls1.y;
    

    Then I added functions to make the leftkey = false when the player hits a wall, or the game restarts. for anyone wondering about the -16, thats half the wall's width, so the player must hit the center of the wall in order to be placed next to the wall, because of the fps i have (im guessing anyway) You don't ever see the player go inside of the wall object, so it actually looks like the player hits the wall perfectly. The reason for the -16 is so that when the player tries to go left/right with a wall perfectly above the player, the wall doesn't detect a collision.