Проблемы со временем в Allegro при реализации Pong

Я пытаюсь реализовать очень простую версию Pong, используя Allegro 4 и C++. Однако у меня возникла проблема, когда я использую механизм синхронизации в сочетании с вызовом rest(). Моя игра настроена для 2 игроков, и игрок выигрывает сет, как только игрок набирает 7 очков, а затем оба начинают с 0. Побеждает первый игрок, выигравший 2 сета. После того, как сет выигран, я показываю имя победителя и вызываю rest(2000), чтобы игроки могли видеть это сообщение. Однако после этого мяч, кажется, появляется из ниоткуда и приводит к автоматическому зачету одного из игроков в начале сета. После этого он возобновляет исходить из центра, как и положено. Этого не происходит, когда я удаляю механизм синхронизации или вызов rest().

Я пытался перенести обновление партитуры и наборов за пределы временного цикла, но это не сработало. Также не вызывается функция init() мяча сразу после вызова rest(). Был бы очень признателен за некоторую информацию о том, как решить проблему.

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;
  }
}

person theSuperiorVenacava    schedule 14.11.2012    source источник
comment
Allegro 4 в значительной степени устарел. Он больше не находится в стадии активной разработки, поскольку старый API был... ну, старым и не очень отражал более современные подходы. Я бы рекомендовал вам использовать Allegro 5.   -  person Cubic    schedule 15.11.2012
comment
Да, я знаю, но я уже довольно хорошо знаком с Allegro 4 и поэтому хочу сделать несколько игр, прежде чем я начну разбираться в Allegro 5.   -  person theSuperiorVenacava    schedule 15.11.2012


Ответы (1)


После rest(2000) сбросьте счетчик на 0. Во время этого отдыха он отсчитывает две секунды, поэтому после его завершения вы получите две секунды всплеска игрового процесса, пока он пытается наверстать упущенное.

Правильное исправление состоит в том, чтобы иметь лучше организованный код. Двухсекундный отдых действительно должен быть частью вашей обычной временной петли.

person Matthew    schedule 15.11.2012
comment
Большое спасибо. Уменьшение счетчика решило проблему. Но вызов rest() происходит внутри временного цикла, поскольку функция updateSets(), которая включает вызов rest(), находится внутри временного цикла. В любом случае, большое спасибо за вашу помощь. Наконец-то работает нормально. - person theSuperiorVenacava; 15.11.2012
comment
Я хочу сказать, что вы должны сделать что-то вроде remaining_pause = 240 * 2;, а затем внутри вашего цикла remaining_pause--. В режиме паузы вы не будете обрабатывать ввод, но по-прежнему будете обновлять графику как обычно и т. д. В небольшой игре все должно прекрасно вписываться в один игровой цикл без специальных обработчиков в различных функциях. - person Matthew; 15.11.2012