I am writing a program in C using OpenGL to draw elements. This is a simple 2D game, in which a square is supposed to change its direction once it hits one of the walls, i.e. the bounds of the screen. To set up the bounding box, I have made tiny squares spanning the length of the sides. My coordinate system is from -1 to 1 in all directions.
Sometimes it all works, but eventually the moving square will go outside the window. It seems my program recognizes the collision, but still nothing stops it from moving past the bounds. Here is my check for collision:
bool checkCollisionRectRect(Rectangle* p1, Rectangle* p2) {
float eps = 0.005;
RectHitbox* rect1 = (RectHitbox*)p1->getHitbox();
RectHitbox* rect2 = (RectHitbox*)p2->getHitbox();
if (rect1->x < rect2->x rect2->w eps &&
rect1->x rect1->w eps > rect2->x &&
rect1->y < rect2->y rect2->h eps &&
rect1->h rect1->y eps > rect2->y) {
return true;
}
return false;
}
This is how collisions are checked for, for the time being for every single frame:
void Game::handleBallWallCollision() {
bool collisionX = checkCollision(this->ball, this->boundBoxes->at(0)) ||
checkCollision(this->ball, this->boundBoxes->at(1));
bool collisionY = checkCollision(this->ball, this->boundBoxes->at(2)) ||
checkCollision(this->ball, this->boundBoxes->at(3));
if (collisionX) { // Collision X
ball->flipDirectionX();
} else if (collisionY) { // Collision Y
ball->flipDirectionY();
}
}
In order to avoid floating point errors, I have added the eps value. Still I have no idea what is wrong, and why the square sometimes jumps past the bounds. Has anyone encountered this problem before, and possibly solved it by some clever means?
CodePudding user response:
You don't need an epsilon. In fact, it is the source of the error.
if (collisionX) { // Collision X
ball->flipDirectionX();
When the ball gets to move slow enough, once it enters the area of epsilon, it will just bounce left and right every frame.
But just removing the epsilon will not be enough to fix the issue. What you need is:
if (collisionXLeftSide) { // Collision X on the left
ball->goRight();
You need to be explicit. If the collision is on the left side, you need to force the ball to go right, and vice versa. That way, due to floating point errors, if you measure two collisions for the same wall, your ball still bounce to the correct side.