I'm making a 2D Platform game and I'm having trouble with my collision detection. It doesn't seems to be framerate independent even though I used deltatime there.
The problem is that at 60fps, a collision is sometimes detected too early whereas at 500fps there's no problem (so it really seems like this isn't framerate-independent but I don't know why).
Here's a video of the game running at 60fps https://www.youtube.com/watch?v=P0hRJbw_gcw
And here's the code which is moving my character (I inspired myself about 2D Collision detection from the youtuber dermetfan):
/// Makes the entity jump
void Entity::jump()
{
m_onGround = false;
setVelocity(sf::Vector2f(getVelocity().x, -500));
}
/// What to do at each frame
void Entity::update(sf::Time dt)
{
if (getVelocity().y > 800)
{
setVelocity(sf::Vector2f(getVelocity().x, 800));
}
else
{
setVelocity(sf::Vector2f(getVelocity().x, getVelocity().y - m_map->getGravity()*dt.asSeconds()));
}
checkCollisions(dt);
}
/// Collision functions
void Entity::checkCollisions(sf::Time dt)
{
float oldX = getPosition().x;
float oldY = getPosition().y;
bool collX = false;
bool collY = false;
setPosition(getPosition().x + getVelocity().x*dt.asSeconds(), getPosition().y); // Setting the position on x
m_collisionIncrement = (getSize().x < getMap().TILE_SIZE) ? getSize().x / 2 : getMap().TILE_SIZE / 2;
if (getVelocity().x < 0)
collX = collidesLeft(); // Using collision tests
else if (getVelocity().x > 0)
collX = collidesRight();
if (collX){ // Testing if there was a collision
setPosition(oldX, getPosition().y); // Correct position
setVelocity(0, getVelocity().y*dt.asSeconds());
}
setPosition(getPosition().x, getPosition().y + getVelocity().y* dt.asSeconds()); // Setting the position on y
m_collisionIncrement = (getSize().y < getMap().TILE_SIZE) ? getSize().y / 2 : getMap().TILE_SIZE / 2;
if (getVelocity().y > 0)
{
collY = collidesBottom();
m_onGround = collY;
}
else if (getVelocity().y < 0)
{
collY = collidesTop();
}
if (collY){ // Testing if there was a collision
setPosition(getPosition().x, oldY);
setVelocity(getVelocity().x*dt.asSeconds(), 0);
}
}
bool Entity::collidesRight()
{
for (float step = 0; step <= getSize().y; step += m_collisionIncrement)
{
if (getMap().isCollideable(getPosition().x + getSize().x, getPosition().y + step))
return true;
}
return false;
}
bool Entity::collidesLeft()
{
for (float step = 0; step <= getSize().y; step += m_collisionIncrement)
{
if (getMap().isCollideable(getPosition().x, getPosition().y + step))
return true;
}
return false;
}
bool Entity::collidesTop()
{
for (float step = 0; step < getSize().x; step += m_collisionIncrement)
{
if (getMap().isCollideable(getPosition().x + step, getPosition().y))
return true;
}
return false;
}
bool Entity::collidesBottom()
{
for (float step = 0; step < getSize().x; step += m_collisionIncrement)
{
if (getMap().isCollideable(getPosition().x + step, getPosition().y + getSize().y))
return true;
}
return false;
}