Search code examples
javascripthtml5-canvasjstilemap

How can I improve the collision detection in this vanilla JS TileMap game?


I am creating a simple JS canvas tile based game, I know it needs refactoring and updating of the syntax which I plan to do when I understand more about what is going on.

I have created the tile sizes dynamically which I think is why I am struggling. The collision detection isn't precise, and I am stumped as to making it more precise... By precise, I mean depending on the size of the display the collision is not hitting the right wall but just before it or after it for example.

Any help/advice, or pointing in the right direction, would be greatly appreciated.

this.moveUp = function(){
    if(this.y > gameCanvas.height / 8){
        this.y -= 7;
    }
};

this.moveDown = function(){
    if(this.y < gameCanvas.height - map.tSizeY * 1.5){
        this.y += 7;
    }
    
};

this.moveLeft = function(){
    if(this.x > gameCanvas.width / 8){
        this.x -= 7;
    }
};

this.moveRight = function(){
    if(this.x < gameCanvas.width - map.tSizeX * 1.25){
        this.x += 7;
    }
}

Github Repo: https://github.com/MrWalshy/jsLameTileGame

Example, Blue Square colliding with right wall


Solution

  • Set the players position touching the wall boundary rather than move the position by an arbitrary amount to an unknown position relative to the wall.

    You also need to include the size of the player in the calculations.

    I will assume that map.tSizeX and map.tSizeY are the tile sizes and that the player moves by a amount called this.speed (which I have added in example) and that the player has a size this.sizeX, this.sizeY (which I have also added in the example below)

    Example

    Move the player then resolve the collisions

    // assuming x,y is player top left
    
    this.sizeX = 7;    // size of player
    this.sizeY = 7;
    
    this.speed = 4;    // speed of player any value will do
    
    this.move = function(moveX, moveY) {
        const left = map.tSizeX;
        const top =  map.tSizeY;
        const right = gameCanvas.width - map.tSizeX - this.sizeX;   // Includes player size
        const bottom = gameCanvas.height - map.tSizeY - this.sizeY; // Includes player size
    
        this.x += moveX;
        this.y += moveY;
    
        if (this.x < left) { this.x = left }
        else if (this.x > right) { this.x = right }
    
        if (this.y < top) { this.y = top }
        else if (this.y > bottom) { this.y = bottom }
    }
    
    // Best would be to call this.move from the location you call the following functions. 
    // eg where you have the call this.moveUp() replace with this.move(0, -this.speed);
    // these are just here to make it compatible with any existing code.
    this.moveUp = function() { this.move(0, -this.speed) }
    this.moveDown = function() { this.move(0, this.speed) }
    this.moveLeft = function() { this.move(-this.speed, 0) }
    this.moveRight = function() { this.move(this.speed, 0) }