I'm trying to implement a very basic version of Pong using Allegro 4 and C++. I'm running into a problem however when I use the timing mechanism in conjunction with a rest() call. My game is set up for 2 players and a player wins a set once the player gets 7 points, and then both start over from 0. First player to win 2 sets wins. After a set is won, I display the name of the winner and call rest(2000) so that the players can see the message. However, after this, the ball seems to come out of nowhere and results in an automatic point for one of the players at the beginning of the set. After that, it resumes coming from the center as it's supposed to. This does not happen when I remove the timing mechanism or the rest() call.
I've tried moving the updation of the score and the sets outside the timing loop, but it doesn't work. Nor does calling the ball's init() function just after the rest() call. Would really appreciate some input as to how to fix the problem.
Here's the code. I've left out basic bits and the includes that don't affect the problem.
//includes...
Paddle p1, p2; //paddles for player 1, player 2 Ball b; //game ball int main() { setupGame(); //setup allegro and bitmaps init(); //initialize paddles and ball bool done = false; int win, game = 0; //game loop while(!done) { if(key[KEY_X]) //quick exit for debugging done = true; //timing loop while(counter > 0) { movePaddles(); moveAndCollideBall(); game = checkCondition(b, p1, p2); //check if either player 1 or player 2 has won a point updateScore(game); //update score updateSets(); //update set if score of either equals 7 counter --; } draw(); //draw paddles and ball displayScore(); blit(buffer, screen, 0, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); //draw buffer to screen clear_bitmap(buffer); //clear buffer for next iteration checkWinner(done); //check if either player has won 2 sets, exit loop if so } exitGame(); //clear bitmaps and exit allegro return 0; } END_OF_MAIN() //Returns 1 if player 1 has won a point, 2 for player 2 int checkCondition(Ball b, Paddle p1, Paddle p2) { if(b.x < p1.x) return 2; else if(b.x > p2.x+PADDLE_WIDTH) return 1; return 0; } //setup allegro and timing variables, load bitmaps void setupGame() { //allegro, screen setup, etc. //timing mechanism LOCK_VARIABLE(counter); LOCK_FUNCTION(increment_counter); install_int_ex(increment_counter, BPS_TO_TIMER(240)); srand(time(0)); //other setup stuff } //initialize paddles and ball void init() { p1.init(10, 210); p2.init(620, 210); b.init(); } //output score to buffer void displayScore() { textprintf_ex(buffer, gamefont, SCREEN_WIDTH/4, 10, WHITE, -1, "%i", p1.score); textprintf_ex(buffer, gamefont, SCREEN_WIDTH/2 - SCREEN_WIDTH/3, 450, WHITE, -1, "Sets: %i", p1.sets); textprintf_ex(buffer, gamefont, SCREEN_WIDTH/2 + SCREEN_WIDTH/4, 10, WHITE, -1, "%i", p2.score); textprintf_ex(buffer, gamefont, SCREEN_WIDTH/2 + SCREEN_WIDTH/6, 450, WHITE, -1, "Sets: %i", p2.sets); } //taking the winner of the point as parameter, update the corresponding player's score by 1, reset ball void updateScore(int game) { if(game > 0) {game == 1 ? ++p1.score : ++p2.score; b.init(); game = 0; } } //update no of sets won if either player has score of 7, reset scores void updateSets() { if(p1.score == 7 || p2.score == 7) { if(p1.score == 7) {p1.sets++; textprintf_ex(screen, gamefont, SCREEN_WIDTH/5, SCREEN_HEIGHT/2,WHITE, -1, "Player 1 wins the set!"); } else {p2.sets++; textprintf_ex(screen, gamefont, SCREEN_WIDTH/5, SCREEN_HEIGHT/2,WHITE, -1, "Player 2 wins the set!"); } p2.score = 0; p1.score = 0; rest(2000); //THIS SEEMS TO CAUSE THE PROBLEM, AFTER THE REST, THE BALL INSTEAD OF COMING FROM THE CENTER, QUICKLY COMES FROM SOMEWHERE CLOSE TO THE CORNER } } //check if either player has won 2 sets, if so set done to true void checkWinner(bool& done) { if(p1.sets == 2) {textprintf_ex(screen, gamefont, SCREEN_WIDTH/4, SCREEN_HEIGHT/2 + 30,WHITE, -1, "Player 1 wins!!"); rest(2000); done = true; } else if(p2.sets == 2) {textprintf_ex(screen, gamefont, SCREEN_WIDTH/4, SCREEN_HEIGHT/2 + 30,WHITE, -1, "Player 2 wins!!"); rest(2000); done = true; } }
After rest(2000)
, reset the counter to 0
. It is ticking away for two seconds during that rest, so after it's finished you'll get two seconds of a gameplay burst as it tries to catch up.
The proper fix is to have better organized code. The two second rest should really take place as part of your regular timing loop.