Question

I'm making a simple version of Tetris using Allegro 4 and C++. I've got most of the code in place and everything is working except user input. The keypresses are only being detected by the game on a few, random occasions. I fear it's a timing problem but I can't seem to catch it. Here are the relevant bits of code...

//Tetris.h


//Tetris class definition...

volatile long tet_counter = 0;

void increment_tet_counter()
{
  tet_counter++;
}
END_OF_FUNCTION(increment_tet_counter);

//this function gets called by the menu class when the user selects the Tetris option
//contains main loop, calls all other functions etc.
void Tetris::show(BITMAP* buffer, int& scr)
{
  LOCK_VARIABLE(tet_counter);
LOCK_FUNCTION(increment_tet_counter);
install_int_ex(increment_tet_counter, BPS_TO_TIMER(120));

while(tet_counter > 0)
{
   if(tet_scr == 1)  //welcome screen logic
   {
     if(key[KEY_E])
     {
       game_init();  //initialize game variables, etc.
       tet_scr = 2;  // go to main game screen
     }
     else if(key[KEY_I])   
     {
       tet_scr = 3;  //go to instructions screen
     }
     else if(key[KEY_Q])  //quit tetris
     {
       scr = 5;  //reference to a variable in the main.cpp, basically reverting the 
                 //main screen to the menu screen upon return
       return;
       }
   }  
   else if(tet_scr == 2)   //main game screen
   {
     if(cannot_move())   //managing auto-block movement, making the last line of blocks 
      {                  //permanent, etc... all of this works fine
       put_block();
       update_score(remove_filled_line());
       get_next_block();
      }
     move_block();  //handles auto-block movement and user input

   if(is_game_over())
    {textprintf_ex(screen, font, 500, 300, WHITE, -1, "GAME OVER!");
     rest(2000);
     tet_scr = 5;
     }

    if(key[KEY_P])  //pause game
      tet_scr = 4;

    if(key[KEY_Q])   //quit game
      tet_scr = 5;
   }

   //else ifs for other screens of the game... all work fine

  tet_counter--;                
}

//drawing functions ... work fine

}

//handles block movement... CPU-generated movement works, user input not detected mot of the time 
void Tetris::move_block()
{ 
 timer = (timer+1) % time_factor; 
 if(timer == time_factor-1)  //move block every couple of seconds
    block_y += 20;
 int k;
 if(keypressed())   //this is where the problem is (i think)
 {                  //the game only picks up the keypresses some of the times
 k = readkey();     //and sometimes when I keep the keypressed for a long time it work
  if(k >> 8 == KEY_DOWN)    //but it's very buggy and erratic and no way to predict
     block_y+=20;           //when it'll work and when it won't
  else if(k >> 8 == KEY_LEFT)
    block_x-=20;
  else if(k >> 8 == KEY_RIGHT)
    block_x+=20;
  else if(k >> 8 == KEY_UP)
    rotate_block();
 } 

 if(block_x < BOARD_X)
    block_x = BOARD_X;
 if(block_x > x_lim)
    block_x = x_lim;

 if(block_y < BOARD_Y)
    block_y = BOARD_Y;
 if(block_y > y_lim)
    block_y = y_lim;

}

//various other functions handling game logic/drawing etc are all working fine

I implemented Tetris exactly the same manner previously but without any overarching menu-class. Just run .exe and you are faced with the Tetris game. That time there were no such problems. So there is obviously something in conjunction with code outside the Tetris.h file that is mucking with the game. The only other place where I use 'keypressed()' is in the main like so...

while (counter > 0)
   {
         if(keypressed())
         {
           switch(readkey() >> 8)
           {
             case KEY_DOWN:
                  option++;
                  break;
             case KEY_UP:
                  option--;
                  break;
           }
         }

         if (option < 0)
             option = 5;
         else if (option > 5)
             option = 0;

         screen_handler(option, done);  //updates a variable using which the appropriate game is called in show_screen(), pong, breakout, snake are the other games

         counter--;
   }

   show_screen();  //this is where Tetris::show() is called
   blit(main_buffer, screen, 0, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
   clear_bitmap(main_buffer);

Any and all help to fix this mess would be greatly appreciated. Thanks.

Was it helpful?

Solution

My comment ended up solving the issue for the OP. Putting in answer form for future reference:

If that keyPressed() function in the main() is being called every frame by accident, perhaps it is making the second keyPressed() call malfunction in a sense. If a call to keyPressed looks for the last key pressed since the last call then the first call could be "receiving" that key and then the second call where you actually want to receive the key is getting nada. Sometimes though you are lucky and press that key between keyPressed() call number 1 and call number 2. If this is a tight loop this could be a short window which explains the behaviors you are getting with it "working" sometimes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top