snake_game.c: resolved bug where the head gets bitten by itself

This commit is contained in:
Christian Kroll 2014-09-04 02:15:30 +02:00
parent 126c1d0c44
commit 967ab9a05e
1 changed files with 19 additions and 6 deletions

View File

@ -12,6 +12,7 @@
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "../../config.h" #include "../../config.h"
#include "../../compat/pgmspace.h" #include "../../compat/pgmspace.h"
#include "../../pixel.h" #include "../../pixel.h"
@ -102,6 +103,8 @@ typedef struct snake_protagonist_s
uint8_t nHeadIndex; /**< Index of the head segment. */ uint8_t nHeadIndex; /**< Index of the head segment. */
uint8_t nTailIndex; /**< Index of the tail segment. */ uint8_t nTailIndex; /**< Index of the tail segment. */
snake_dir_t dir; /**< Direction of the snake. */ snake_dir_t dir; /**< Direction of the snake. */
bool bJoystickLocked; /**< Avoid double joytick queries
between movements. */
} snake_protagonist_t; } snake_protagonist_t;
@ -213,6 +216,7 @@ static void snake_initGameProtagonist(snake_protagonist_t *pprotSnake)
#endif #endif
pprotSnake->nTailIndex = 0; pprotSnake->nTailIndex = 0;
pprotSnake->nHeadIndex = 1; pprotSnake->nHeadIndex = 1;
pprotSnake->bJoystickLocked = false;
} }
#ifdef GAME_SNAKE #ifdef GAME_SNAKE
@ -229,10 +233,14 @@ static void snake_userControl(snake_protagonist_t *pprotSnake,
if (dirJoystick != SNAKE_DIR_NONE) if (dirJoystick != SNAKE_DIR_NONE)
{ {
// valid transitions can only be uneven // valid transitions can only be uneven
if ((pprotSnake->dir + dirJoystick) & 0x01) if (((pprotSnake->dir + dirJoystick) & 0x01) &&
!pprotSnake->bJoystickLocked)
{ {
pprotSnake->dir = dirJoystick; pprotSnake->dir = dirJoystick;
} }
// we query the joystick twice as fast as we move the snake, so we
// have to ensure that it does not bite its head with its head...uh
pprotSnake->bJoystickLocked = true;
} }
#else #else
if ((dirJoystick ^ *pdirLast) && (dirJoystick != SNAKE_DIR_NONE)) if ((dirJoystick ^ *pdirLast) && (dirJoystick != SNAKE_DIR_NONE))
@ -244,6 +252,9 @@ static void snake_userControl(snake_protagonist_t *pprotSnake,
pprotSnake->dir = (pprotSnake->dir + pprotSnake->dir = (pprotSnake->dir +
(dirJoystick == SNAKE_DIR_LEFT ? 3 : 1)) % 4u; (dirJoystick == SNAKE_DIR_LEFT ? 3 : 1)) % 4u;
} }
// we query the joystick twice as fast as we move the snake, so we
// have to ensure that it does not bite its head with its head...uh
pprotSnake->bJoystickLocked = true;
} }
*pdirLast = dirJoystick; *pdirLast = dirJoystick;
#endif #endif
@ -362,9 +373,9 @@ static void snake_initApples(snake_apples_t *pApples)
* Checks for an apple at a given position and removes it if there is one. * Checks for an apple at a given position and removes it if there is one.
* @param pApples The set of apples which are lying on the playing field. * @param pApples The set of apples which are lying on the playing field.
* @param pxHead The position to be tested. * @param pxHead The position to be tested.
* @return 0 if no apples were found, 1 otherwise * @return false if no apples were found, true otherwise
*/ */
static uint8_t snake_checkForApple(snake_apples_t *pApples, pixel pxHead) static bool snake_checkForApple(snake_apples_t *pApples, pixel pxHead)
{ {
for (uint8_t i = pApples->nAppleCount; i--;) for (uint8_t i = pApples->nAppleCount; i--;)
{ {
@ -376,10 +387,10 @@ static uint8_t snake_checkForApple(snake_apples_t *pApples, pixel pxHead)
pApples->aApples[i] = pApples->aApples[i + 1]; pApples->aApples[i] = pApples->aApples[i + 1];
} }
--pApples->nAppleCount; --pApples->nAppleCount;
return 1; return true;
} }
} }
return 0; return false;
} }
@ -419,7 +430,7 @@ void snake_engine(uint8_t bDemoMode)
clear_screen(0); clear_screen(0);
snake_drawBorder(); snake_drawBorder();
for (uint8_t nTick = 0; 1; nTick ^= SNAKE_COLOR_APPLE) for (uint8_t nTick = 0; true; nTick ^= SNAKE_COLOR_APPLE)
{ {
// determine new direction // determine new direction
#if defined ANIMATION_SNAKE && defined GAME_SNAKE #if defined ANIMATION_SNAKE && defined GAME_SNAKE
@ -439,6 +450,8 @@ void snake_engine(uint8_t bDemoMode)
snake_userControl(&protSnake, &dirLast); snake_userControl(&protSnake, &dirLast);
if (nTick) { if (nTick) {
#endif #endif
// release joystick lock
protSnake.bJoystickLocked = false;
// actually move head // actually move head
pixel pxOldHead = protSnake.aSegments[protSnake.nHeadIndex]; pixel pxOldHead = protSnake.aSegments[protSnake.nHeadIndex];