8 Commits

Author SHA1 Message Date
ba4248ff24 flash 2024-05-17 16:08:10 +02:00
2cc5a6a4f3 changes 2024-05-05 21:48:20 +02:00
5c86d55458 dark mode 2024-05-05 17:24:29 +02:00
b9e5813223 flash 2024-05-04 12:58:02 +02:00
1b4a93d9e1 types bigger 2024-05-04 11:35:29 +02:00
30d50dcc5e seems to work but some unpleasant delays 2024-05-04 11:31:27 +02:00
1607dc62dd fix wrong wipe behaviour 2024-05-03 23:10:29 +02:00
78df7eee66 start new wipe approach 2024-05-03 16:21:20 +02:00
5 changed files with 91 additions and 50 deletions

View File

@ -1,3 +1,5 @@
// #define STATE_DEBUGGING
#include "stddef.h" #include "stddef.h"
#include "stdint.h" #include "stdint.h"
@ -12,35 +14,36 @@
#include "buttons.h" #include "buttons.h"
#define GAME_CYCLE_TIME 50 #define GAME_CYCLE_TIME 10
#define GAMEOVER_DELAY 10 #define GAMEOVER_DELAY 10
#define MAX_LEVEL 20 #define MAX_LEVEL 100
static uint8_t delayFactor(uint8_t level) { static uint16_t delayFactor(uint16_t level) {
return MAX_LEVEL + 1 - level; return MAX_LEVEL + 1 - level;
} }
typedef enum {
e_Phase_Game, e_Phase_GameOver
} phase_t;
typedef enum { typedef enum {
e_Start, e_NewStone, e_Down, e_DownDelay, e_ClearRows, e_Start, e_NewStone, e_Down, e_DownDelay,
e_ClearRowInit, e_ClearRowNext, e_ClearRowCheck, e_ClearRowFlash, e_ClearRowFlashDelay, e_ClearRowWipe,
e_GameOver, e_GameOverFill, e_GameOverWipe, e_GameOverDelay e_GameOver, e_GameOverFill, e_GameOverWipe, e_GameOverDelay
} state_t; } state_t;
void gameExec(void *handle) { void gameExec(void *handle) {
static phase_t phase;
static state_t state = e_Start; static state_t state = e_Start;
static uint8_t gameOverDelay; static uint8_t gameOverDelay;
static uint8_t rowIndex; static uint8_t rowIndex;
static uint8_t proceedDelay; static uint16_t proceedDelay;
static uint8_t level; static uint16_t level;
static uint16_t filledLines; static uint16_t filledLines;
static uint16_t score; static uint16_t score;
static bool newHighScoreAchieved; static bool newHighScoreAchieved;
static uint8_t clearCheckCnt;
#ifdef STATE_DEBUGGING
displaySetValue(state);
#endif
// --- engine begin ------------------------------------------------------- // --- engine begin -------------------------------------------------------
switch (state) { switch (state) {
// --- phase: game -------------------------------------------------------- // --- phase: game --------------------------------------------------------
@ -51,7 +54,6 @@ void gameExec(void *handle) {
filledLines = 0; filledLines = 0;
score = 0; score = 0;
newHighScoreAchieved = false; newHighScoreAchieved = false;
phase = e_Phase_Game;
state = e_NewStone; state = e_NewStone;
break; break;
@ -68,30 +70,77 @@ void gameExec(void *handle) {
case e_DownDelay: case e_DownDelay:
proceedDelay--; proceedDelay--;
if (proceedDelay == 0) { if (proceedDelay == 0) {
rowIndex = 0; state = e_Down;
state = e_ClearRows;
} }
break; break;
case e_ClearRows:
state = e_Down;
break;
case e_Down: case e_Down:
if (! stoneMoveDown()) { if (! stoneMoveDown()) {
soundCtrl(SOUND_LOCK); soundCtrl(SOUND_LOCK);
state = e_NewStone; stoneLock();
state = e_ClearRowInit;
} else { } else {
proceedDelay = delayFactor(level); proceedDelay = delayFactor(level);
state = e_DownDelay; state = e_DownDelay;
} }
break; break;
// --- phase: clear rows --------------------------------------------------
case e_ClearRowInit:
clearCheckCnt = 0;
state = e_ClearRowCheck;
break;
case e_ClearRowNext:
if (clearCheckCnt >= CANVAS_HEIGHT) {
state = e_NewStone;
} else {
clearCheckCnt += 1;
state = e_ClearRowCheck;
}
break;
case e_ClearRowCheck:
if (canvasIsRowFilled(clearCheckCnt)) {
score += level;
if (score > eepromReadHighScore()) {
newHighScoreAchieved = true;
eepromWriteHighScore(score);
}
state = e_ClearRowFlash;
} else {
state = e_ClearRowNext;
}
break;
case e_ClearRowFlash:
canvasFillRow(clearCheckCnt, _flash);
state = e_ClearRowFlashDelay;
break;
case e_ClearRowFlashDelay:
state = e_ClearRowWipe;
break;
case e_ClearRowWipe:
canvasWipeRow(clearCheckCnt);
filledLines += 1;
if ((filledLines > 0) && ((filledLines % 10) == 0)) {
if (level < MAX_LEVEL) {
level += 1;
}
soundCtrl(SOUND_FANFARE);
} else {
soundCtrl(SOUND_PLING);
}
state = e_ClearRowNext;
break;
// --- phase: game over --------------------------------------------------- // --- phase: game over ---------------------------------------------------
case e_GameOver: case e_GameOver:
soundCtrl(SOUND_GAMEOVER); soundCtrl(SOUND_GAMEOVER);
rowIndex = CANVAS_HEIGHT; rowIndex = CANVAS_HEIGHT;
phase = e_Phase_GameOver;
state = e_GameOverFill; state = e_GameOverFill;
break; break;
@ -121,42 +170,15 @@ void gameExec(void *handle) {
} }
// --- engine end --------------------------------------------------------- // --- engine end ---------------------------------------------------------
bool wipedLines = false;
canvasShow(); canvasShow();
if (phase == e_Phase_Game) {
for (uint8_t r = 0; r < CANVAS_HEIGHT; r++) {
if (canvasIsRowFilled(r)) {
score += level;
if (score > eepromReadHighScore()) {
newHighScoreAchieved = true;
eepromWriteHighScore(score);
}
displaySetValue(score);
canvasWipeRow(r);
canvasShow();
wipedLines = true;
filledLines += 1;
}
}
}
if (wipedLines) {
soundCtrl(SOUND_PLING);
}
if (wipedLines && (filledLines > 0) && ((filledLines % 10) == 0)) {
if (level < MAX_LEVEL) {
level += 1;
}
soundCtrl(SOUND_FANFARE);
}
#ifndef STATE_DEBUGGING
if (isGameActive()) { if (isGameActive()) {
displaySetValue(score); displaySetValue(score);
} else { } else {
displaySetValue(eepromReadHighScore()); displaySetValue(eepromReadHighScore());
} }
#endif
} }
void gameInit() { void gameInit() {

View File

@ -1,6 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include "shapes.h" #include "shapes.h"
#include "myrand.h" #include "myrand.h"
@ -19,6 +20,7 @@ typedef struct {
orientation_t orientation; orientation_t orientation;
uint8_t x; // column uint8_t x; // column
uint8_t y; // row uint8_t y; // row
bool locked;
} stone_t; } stone_t;
typedef struct { typedef struct {
@ -363,6 +365,11 @@ void stoneCreate() {
stone.orientation = e_0; stone.orientation = e_0;
stone.x = 4; stone.x = 4;
stone.y = 0; stone.y = 0;
stone.locked = false;
}
void stoneLock() {
stone.locked = true;
} }
uint8_t stoneIsValid() { uint8_t stoneIsValid() {
@ -376,6 +383,12 @@ static uint8_t move(direction_t direction) {
if (motions[stone.shape].nullRotation && (direction == e_RotateLeft || direction == e_RotateRight)) { if (motions[stone.shape].nullRotation && (direction == e_RotateLeft || direction == e_RotateRight)) {
return 1; return 1;
} }
// if the stone is already locked, do nothing
if (stone.locked) {
return 0;
}
// check whether the pixels to move to are free // check whether the pixels to move to are free
if (canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[0].x, if (canvasIsPixelFree(stone.x + motions[stone.shape].motion[direction][stone.orientation].set[0].x,
stone.y + motions[stone.shape].motion[direction][stone.orientation].set[0].y) && stone.y + motions[stone.shape].motion[direction][stone.orientation].set[0].y) &&

View File

@ -5,6 +5,7 @@
void shapesInit(); void shapesInit();
void stoneCreate(); void stoneCreate();
void stoneLock();
uint8_t stoneIsValid(); uint8_t stoneIsValid();
uint8_t stoneDraw(); uint8_t stoneDraw();
uint8_t stoneMoveDown(); uint8_t stoneMoveDown();

View File

@ -1,6 +1,6 @@
#include "colors.h" #include "colors.h"
#define DIMM_FACTOR 3 #define DIMM_FACTOR 5
.section ".rodata","a" .section ".rodata","a"
;; color definitions according to ;; color definitions according to
;; https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide/3-custom-color-mixing ;; https://learn.sparkfun.com/tutorials/lilypad-protosnap-plus-activity-guide/3-custom-color-mixing
@ -35,4 +35,8 @@ white:
.byte 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0 .byte 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0xff>>DIMM_FACTOR, 0
red: red:
.byte 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0 .byte 0xff>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0x00>>DIMM_FACTOR, 0
flash:
.byte 0xff, 0xff, 0xff, 0
;; .byte 0x00, 0x00, 0x00, 0
;; .byte 0x80>>3, 0x00>>3, 0xff>>3, 0

View File

@ -16,6 +16,7 @@
#define _yellow 0x0b #define _yellow 0x0b
#define _white 0x0c #define _white 0x0c
#define _red 0x0d #define _red 0x0d
#define _flash 0x0e