Pegaz Pegaz - 3 months ago 9
C++ Question

Controls not responding properly in snake

I'm writing a basic snake game as console application in c++. It's based on two-dimensional array of "tile" structures. My problem is: when pressing button to change the direction the snake is going it doesn't work immidiately but waits for next "tick" instead. The function that manages game itself looks like this:

void board::play()
{
display();
while(1)
{
getInput();
delay(0.5);
getInput();
resetCursor();
tick();
display();
}
}


display()
is pretty self-explanatory, displays whole board in console window.

delay()
as well, it's function which gets number of seconds as a float and waits this much time before proceeding
getInput()
looks like this:

void board::getInput()
{
int input;
if(kbhit())
{
input=getch();
if(input==KEY_LEFT)
turnLeft();
if(input==KEY_RIGHT)
turnRight();
if(input==KEY_UP)
turnUp();
if(input==KEY_DOWN)
turnDown();
}
}


resetCursor()
sets the cursor to 0,0 coordinate so each time the board will write over itself and not one under another

And now for the game itself: class
board
contains amongst others field
int direction
. The tiles themselves contain a counter, which counts down by 1 with each move, and when reaches 0 the tile becomes empty. If the counter is equal to the lenght of a snake the tile is considered a head.
The
tick()
function does just that: decreases all counters by 1, remembers where head was and spawns a new head in the field next to previous one in direction specified. It looks like this:

void board::tick()
{
int posx, posy;
for(int i=0; i<boardSize; i++)
{
for(int j=0; j<boardSize; j++)
{
if(tab[i][j].getCounter()==lenght)
{
posx=i;
posy=j;
}
tab[i][j].tick();
}
}
switch(direction)
{
case UP: tab[posx-1][posy].addSnake(lenght);
break;
case DOWN: tab[posx+1][posy].addSnake(lenght);
break;
case LEFT: tab[posx][posy-1].addSnake(lenght);
break;
case RIGHT: tab[posx][posy+1].addSnake(lenght);
break;

}
}


Problem is, as stated before, that game waits one "tick" before changing direction when it should do so immediately after pressing associated button, e.g. when turning from UP to LEFT it does one more move up and only after that moves left.

Answer

Solved.

Turns out there were too many things put into buffer, as the program started going crazy if you mashed controls randomly during waiting time. I solved it by replacing

if(kbhit())
{
    input=getch();
    //reactions
}

with

while(kbhit())
{
    input=getch();
}
//reactions

It now checks every signal in the buffer and reacts only to the last one, so the delay is eliminated.