let this arrow be the snake heading to right direction while game is running:
---->
the problem is if i press up-key and manage to press left-key very quickly after that , then the snake take this u-turn and hit itself:
---->-<
game over.
looks like the snake is skipping one of the iterations of the game and doesn't move at all.
it means on one iteration of game loop the variable dir sets it's value to direction_up but switch statement doesn't execute. so theres a point where "dir = direction_up" but snake is really heading right-direction.
i want to prevent the snake from taking u-turn. the snake should move in one direction on each frame(each iteration of game loop).
i want turn keypresses to be ignored if snake hasn't moved at least 1 tile since previous turn?
this enum is outside of main loop:
enum directions
{
direction_default,
direction_down,
direction_left,
direction_right,
direction_up,
direction_total
};
handling event inside game loop:
while(SDL_PollEvent(&e))
{
//poll for currently pending events
if(e.type == SDL_QUIT) {quit = 1;}
if(e.type == SDL_KEYDOWN)
{
if(e.key.keysym.sym == SDLK_DOWN && dir != direction_up)
dir = direction_down;
if(e.key.keysym.sym == SDLK_UP && dir != direction_down)
dir = direction_up;
if(e.key.keysym.sym == SDLK_LEFT && dir != direction_right)
dir = direction_left;
if(e.key.keysym.sym == SDLK_RIGHT && dir != direction_left)
dir = direction_right;
}
}
this switch statement for moving:
switch(dir)
{
//check which direction snake is moving
case direction_down:
head.y += 10;
break;
case direction_up:
head.y -= 10;
break;
case direction_left:
head.x -= 10;
break;
case direction_right:
head.x += 10;
break;
}
Solving any problem starts with clear and precise description of desired behaviour. How about this: "i want turn keypresses to be ignored if snake hasn't moved at least 1 tile since previous turn"? When stated that way, it should be obvious how to implement it.
You could accumulate distance your snake travelled without changing its direction, e.g.:
int moved_since_last_turn = 0;
// ...
while(SDL_PollEvent(&e))
{
//poll for currently pending events
if(e.type == SDL_QUIT) {quit = 1;}
if(e.type == SDL_KEYDOWN)
{
if(moved_since_last_turn == 0) { continue; }
// set new direction to ndir and compare it with old direction later
int ndir = dir;
if(e.key.keysym.sym == SDLK_DOWN && dir != direction_up)
ndir = direction_down;
if(e.key.keysym.sym == SDLK_UP && dir != direction_down)
ndir = direction_up;
if(e.key.keysym.sym == SDLK_LEFT && dir != direction_right)
ndir = direction_left;
if(e.key.keysym.sym == SDLK_RIGHT && dir != direction_left)
ndir = direction_right;
if(dir != ndir)
{
// direction changed, reset move counter
dir = ndir;
moved_since_last_turn = 0;
}
}
}
// ...
moved_since_last_turn += 1;
switch(dir)
{
//check which direction snake is moving
// ...
}
As a side note, I'd suggest untying your logic from frame rate. Oftentimes you need to redraw in much higher rate than your logic step, e.g. when OS tells you your previous image is no longer valid and you have to redraw, or when you have some animation and/or effects that you need to redraw at righer rate while snake's logic remains fixed step, intedepndent on how often you draw. It also simplifies things quite a bit.