130 lines
2.7 KiB
C
130 lines
2.7 KiB
C
#include "stddef.h"
|
|
#include "stdint.h"
|
|
|
|
#include "game.h"
|
|
#include "scheduler.h"
|
|
#include "shapes.h"
|
|
#include "canvas.h"
|
|
#include "../rgb-driver/colors.h"
|
|
#include "display.h"
|
|
|
|
|
|
#define GAME_CYCLE_TIME 100
|
|
#define GAMEOVER_DELAY 10
|
|
|
|
|
|
static uint8_t delayFactor(uint8_t level) {
|
|
return 11 - level;
|
|
}
|
|
|
|
typedef enum {
|
|
e_Phase_Game, e_Phase_GameOver
|
|
} phase_t;
|
|
|
|
typedef enum {
|
|
e_Start, e_NewStone, e_Down, e_DownDelay, e_ClearRows,
|
|
e_GameOver, e_GameOverFill, e_GameOverWipe, e_GameOverDelay
|
|
} state_t;
|
|
|
|
void gameExec(void *handle) {
|
|
static phase_t phase;
|
|
static state_t state = e_Start;
|
|
static uint8_t gameOverDelay;
|
|
static uint8_t rowIndex;
|
|
static uint8_t proceedDelay;
|
|
static uint8_t level;
|
|
static uint16_t score;
|
|
|
|
// --- engine begin -------------------------------------------------------
|
|
switch (state) {
|
|
// --- phase: game --------------------------------------------------------
|
|
case e_Start:
|
|
canvasClear();
|
|
level = 1;
|
|
score = 0;
|
|
displaySetValue(score);
|
|
phase = e_Phase_Game;
|
|
state = e_NewStone;
|
|
break;
|
|
|
|
case e_NewStone:
|
|
stoneCreate();
|
|
if (stoneDraw()) {
|
|
proceedDelay = delayFactor(level);
|
|
state = e_DownDelay;
|
|
} else {
|
|
state = e_GameOver;
|
|
}
|
|
break;
|
|
|
|
case e_DownDelay:
|
|
proceedDelay--;
|
|
if (proceedDelay == 0) {
|
|
rowIndex = 0;
|
|
state = e_ClearRows;
|
|
}
|
|
break;
|
|
|
|
case e_ClearRows:
|
|
state = e_Down;
|
|
break;
|
|
|
|
case e_Down:
|
|
if (! stoneMoveDown()) {
|
|
state = e_NewStone;
|
|
} else {
|
|
proceedDelay = delayFactor(level);
|
|
state = e_DownDelay;
|
|
}
|
|
break;
|
|
|
|
// --- phase: game over ---------------------------------------------------
|
|
case e_GameOver:
|
|
rowIndex = CANVAS_HEIGHT;
|
|
phase = e_Phase_GameOver;
|
|
state = e_GameOverFill;
|
|
break;
|
|
|
|
case e_GameOverFill:
|
|
rowIndex--;
|
|
canvasFillRow(rowIndex, _red);
|
|
if (rowIndex == 0) {
|
|
state = e_GameOverWipe;
|
|
}
|
|
break;
|
|
|
|
case e_GameOverWipe:
|
|
canvasWipeRow(rowIndex);
|
|
rowIndex++;
|
|
if (rowIndex == CANVAS_HEIGHT) {
|
|
gameOverDelay = GAMEOVER_DELAY;
|
|
state = e_GameOverDelay;
|
|
}
|
|
break;
|
|
|
|
case e_GameOverDelay:
|
|
gameOverDelay--;
|
|
if (gameOverDelay == 0) {
|
|
state = e_Start;
|
|
}
|
|
break;
|
|
}
|
|
// --- engine end ---------------------------------------------------------
|
|
|
|
canvasShow();
|
|
if (phase == e_Phase_Game) {
|
|
for (uint8_t r = 0; r < CANVAS_HEIGHT; r++) {
|
|
if (canvasIsRowFilled(r)) {
|
|
score += level;
|
|
displaySetValue(score);
|
|
canvasWipeRow(r);
|
|
canvasShow();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void gameInit() {
|
|
schAdd(gameExec, NULL, 0, GAME_CYCLE_TIME);
|
|
}
|