Skip to content

Intermediary Collision Detection

Vinicius Reif Biavatti edited this page Oct 11, 2019 · 3 revisions

Collision Detection Improvement

In our movePlayer() function we detect the collision just checking the new player coordinates in relation of the map to discover if there is an wall in this new position. This is the simplest collision detection logic for the RayCasting. It is not good for the player because if the player collides in any wall position, he will be stopped. This method we will implement here will make the player slide in the walls. We will controll the X and Y player position separately. The logic is:

  • Check the map position with newY and oldX to discover if we can increment the Y position of the player
  • Check the map position with oldY and newX to discover if we can increment the X position of the player.

For example, if the player colides with some left wall, the oldY and newX checking will discover the wall, and the Y player position will be incremented only.

The other thing we will do in this step, is to create the player radius to define a min distance between the player and the wall. In this actual implementation, the distance between both is the minimum possible and it doesn't look good for playing.

The first step is create the new attribute called radius. We will use the value 10 (ten) because it is the value I liked, but you can change it to make it better to you. It is up to you, ok?

// Data
let data = {
    // ...
    player: {
        // ...
        radius: 10,
    // ...
    }
}

After it we will change the movePlayer() function to make the new check collision logic. The first thing is to create the checking variables. These checking variables will have the new position of the player multiplied with the radius of the player, to check the correct position so, in the movePlayer() function...

/**
 * Movement
 */
function movePlayer() {
    if(data.key.up.active) {
        let playerCos = Math.cos(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let playerSin = Math.sin(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let newX = data.player.x + playerCos;
        let newY = data.player.y + playerSin;
        let checkX = Math.floor(newX + playerCos * data.player.radius);
        let checkY = Math.floor(newY + playerSin * data.player.radius);
        // ...
    }
    // ...
}

Note: See that we will just need to correct the up and down movements. Left and right will just change the player angle and it doesn't need to have any collision detection logic.

After we have the checkX and checkY variables, we will check these positions separately to discover what we can increment for the player position.

/**
 * Movement
 */
function movePlayer() {
    if(data.key.up.active) {
        let playerCos = Math.cos(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let playerSin = Math.sin(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let newX = data.player.x + playerCos;
        let newY = data.player.y + playerSin;
        let checkX = Math.floor(newX + playerCos * data.player.radius);
        let checkY = Math.floor(newY + playerSin * data.player.radius);

        // Collision detection
        if(data.map[checkY][Math.floor(data.player.x)] == 0) {
            data.player.y = newY;
        }
        if(data.map[Math.floor(data.player.y)][checkX] == 0) {
            data.player.x = newX;
        } 
    }
    // ...
}

This is the implementation of the logic we checked before. Do the same thing for the down step but dont forget to minus the incrementer values (sin and cos) instead of plus it with the player position.

/**
 * Movement
 */
function movePlayer() {
    // ...
    if(data.key.down.active) {
        let playerCos = Math.cos(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let playerSin = Math.sin(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let newX = data.player.x - playerCos;
        let newY = data.player.y - playerSin;
        let checkX = Math.floor(newX - playerCos * data.player.radius);
        let checkY = Math.floor(newY - playerSin * data.player.radius);

        // Collision detection
        if(data.map[checkY][Math.floor(data.player.x)] == 0) {
            data.player.y = newY;
        }
        if(data.map[Math.floor(data.player.y)][checkX] == 0) {
            data.player.x = newX;
        } 
    }
    // ...
}

It is all! It was a little easy comparing with the other tutorials. Good luck!

Code

This is the new movePlayer() function code:

/**
 * Movement
 */
function movePlayer() {
    if(data.key.up.active) {
        let playerCos = Math.cos(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let playerSin = Math.sin(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let newX = data.player.x + playerCos;
        let newY = data.player.y + playerSin;
        let checkX = Math.floor(newX + playerCos * data.player.radius);
        let checkY = Math.floor(newY + playerSin * data.player.radius);

        // Collision detection
        if(data.map[checkY][Math.floor(data.player.x)] == 0) {
            data.player.y = newY;
        }
        if(data.map[Math.floor(data.player.y)][checkX] == 0) {
            data.player.x = newX;
        } 

    }
    if(data.key.down.active) {
        let playerCos = Math.cos(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let playerSin = Math.sin(degreeToRadians(data.player.angle)) * data.player.speed.movement;
        let newX = data.player.x - playerCos;
        let newY = data.player.y - playerSin;
        let checkX = Math.floor(newX - playerCos * data.player.radius);
        let checkY = Math.floor(newY - playerSin * data.player.radius);

        // Collision detection
        if(data.map[checkY][Math.floor(data.player.x)] == 0) {
            data.player.y = newY;
        }
        if(data.map[Math.floor(data.player.y)][checkX] == 0) {
            data.player.x = newX;
        } 
    }
    if(data.key.left.active) {
        data.player.angle -= data.player.speed.rotation;
        data.player.angle %= 360;
    }
    if(data.key.right.active) {
        data.player.angle += data.player.speed.rotation;
        data.player.angle %= 360;
    } 
}

Thanks! See you in the next tutorial!