patternjavascriptMinor
2D tilemap collision method
Viewed 0 times
tilemapcollisionmethod
Problem
Is this the optimal method to check for collisions in a 2d-based game? I put together a working demo of 2D collisions here (WSAD to move, orange blocks collide).
I currently use the following code to check for collisions:
Update function:
This is called before movement is applied the the 'player'. The game is laid out as a 2D array of 1's and 0's for testing purposes.
Can I use fewer mathematical operations (less expensive for each tick) to check for a collision between the player and a '1' on my game grid?
I currently use the following code to check for collisions:
function checkmove(x, y) {
if(level[Math.floor(x/20)][Math.floor(y/20)] == 1 || level[Math.ceil(x/20)][Math.floor(y/20)] == 1 || level[Math.floor(x/20)][Math.ceil(y/20)] == 1 || level[Math.ceil(x/20)][Math.ceil(y/20)] == 1) {
return false;
} else {
return true;
}
}Update function:
function update(key) {
switch(key) {
case "W":
if(checkmove(pos.x, pos.y-2)) {
pos.y -= 2;
break;
} else {
break;
}
case "S":
if(checkmove(pos.x, pos.y+2)) {
pos.y += 2;
break;
} else {
break;
}
case "A":
if(checkmove(pos.x-2, pos.y)) {
pos.x -= 2;
break;
} else {
break;
}
case "D":
if(checkmove(pos.x+2, pos.y)) {
pos.x += 2;
break;
} else {
break;
}
default:
break;
}
}This is called before movement is applied the the 'player'. The game is laid out as a 2D array of 1's and 0's for testing purposes.
Can I use fewer mathematical operations (less expensive for each tick) to check for a collision between the player and a '1' on my game grid?
Solution
Before making this more efficient I'd suggest making it more readable:
in your
It would be much easier to read if you just move the break out of the if statement.
In another question I had suggested a bit shaving optimisation that might help here.
becomes
similarly adding almost 1 (
The
in your
switch statement you have break in both the true and else parts of your if statement.if(checkmove(pos.x, pos.y-2)) {
pos.y -= 2;
break;
} else {
break;
}It would be much easier to read if you just move the break out of the if statement.
if(checkmove(pos.x, pos.y-2)) {
pos.y -= 2;
}
break;In another question I had suggested a bit shaving optimisation that might help here.
Math.floor(number) is equivalent to number >> 0 this bit shifts the number by 0 bits and converts it to an integer. Math.floor(x/20)becomes
(x / 20) >> 0similarly adding almost 1 (
+ 1 - Number.EPSILON) and then flooring will give you the ceiling. (number + 1 - Number.EPSILON) >> 0The
checkmove() function calculates this multiple times on the one line. I'd rewrite it to calculate once.function checkmove(x, y) {
var floorX = (x/20) >> 0;
var floorY = (y/20) >> 0;
var ceilX = ((x/20) + 1 - Number.EPSILON) >> 0;
var ceilY = ((y/20) + 1 - Number.EPSILON) >> 0;
return level[floorX][floorY] == 1 ||
level[ceilX][floorY] == 1 ||
level[floorX][ceilY] == 1 ||
level[ceilX][ceilY] == 1;
}Code Snippets
if(checkmove(pos.x, pos.y-2)) {
pos.y -= 2;
break;
} else {
break;
}if(checkmove(pos.x, pos.y-2)) {
pos.y -= 2;
}
break;Math.floor(x/20)(x / 20) >> 0function checkmove(x, y) {
var floorX = (x/20) >> 0;
var floorY = (y/20) >> 0;
var ceilX = ((x/20) + 1 - Number.EPSILON) >> 0;
var ceilY = ((y/20) + 1 - Number.EPSILON) >> 0;
return level[floorX][floorY] == 1 ||
level[ceilX][floorY] == 1 ||
level[floorX][ceilY] == 1 ||
level[ceilX][ceilY] == 1;
}Context
StackExchange Code Review Q#60439, answer score: 8
Revisions (0)
No revisions yet.