11#ifdef EMBED_DINO_IN_UI
2- #define setup dinoSetup
3- #define loop runChromeDino
4- extern LiquidCrystal lcd;
5- extern int read_LCD_buttons ();
2+ // When embedded in the menu UI:
3+ // - rename Arduino entry points so UI can call one frame at a time
4+ // - reuse UI's lcd and button reader
5+ #define setup dinoSetup
6+ #define loop runChromeDino
7+ class LiquidCrystal ; // forward declaration to avoid include order issues
8+ extern LiquidCrystal lcd;
9+ extern int read_LCD_buttons ();
610#endif
711
12+ /* Chrome Dino (16x2 LCD Keypad Shield)
13+ * - Dino pixels: UNCHANGED (CREA ELECTRONICA / Max Imagination two-cell style)
14+ * - Separate lanes: ground cactus (row 1) and bird (row 0)
15+ * - Score-based difficulty, clean Game Over
16+ * - Start/Restart with SELECT; Jump with UP or SELECT
17+ */
18+
819#include < LiquidCrystal.h>
9- const uint8_t DINO_BTN_RIGHT = 0 ;
10- const uint8_t DINO_BTN_UP = 1 ;
11- const uint8_t DINO_BTN_DOWN = 2 ;
12- const uint8_t DINO_BTN_LEFT = 3 ;
13- const uint8_t DINO_BTN_SELECT = 4 ;
14- const uint8_t DINO_BTN_NONE = 5 ;
20+
1521#ifndef EMBED_DINO_IN_UI
1622LiquidCrystal lcd (8 , 9 , 4 , 5 , 6 , 7 );
1723#endif
1824
19- // ---- Buttons via A0 ----
25+ // ---------- Button mapping (no BTN_* macros to avoid clashes) ----------
26+ #ifndef DINO_BTN_RIGHT
27+ const uint8_t DINO_BTN_RIGHT = 0 ;
28+ const uint8_t DINO_BTN_UP = 1 ;
29+ const uint8_t DINO_BTN_DOWN = 2 ;
30+ const uint8_t DINO_BTN_LEFT = 3 ;
31+ const uint8_t DINO_BTN_SELECT = 4 ;
32+ const uint8_t DINO_BTN_NONE = 5 ;
33+ #endif
34+
2035#ifndef EMBED_DINO_IN_UI
36+ // Local reader only in standalone builds
2137int read_LCD_buttons () {
2238 int adc = analogRead (A0);
23- if (adc < 50 ) return BTN_RIGHT ;
24- if (adc < 195 ) return BTN_UP ;
25- if (adc < 380 ) return BTN_DOWN ;
26- if (adc < 555 ) return BTN_LEFT ;
39+ if (adc < 50 ) return DINO_BTN_RIGHT ;
40+ if (adc < 195 ) return DINO_BTN_UP ;
41+ if (adc < 380 ) return DINO_BTN_DOWN ;
42+ if (adc < 555 ) return DINO_BTN_LEFT ;
2743 if (adc < 790 ) return DINO_BTN_SELECT;
28- return BTN_NONE ;
44+ return DINO_BTN_NONE ;
2945}
3046#endif
3147
32- static inline bool isJumpPressed (){ int b = read_LCD_buttons (); return (b == DINO_BTN_UP || b == DINO_BTN_SELECT); }
33-
34- // ---- Custom characters ----
35- // Index map: 0/1 right foot, 2/3 left foot, 4/5 idle, 6 cactus, 7 bird (animated)
48+ static inline bool isJumpPressed (){
49+ int b = read_LCD_buttons ();
50+ return (b == DINO_BTN_UP || b == DINO_BTN_SELECT);
51+ }
3652
37- // ---- Cactus ----
53+ // ---------- Custom characters (PRESERVED DINO PIXELS) ----------
54+ // CACTUS
3855byte CACTUS[8 ] = {
3956 B00100,
4057 B00101,
@@ -46,57 +63,47 @@ byte CACTUS[8] = {
4663 B00100
4764};
4865
49- // --- Dino style from CREA ELECTRONICA / Max Imagination (two-cell wide) ---
66+ // Dino (two-cell style) — DO NOT CHANGE
5067byte DINO_PARADO_PARTE_1[8 ] = {B00000, B00000, B00010, B00010, B00011, B00011, B00001, B00001};
5168byte DINO_PARADO_PARTE_2[8 ] = {B00111, B00111, B00111, B00100, B11100, B11100, B11000, B01000};
5269byte DINO_PIE_DERE_PART_1[8 ] = {B00000, B00000, B00010, B00010, B00011, B00011, B00001, B00001};
5370byte DINO_PIE_DERE_PART_2[8 ] = {B00111, B00111, B00111, B00100, B11100, B11100, B11000, B00000};
5471byte DINO_PIE_IZQU_PART_1[8 ] = {B00000, B00000, B00010, B00010, B00011, B00011, B00001, B00000};
5572byte DINO_PIE_IZQU_PART_2[8 ] = {B00111, B00111, B00111, B00100, B11100, B11100, B11000, B01000};
5673
57- // --- Upper obstacle: bird (animated wings on index 7) ---
58- byte BIRD_UP[8 ] = {
59- B00000,
60- B00001,
61- B00011,
62- B00111,
63- B01111,
64- B11111,
65- B00000,
66- B00000
67- };
68-
69- byte BIRD_DOWN[8 ] = {
70- B00000,
71- B10000,
72- B11000,
73- B11100,
74- B11110,
75- B11111,
76- B00000,
77- B00000
74+ // Bird (animated into slot 7 only)
75+ byte BIRD_UP[8 ] = {B00000, B00001, B00011, B00111, B01111, B11111, B00000, B00000};
76+ byte BIRD_DOWN[8 ] = {B00000, B10000, B11000, B11100, B11110, B11111, B00000, B00000};
77+
78+ // Character slots (lock dino pixels in 0..6; only slot 7 animates)
79+ enum : uint8_t {
80+ CH_DINO_L0 = 0 , // right-foot left cell
81+ CH_DINO_R0 = 1 , // right-foot right cell
82+ CH_DINO_L1 = 2 , // left-foot left cell
83+ CH_DINO_R1 = 3 , // left-foot right cell
84+ CH_DINO_IDLE_L = 4 ,
85+ CH_DINO_IDLE_R = 5 ,
86+ CH_CACTUS = 6 ,
87+ CH_BIRD = 7
7888};
7989
90+ // ---------- Game state ----------
8091enum State { START, RUN, GAMEOVER };
8192State state = START;
8293
8394// Dino placement (two cells wide)
8495const uint8_t DINO_COL1 = 1 ;
8596const uint8_t DINO_COL2 = 2 ;
86-
8797uint8_t dinoRow = 1 ; // 0 = top, 1 = bottom
8898bool footSwap = false ; // toggle run frames
8999
90100// Obstacles
91- int8_t cactusCol = 15 ;
92- bool cactusActive = false ;
93-
94- int8_t birdCol = 15 ;
95- bool birdActive = false ;
101+ int8_t cactusCol = 15 ; bool cactusActive = false ;
102+ int8_t birdCol = 15 ; bool birdActive = false ;
96103
97104// Difficulty/scaling
98105uint8_t cactusSpawnChance = 2 ; // out of 10
99- uint8_t birdSpawnChance = 0 ; // out of 10 (starts at 0 until score threshold )
106+ uint8_t birdSpawnChance = 0 ; // out of 10 (begins at 0)
100107
101108// Timing
102109unsigned long lastTick = 0 ;
@@ -111,7 +118,7 @@ const unsigned long jumpDuration = 520;
111118// Score
112119unsigned long score = 0 ;
113120
114- // ---- Drawing helpers ----
121+ // ---------- Helpers ------ ----
115122void drawScore () {
116123 lcd.setCursor (10 , 0 );
117124 char buf[7 ];
@@ -130,25 +137,25 @@ void clearDinoRow(uint8_t row) {
130137}
131138
132139void drawDino () {
133- // Alternate legs; during jump we can keep alternating for effect
140+ // Alternate legs; dino pixels fixed to slots 0..5
134141 bool right = footSwap;
135- uint8_t leftIdx = right ? 0 : 2 ; // left cell bitmap index group
136- uint8_t rightIdx = right ? 1 : 3 ; // right cell bitmap index group
137- lcd.setCursor (DINO_COL1, dinoRow); lcd.write (byte ( leftIdx) );
138- lcd.setCursor (DINO_COL2, dinoRow); lcd.write (byte ( rightIdx) );
142+ uint8_t leftIdx = right ? CH_DINO_L0 : CH_DINO_L1;
143+ uint8_t rightIdx = right ? CH_DINO_R0 : CH_DINO_R1;
144+ lcd.setCursor (DINO_COL1, dinoRow); lcd.write (leftIdx);
145+ lcd.setCursor (DINO_COL2, dinoRow); lcd.write (rightIdx);
139146}
140147
141148inline void spawnCactus (){ cactusCol = 15 ; cactusActive = true ; }
142149inline void eraseCactus (int8_t c){ if (c>=0 && c<16 ){ lcd.setCursor (c,1 ); lcd.print (' ' );} }
143- inline void drawCactusAt (int8_t c){ if (c>=0 && c<16 ){ lcd.setCursor (c,1 ); lcd.write (byte ( 6 ) ); } }
150+ inline void drawCactusAt (int8_t c){ if (c>=0 && c<16 ){ lcd.setCursor (c,1 ); lcd.write (CH_CACTUS ); } }
144151
145152inline void spawnBird (){ birdCol = 15 ; birdActive = true ; }
146153inline void eraseBird (int8_t c){ if (c>=0 && c<16 ){ lcd.setCursor (c,0 ); lcd.print (' ' );} }
147154inline void drawBirdAt (int8_t c){
148155 if (c>=0 && c<16 ){
149- lcd.createChar (7 , (footSwap ? BIRD_UP : BIRD_DOWN));
156+ lcd.createChar (CH_BIRD , (footSwap ? BIRD_UP : BIRD_DOWN)); // only slot 7 is updated
150157 lcd.setCursor (c,0 );
151- lcd.write (byte ( 7 ) );
158+ lcd.write (CH_BIRD );
152159 }
153160}
154161
@@ -164,7 +171,7 @@ void updateDifficulty() {
164171 else if (score < 20 ) { cactusSpawnChance = 3 ; birdSpawnChance = 2 ; }
165172 else if (score < 40 ) { cactusSpawnChance = 4 ; birdSpawnChance = 3 ; }
166173 else if (score < 60 ) { cactusSpawnChance = 5 ; birdSpawnChance = 4 ; }
167- else { cactusSpawnChance = 6 ; birdSpawnChance = 5 ; } // still out of 10
174+ else { cactusSpawnChance = 6 ; birdSpawnChance = 5 ; } // out of 10
168175}
169176
170177bool checkCollision () {
@@ -191,32 +198,29 @@ void resetGame(bool toStart) {
191198 footSwap = false ;
192199 jumping = false ;
193200 dinoRow = 1 ;
194- cactusActive = false ;
195- cactusCol = 15 ;
196- birdActive = false ;
197- birdCol = 15 ;
198-
199- if (toStart) {
200- lcd.setCursor (0 , 0 ); lcd.print (" CHROME DINO " );
201- lcd.setCursor (0 , 1 ); lcd.print (" >Press SELECT< " );
202- state = START;
203- } else {
201+ cactusActive = false ; cactusCol = 15 ;
202+ birdActive = false ; birdCol = 15 ;
203+
204+
204205 showHUD ();
205206 state = RUN;
206- }
207+
207208}
208209
210+ // ---------- Arduino entry points (renamed when embedded) ----------
209211void setup () {
210212 lcd.begin (16 , 2 );
211213 randomSeed (analogRead (A0));
212- // 0/1 = right foot; 2/3 = left foot; 4/5 = idle; 6 = cactus
213- lcd.createChar (0 , DINO_PIE_DERE_PART_1);
214- lcd.createChar (1 , DINO_PIE_DERE_PART_2);
215- lcd.createChar (2 , DINO_PIE_IZQU_PART_1);
216- lcd.createChar (3 , DINO_PIE_IZQU_PART_2);
217- lcd.createChar (4 , DINO_PARADO_PARTE_1);
218- lcd.createChar (5 , DINO_PARADO_PARTE_2);
219- lcd.createChar (6 , CACTUS);
214+
215+ // Load fixed glyphs (dino & cactus). Only bird slot is animated later.
216+ lcd.createChar (CH_DINO_L0, DINO_PIE_DERE_PART_1);
217+ lcd.createChar (CH_DINO_R0, DINO_PIE_DERE_PART_2);
218+ lcd.createChar (CH_DINO_L1, DINO_PIE_IZQU_PART_1);
219+ lcd.createChar (CH_DINO_R1, DINO_PIE_IZQU_PART_2);
220+ lcd.createChar (CH_DINO_IDLE_L, DINO_PARADO_PARTE_1);
221+ lcd.createChar (CH_DINO_IDLE_R, DINO_PARADO_PARTE_2);
222+ lcd.createChar (CH_CACTUS, CACTUS);
223+
220224 resetGame (true );
221225}
222226
@@ -255,10 +259,11 @@ void loop() {
255259 lastTick = now;
256260 footSwap = !footSwap;
257261
258- // Cactus movement
262+ // Difficulty
259263 updateDifficulty ();
264+
265+ // Cactus movement / spawn
260266 if (!cactusActive) {
261- // avoid spawning right on top of a fresh bird near the edge
262267 bool birdTooClose = (birdActive && birdCol > 11 );
263268 if (!birdTooClose && (random (0 , 10 ) < cactusSpawnChance || score == 0 )) spawnCactus ();
264269 } else {
@@ -273,9 +278,8 @@ void loop() {
273278 }
274279 }
275280
276- // Bird movement
281+ // Bird movement / spawn
277282 if (!birdActive) {
278- // Start birds only after a few points and keep spacing from fresh cactus
279283 bool cactusTooClose = (cactusActive && cactusCol > 11 );
280284 if (!cactusTooClose && score > 5 && random (0 , 10 ) < birdSpawnChance) spawnBird ();
281285 } else {
@@ -296,7 +300,7 @@ void loop() {
296300 // Collision
297301 if (checkCollision ()) {
298302 enterGameOver ();
299- return ;
303+ return ; // stop processing this frame
300304 }
301305 }
302306 } break ;
0 commit comments