-
Notifications
You must be signed in to change notification settings - Fork 16
Intermediary Collision Detection
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
andoldX
to discover if we can increment the Y position of the player - Check the map position with
oldY
andnewX
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!
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!
- Next: Window Focus
- Previous: Intermediary Movement
Copyright © 2018 Vinícius Reif Biavatti
- Home
- RayTrancing
- Examples
- Basic Tutorial
- Intermediary Tutorial
- Advanced Tutorial