I am trying to implement my own collision detection for a 2.5d voxel style platformer using Three.js. I have a problem with my implementation - if the framerate is too low or the character is moving too fast (usually when falling from high places) it falls right through. Is there a way to improve collision detection to be immune to problems like this?
This is how I detect collisions:
function render(){
requestAnimationFrame(render);
setVelocity();
animate();
manageCollisions();
renderer.render(scene, camera);
}
function manageCollisions(){
//Check every game object for collision -> TODO: implement broad phase when dealing with many objects
for(i=0; i < world.length; i++){
//Check for bottom collision <- ALWAYS check (unless moving up)
if(velocityY<0) {
if( (character.position.y - character.height/2) < (world[i].position.y + world[i].height/2)
&& (character.position.y + character.height/2) > (world[i].position.y + world[i].height/2)
&& (character.position.x + character.width/2) > (world[i].position.x - world[i].width/2)
&& (character.position.x - character.width/2) < (world[i].position.x + world[i].width/2))
{
console.log("bottom collision " + i);
velocityY=0;
jumped=false;
grounded = true;
character.position.y = world[i].position.y + world[i].height/2 + character.height/2 - 0.1; //-0.1 prevents shaking
} else {
grounded = false;
}
}
//Check for right collision <- ONLY if moving right (velocityX is positive)
if(velocityX > 0){
if( (character.position.y) < (world[i].position.y + world[i].height/2)
&& (character.position.y + character.height/2) > (world[i].position.y - world[i].height/2)
&& (character.position.x + character.width/2) > (world[i].position.x - world[i].width/2)
&& (character.position.x - character.width/2) < (world[i].position.x - world[i].width/2))
{
console.log("right collision" + i);
velocityX=0;
character.position.x = world[i].position.x - world[i].width/2 - character.width/2;
}
}
//check for left collision <- ONLY if moving left (velocityX is negative)
if(velocityX < 0){
if( (character.position.y) < (world[i].position.y + world[i].height/2)
&& (character.position.y + character.height/2) > (world[i].position.y - world[i].height/2)
&& (character.position.x - character.width/2) < (world[i].position.x + world[i].width/2)
&& (character.position.x + character.width/2) > (world[i].position.x + world[i].width/2))
{
console.log("left collision" + i);
velocityX=0;
character.position.x = world[i].position.x + world[i].width/2 + character.width/2;
}
}
//check for top collision <- ONLY if moving up (velocityY is positive)
if(velocityY > 0){
if( (character.position.y + character.height/2) > (world[i].position.y - world[i].height/2)
&& (character.position.y - character.height/2) < (world[i].position.y - world[i].height/2)
&& (character.position.x + character.width/2) > (world[i].position.x - world[i].width/2)
&& (character.position.x - character.width/2) < (world[i].position.x + world[i].width/2))
{
console.log("top collision" + i);
velocityY=0;
character.position.y = world[i].position.y - world[i].height/2 - character.height/2;
}
}
}
}