I made a breakout clone a while back. My ball object had a single trajectory object (x,y) and a speed multiplier, and if I hit a boundary I would just invert the trajectory specific to the boundary orientation (If I hit the left or right wall, I would invert the x value in the trajectory and if I hit the top wall or the paddle I would invert the y value in the trajectory.
Ball going up and to the right trajectory: (1,1)
then after hitting top wall (1,-1)
then after hitting left wall (-1,-1)
then bouncing off paddle at bottom (-1,1)
void game::updateBallPath() // update ball in scene
{
if(gameBall->Moving()) // is the ball in motion?
{
if(gameBall->collisionBoundaryCheck(LEFT_WALL) || gameBall->collisionBoundaryCheck(RIGHT_WALL)) // have we hit a vertical boundary?
{
gameBall->flipX(); // we hit a vertical wall, invert x direction
return;
}
if(gameBall->collisionBoundaryCheck(TOP_WALL)) // have we hit the top boundary?
{
gameBall->flipY(); // we hit the roof, invert y direction
return;
}
if(gameBall->collisionBoundaryCheck(gamePaddle->Rect())) // did we hit the paddle?
{
if(gameBall->Right() < gamePaddle->Left() + half(gameBall->Width()) && gameBall->VelocityX() > 0.0) gameBall->flipX(); // hit left corner, ball coming right
if(gameBall->Left() > gamePaddle->Right() - half(gameBall->Width()) && gameBall->VelocityX() < 0.0) gameBall->flipX(); // hit right corner, ball coming left
gameBall->flipY();
return;
}
if(!gameBall->collisionBoundaryCheck(BRICK_AREA))
{
return;
} else {
if(brickWall->Remove(gameBall->Rect())) // we hit a brick
{
gameBall->flipY(); // invert y trajectory
}
}
}
}
Note that this code only updates the ball members for trajectory.
This is the collisionBoundaryCheck function: bool collisionBoundaryCheck(sf::FloatRect b) { return image.getGlobalBounds().intersects(b); }
This in the function inside the ball object that dealt with recalculating the ball position based on trajectory and speed: