Components and supplies
Rotary potentiometer (generic)
Buzzer
Analog joystick (Generic)
Breadboard (generic)
USB-A to B Cable
Jumper wires (generic)
Arduino UNO
Standard LCD - 16x2 White on Blue
Apps and platforms
Arduino IDE
Project description
Code
The code
arduino
1#include <LiquidCrystal.h> 2 3#define PIN_BUTTON 2 4#define PIN_AUTOPLAY 1 5#define PIN_BUZZER 8 6#define PIN_READWRITE 10 7#define PIN_CONTRAST 12 8 9#define SPRITE_RUN1 1 10#define SPRITE_RUN2 2 11#define SPRITE_JUMP 3 12#define SPRITE_JUMP_UPPER '.' // Use the '.' character for the head 13#define SPRITE_JUMP_LOWER 4 14#define SPRITE_TERRAIN_EMPTY ' ' // User the ' ' character 15#define SPRITE_TERRAIN_SOLID 5 16#define SPRITE_TERRAIN_SOLID_RIGHT 6 17#define SPRITE_TERRAIN_SOLID_LEFT 7 18 19#define HERO_HORIZONTAL_POSITION 1 // Horizontal position of hero on screen 20 21#define TERRAIN_WIDTH 16 22#define TERRAIN_EMPTY 0 23#define TERRAIN_LOWER_BLOCK 1 24#define TERRAIN_UPPER_BLOCK 2 25 26#define HERO_POSITION_OFF 0 // Hero is invisible 27#define HERO_POSITION_RUN_LOWER_1 1 // Hero is running on lower row (pose 1) 28#define HERO_POSITION_RUN_LOWER_2 2 // (pose 2) 29 30#define HERO_POSITION_JUMP_1 3 // Starting a jump 31#define HERO_POSITION_JUMP_2 4 // Half-way up 32#define HERO_POSITION_JUMP_3 5 // Jump is on upper row 33#define HERO_POSITION_JUMP_4 6 // Jump is on upper row 34#define HERO_POSITION_JUMP_5 7 // Jump is on upper row 35#define HERO_POSITION_JUMP_6 8 // Jump is on upper row 36#define HERO_POSITION_JUMP_7 9 // Half-way down 37#define HERO_POSITION_JUMP_8 10 // About to land 38 39#define HERO_POSITION_RUN_UPPER_1 11 // Hero is running on upper row (pose 1) 40#define HERO_POSITION_RUN_UPPER_2 12 // (pose 2) 41 42LiquidCrystal lcd(11, 9, 6, 5, 4, 3); 43static char terrainUpper[TERRAIN_WIDTH + 1]; 44static char terrainLower[TERRAIN_WIDTH + 1]; 45static bool buttonPushed = false; 46 47void initializeGraphics(){ 48 static byte graphics[] = { 49 // Run position 1 50 B01100, 51 B01100, 52 B00000, 53 B01110, 54 B11100, 55 B01100, 56 B11010, 57 B10011, 58 // Run position 2 59 B01100, 60 B01100, 61 B00000, 62 B01100, 63 B01100, 64 B01100, 65 B01100, 66 B01110, 67 // Jump 68 B01100, 69 B01100, 70 B00000, 71 B11110, 72 B01101, 73 B11111, 74 B10000, 75 B00000, 76 // Jump lower 77 B11110, 78 B01101, 79 B11111, 80 B10000, 81 B00000, 82 B00000, 83 B00000, 84 B00000, 85 // Ground 86 B11111, 87 B11111, 88 B11111, 89 B11111, 90 B11111, 91 B11111, 92 B11111, 93 B11111, 94 // Ground right 95 B00011, 96 B00011, 97 B00011, 98 B00011, 99 B00011, 100 B00011, 101 B00011, 102 B00011, 103 // Ground left 104 B11000, 105 B11000, 106 B11000, 107 B11000, 108 B11000, 109 B11000, 110 B11000, 111 B11000, 112 }; 113 int i; 114 // Skip using character 0, this allows lcd.print() to be used to 115 // quickly draw multiple characters 116 for (i = 0; i < 7; ++i) { 117 lcd.createChar(i + 1, &graphics[i * 8]); 118 } 119 for (i = 0; i < TERRAIN_WIDTH; ++i) { 120 terrainUpper[i] = SPRITE_TERRAIN_EMPTY; 121 terrainLower[i] = SPRITE_TERRAIN_EMPTY; 122 } 123} 124 125// Slide the terrain to the left in half-character increments 126// 127void advanceTerrain(char* terrain, byte newTerrain){ 128 for (int i = 0; i < TERRAIN_WIDTH; ++i) { 129 char current = terrain[i]; 130 char next = (i == TERRAIN_WIDTH-1) ? newTerrain : terrain[i+1]; 131 switch (current){ 132 case SPRITE_TERRAIN_EMPTY: 133 terrain[i] = (next == SPRITE_TERRAIN_SOLID) ? SPRITE_TERRAIN_SOLID_RIGHT : SPRITE_TERRAIN_EMPTY; 134 break; 135 case SPRITE_TERRAIN_SOLID: 136 terrain[i] = (next == SPRITE_TERRAIN_EMPTY) ? SPRITE_TERRAIN_SOLID_LEFT : SPRITE_TERRAIN_SOLID; 137 break; 138 case SPRITE_TERRAIN_SOLID_RIGHT: 139 terrain[i] = SPRITE_TERRAIN_SOLID; 140 break; 141 case SPRITE_TERRAIN_SOLID_LEFT: 142 terrain[i] = SPRITE_TERRAIN_EMPTY; 143 break; 144 } 145 } 146} 147 148bool drawHero(byte position, char* terrainUpper, char* terrainLower, unsigned int score) { 149 bool collide = false; 150 char upperSave = terrainUpper[HERO_HORIZONTAL_POSITION]; 151 char lowerSave = terrainLower[HERO_HORIZONTAL_POSITION]; 152 byte upper, lower; 153 switch (position) { 154 case HERO_POSITION_OFF: 155 upper = lower = SPRITE_TERRAIN_EMPTY; 156 break; 157 case HERO_POSITION_RUN_LOWER_1: 158 upper = SPRITE_TERRAIN_EMPTY; 159 lower = SPRITE_RUN1; 160 break; 161 case HERO_POSITION_RUN_LOWER_2: 162 upper = SPRITE_TERRAIN_EMPTY; 163 lower = SPRITE_RUN2; 164 break; 165 case HERO_POSITION_JUMP_1: 166 case HERO_POSITION_JUMP_8: 167 upper = SPRITE_TERRAIN_EMPTY; 168 lower = SPRITE_JUMP; 169 break; 170 case HERO_POSITION_JUMP_2: 171 case HERO_POSITION_JUMP_7: 172 upper = SPRITE_JUMP_UPPER; 173 lower = SPRITE_JUMP_LOWER; 174 break; 175 case HERO_POSITION_JUMP_3: 176 case HERO_POSITION_JUMP_4: 177 case HERO_POSITION_JUMP_5: 178 case HERO_POSITION_JUMP_6: 179 upper = SPRITE_JUMP; 180 lower = SPRITE_TERRAIN_EMPTY; 181 break; 182 case HERO_POSITION_RUN_UPPER_1: 183 upper = SPRITE_RUN1; 184 lower = SPRITE_TERRAIN_EMPTY; 185 break; 186 case HERO_POSITION_RUN_UPPER_2: 187 upper = SPRITE_RUN2; 188 lower = SPRITE_TERRAIN_EMPTY; 189 break; 190 } 191 if (upper != ' ') { 192 terrainUpper[HERO_HORIZONTAL_POSITION] = upper; 193 collide = (upperSave == SPRITE_TERRAIN_EMPTY) ? false : true; 194 } 195 if (lower != ' ') { 196 terrainLower[HERO_HORIZONTAL_POSITION] = lower; 197 collide |= (lowerSave == SPRITE_TERRAIN_EMPTY) ? false : true; 198 } 199 200 byte digits = (score > 9999) ? 5 : (score > 999) ? 4 : (score > 99) ? 3 : (score > 9) ? 2 : 1; 201 202 // Draw the scene 203 terrainUpper[TERRAIN_WIDTH] = '\\0'; 204 terrainLower[TERRAIN_WIDTH] = '\\0'; 205 char temp = terrainUpper[16-digits]; 206 terrainUpper[16-digits] = '\\0'; 207 lcd.setCursor(0,0); 208 lcd.print(terrainUpper); 209 terrainUpper[16-digits] = temp; 210 lcd.setCursor(0,1); 211 lcd.print(terrainLower); 212 213 lcd.setCursor(16 - digits,0); 214 lcd.print(score); 215 216 terrainUpper[HERO_HORIZONTAL_POSITION] = upperSave; 217 terrainLower[HERO_HORIZONTAL_POSITION] = lowerSave; 218 return collide; 219} 220 221// Handle the button push as an interrupt 222void buttonPush() { 223 buttonPushed = true; 224} 225 226void setup(){ 227 pinMode(PIN_READWRITE, OUTPUT); 228 digitalWrite(PIN_READWRITE, LOW); 229 pinMode(PIN_CONTRAST, OUTPUT); 230 digitalWrite(PIN_CONTRAST, LOW); 231 pinMode(PIN_BUTTON, INPUT); 232 digitalWrite(PIN_BUTTON, HIGH); 233 pinMode(PIN_AUTOPLAY, OUTPUT); 234 digitalWrite(PIN_AUTOPLAY, HIGH); 235 pinMode(PIN_BUZZER,OUTPUT);//initialize the buzzer pin as an output 236 digitalWrite(PIN_BUZZER, LOW); 237 238 // Digital pin 2 maps to interrupt 0 239 attachInterrupt(0/*PIN_BUTTON*/, buttonPush, FALLING); 240 241 initializeGraphics(); 242 243 lcd.begin(16, 2); 244} 245 246void loop(){ 247 static byte heroPos = HERO_POSITION_RUN_LOWER_1; 248 static byte newTerrainType = TERRAIN_EMPTY; 249 static byte newTerrainDuration = 1; 250 static bool playing = false; 251 static bool blink = false; 252 static unsigned int distance = 0; 253 254 if (!playing) { 255 drawHero((blink) ? HERO_POSITION_OFF : heroPos, terrainUpper, terrainLower, distance >> 3); 256 if (blink) { 257 lcd.setCursor(0,0); 258 lcd.print("Press Start"); 259 } 260 delay(250); 261 blink = !blink; 262 if (buttonPushed) { 263 264 265 266 initializeGraphics(); 267 heroPos = HERO_POSITION_RUN_LOWER_1; 268 playing = true; 269 buttonPushed = false; 270 distance = 0; 271 } 272 return; 273 } 274 275 // Shift the terrain to the left 276 advanceTerrain(terrainLower, newTerrainType == TERRAIN_LOWER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY); 277 advanceTerrain(terrainUpper, newTerrainType == TERRAIN_UPPER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY); 278 279 // Make new terrain to enter on the right 280 if (--newTerrainDuration == 0) { 281 if (newTerrainType == TERRAIN_EMPTY) { 282 newTerrainType = (random(3) == 0) ? TERRAIN_UPPER_BLOCK : TERRAIN_LOWER_BLOCK; 283 newTerrainDuration = 2 + random(10); 284 } else { 285 newTerrainType = TERRAIN_EMPTY; 286 newTerrainDuration = 10 + random(10); 287 } 288 } 289 290 if (buttonPushed) { 291 if (heroPos <= HERO_POSITION_RUN_LOWER_2) heroPos = HERO_POSITION_JUMP_1; 292 buttonPushed = false; 293 digitalWrite(PIN_BUZZER,HIGH); 294 } 295 296 if (drawHero(heroPos, terrainUpper, terrainLower, distance >> 3)) { 297 playing = false; // The hero collided with something. Too bad. 298 for (int i = 0; i <= 2; i++) { 299 digitalWrite(PIN_BUZZER, HIGH); 300 delay(100); 301 digitalWrite(PIN_BUZZER, LOW); 302 delay(100); 303 } 304 } else { 305 if (heroPos == HERO_POSITION_RUN_LOWER_2 || heroPos == HERO_POSITION_JUMP_8) { 306 heroPos = HERO_POSITION_RUN_LOWER_1; 307 } else if ((heroPos >= HERO_POSITION_JUMP_3 && heroPos <= HERO_POSITION_JUMP_5) && terrainLower[HERO_HORIZONTAL_POSITION] != SPRITE_TERRAIN_EMPTY) { 308 heroPos = HERO_POSITION_RUN_UPPER_1; 309 } else if (heroPos >= HERO_POSITION_RUN_UPPER_1 && terrainLower[HERO_HORIZONTAL_POSITION] == SPRITE_TERRAIN_EMPTY) { 310 heroPos = HERO_POSITION_JUMP_5; 311 } else if (heroPos == HERO_POSITION_RUN_UPPER_2) { 312 heroPos = HERO_POSITION_RUN_UPPER_1; 313 } else { 314 ++heroPos; 315 } 316 ++distance; 317 318 digitalWrite(PIN_AUTOPLAY, terrainLower[HERO_HORIZONTAL_POSITION + 2] == SPRITE_TERRAIN_EMPTY ? HIGH : LOW); 319 } 320 delay(100); 321 digitalWrite(PIN_BUZZER,LOW); 322}
The code
arduino
1#include <LiquidCrystal.h> 2 3#define PIN_BUTTON 2 4#define PIN_AUTOPLAY 5 1 6#define PIN_BUZZER 8 7#define PIN_READWRITE 10 8#define PIN_CONTRAST 12 9 10#define 11 SPRITE_RUN1 1 12#define SPRITE_RUN2 2 13#define SPRITE_JUMP 3 14#define SPRITE_JUMP_UPPER 15 '.' // Use the '.' character for the head 16#define SPRITE_JUMP_LOWER 4 17#define 18 SPRITE_TERRAIN_EMPTY ' ' // User the ' ' character 19#define SPRITE_TERRAIN_SOLID 20 5 21#define SPRITE_TERRAIN_SOLID_RIGHT 6 22#define SPRITE_TERRAIN_SOLID_LEFT 7 23 24#define 25 HERO_HORIZONTAL_POSITION 1 // Horizontal position of hero on screen 26 27#define 28 TERRAIN_WIDTH 16 29#define TERRAIN_EMPTY 0 30#define TERRAIN_LOWER_BLOCK 1 31#define 32 TERRAIN_UPPER_BLOCK 2 33 34#define HERO_POSITION_OFF 0 // Hero is invisible 35#define 36 HERO_POSITION_RUN_LOWER_1 1 // Hero is running on lower row (pose 1) 37#define 38 HERO_POSITION_RUN_LOWER_2 2 // (pose 2) 39 40#define 41 HERO_POSITION_JUMP_1 3 // Starting a jump 42#define HERO_POSITION_JUMP_2 43 4 // Half-way up 44#define HERO_POSITION_JUMP_3 5 // Jump is on upper 45 row 46#define HERO_POSITION_JUMP_4 6 // Jump is on upper row 47#define HERO_POSITION_JUMP_5 48 7 // Jump is on upper row 49#define HERO_POSITION_JUMP_6 8 // Jump 50 is on upper row 51#define HERO_POSITION_JUMP_7 9 // Half-way down 52#define 53 HERO_POSITION_JUMP_8 10 // About to land 54 55#define HERO_POSITION_RUN_UPPER_1 56 11 // Hero is running on upper row (pose 1) 57#define HERO_POSITION_RUN_UPPER_2 58 12 // (pose 2) 59 60LiquidCrystal lcd(11, 9, 6, 5, 61 4, 3); 62static char terrainUpper[TERRAIN_WIDTH + 1]; 63static char terrainLower[TERRAIN_WIDTH 64 + 1]; 65static bool buttonPushed = false; 66 67void initializeGraphics(){ 68 69 static byte graphics[] = { 70 // Run position 1 71 B01100, 72 B01100, 73 74 B00000, 75 B01110, 76 B11100, 77 B01100, 78 B11010, 79 B10011, 80 81 // Run position 2 82 B01100, 83 B01100, 84 B00000, 85 B01100, 86 87 B01100, 88 B01100, 89 B01100, 90 B01110, 91 // Jump 92 B01100, 93 94 B01100, 95 B00000, 96 B11110, 97 B01101, 98 B11111, 99 B10000, 100 101 B00000, 102 // Jump lower 103 B11110, 104 B01101, 105 B11111, 106 107 B10000, 108 B00000, 109 B00000, 110 B00000, 111 B00000, 112 // 113 Ground 114 B11111, 115 B11111, 116 B11111, 117 B11111, 118 B11111, 119 120 B11111, 121 B11111, 122 B11111, 123 // Ground right 124 B00011, 125 126 B00011, 127 B00011, 128 B00011, 129 B00011, 130 B00011, 131 B00011, 132 133 B00011, 134 // Ground left 135 B11000, 136 B11000, 137 B11000, 138 139 B11000, 140 B11000, 141 B11000, 142 B11000, 143 B11000, 144 }; 145 146 int i; 147 // Skip using character 0, this allows lcd.print() to be used to 148 149 // quickly draw multiple characters 150 for (i = 0; i < 7; ++i) { 151 lcd.createChar(i 152 + 1, &graphics[i * 8]); 153 } 154 for (i = 0; i < TERRAIN_WIDTH; ++i) { 155 terrainUpper[i] 156 = SPRITE_TERRAIN_EMPTY; 157 terrainLower[i] = SPRITE_TERRAIN_EMPTY; 158 } 159} 160 161// 162 Slide the terrain to the left in half-character increments 163// 164void advanceTerrain(char* 165 terrain, byte newTerrain){ 166 for (int i = 0; i < TERRAIN_WIDTH; ++i) { 167 char 168 current = terrain[i]; 169 char next = (i == TERRAIN_WIDTH-1) ? newTerrain : terrain[i+1]; 170 171 switch (current){ 172 case SPRITE_TERRAIN_EMPTY: 173 terrain[i] 174 = (next == SPRITE_TERRAIN_SOLID) ? SPRITE_TERRAIN_SOLID_RIGHT : SPRITE_TERRAIN_EMPTY; 175 176 break; 177 case SPRITE_TERRAIN_SOLID: 178 terrain[i] = (next 179 == SPRITE_TERRAIN_EMPTY) ? SPRITE_TERRAIN_SOLID_LEFT : SPRITE_TERRAIN_SOLID; 180 181 break; 182 case SPRITE_TERRAIN_SOLID_RIGHT: 183 terrain[i] = 184 SPRITE_TERRAIN_SOLID; 185 break; 186 case SPRITE_TERRAIN_SOLID_LEFT: 187 188 terrain[i] = SPRITE_TERRAIN_EMPTY; 189 break; 190 } 191 } 192} 193 194bool 195 drawHero(byte position, char* terrainUpper, char* terrainLower, unsigned int score) 196 { 197 bool collide = false; 198 char upperSave = terrainUpper[HERO_HORIZONTAL_POSITION]; 199 200 char lowerSave = terrainLower[HERO_HORIZONTAL_POSITION]; 201 byte upper, lower; 202 203 switch (position) { 204 case HERO_POSITION_OFF: 205 upper = lower = SPRITE_TERRAIN_EMPTY; 206 207 break; 208 case HERO_POSITION_RUN_LOWER_1: 209 upper = SPRITE_TERRAIN_EMPTY; 210 211 lower = SPRITE_RUN1; 212 break; 213 case HERO_POSITION_RUN_LOWER_2: 214 215 upper = SPRITE_TERRAIN_EMPTY; 216 lower = SPRITE_RUN2; 217 break; 218 219 case HERO_POSITION_JUMP_1: 220 case HERO_POSITION_JUMP_8: 221 upper 222 = SPRITE_TERRAIN_EMPTY; 223 lower = SPRITE_JUMP; 224 break; 225 case 226 HERO_POSITION_JUMP_2: 227 case HERO_POSITION_JUMP_7: 228 upper = SPRITE_JUMP_UPPER; 229 230 lower = SPRITE_JUMP_LOWER; 231 break; 232 case HERO_POSITION_JUMP_3: 233 234 case HERO_POSITION_JUMP_4: 235 case HERO_POSITION_JUMP_5: 236 case HERO_POSITION_JUMP_6: 237 238 upper = SPRITE_JUMP; 239 lower = SPRITE_TERRAIN_EMPTY; 240 break; 241 242 case HERO_POSITION_RUN_UPPER_1: 243 upper = SPRITE_RUN1; 244 lower 245 = SPRITE_TERRAIN_EMPTY; 246 break; 247 case HERO_POSITION_RUN_UPPER_2: 248 249 upper = SPRITE_RUN2; 250 lower = SPRITE_TERRAIN_EMPTY; 251 break; 252 253 } 254 if (upper != ' ') { 255 terrainUpper[HERO_HORIZONTAL_POSITION] = upper; 256 257 collide = (upperSave == SPRITE_TERRAIN_EMPTY) ? false : true; 258 } 259 if 260 (lower != ' ') { 261 terrainLower[HERO_HORIZONTAL_POSITION] = lower; 262 collide 263 |= (lowerSave == SPRITE_TERRAIN_EMPTY) ? false : true; 264 } 265 266 byte digits 267 = (score > 9999) ? 5 : (score > 999) ? 4 : (score > 99) ? 3 : (score > 9) ? 2 : 268 1; 269 270 // Draw the scene 271 terrainUpper[TERRAIN_WIDTH] = '\\0'; 272 terrainLower[TERRAIN_WIDTH] 273 = '\\0'; 274 char temp = terrainUpper[16-digits]; 275 terrainUpper[16-digits] 276 = '\\0'; 277 lcd.setCursor(0,0); 278 lcd.print(terrainUpper); 279 terrainUpper[16-digits] 280 = temp; 281 lcd.setCursor(0,1); 282 lcd.print(terrainLower); 283 284 lcd.setCursor(16 285 - digits,0); 286 lcd.print(score); 287 288 terrainUpper[HERO_HORIZONTAL_POSITION] 289 = upperSave; 290 terrainLower[HERO_HORIZONTAL_POSITION] = lowerSave; 291 return 292 collide; 293} 294 295// Handle the button push as an interrupt 296void buttonPush() 297 { 298 buttonPushed = true; 299} 300 301void setup(){ 302 pinMode(PIN_READWRITE, 303 OUTPUT); 304 digitalWrite(PIN_READWRITE, LOW); 305 pinMode(PIN_CONTRAST, OUTPUT); 306 307 digitalWrite(PIN_CONTRAST, LOW); 308 pinMode(PIN_BUTTON, INPUT); 309 digitalWrite(PIN_BUTTON, 310 HIGH); 311 pinMode(PIN_AUTOPLAY, OUTPUT); 312 digitalWrite(PIN_AUTOPLAY, HIGH); 313 314 pinMode(PIN_BUZZER,OUTPUT);//initialize the buzzer pin as an output 315 digitalWrite(PIN_BUZZER, 316 LOW); 317 318 // Digital pin 2 maps to interrupt 0 319 attachInterrupt(0/*PIN_BUTTON*/, 320 buttonPush, FALLING); 321 322 initializeGraphics(); 323 324 lcd.begin(16, 325 2); 326} 327 328void loop(){ 329 static byte heroPos = HERO_POSITION_RUN_LOWER_1; 330 331 static byte newTerrainType = TERRAIN_EMPTY; 332 static byte newTerrainDuration 333 = 1; 334 static bool playing = false; 335 static bool blink = false; 336 static 337 unsigned int distance = 0; 338 339 if (!playing) { 340 drawHero((blink) ? 341 HERO_POSITION_OFF : heroPos, terrainUpper, terrainLower, distance >> 3); 342 if 343 (blink) { 344 lcd.setCursor(0,0); 345 lcd.print("Press Start"); 346 347 } 348 delay(250); 349 blink = !blink; 350 if (buttonPushed) { 351 352 353 354 355 initializeGraphics(); 356 heroPos = HERO_POSITION_RUN_LOWER_1; 357 358 playing = true; 359 buttonPushed = false; 360 distance = 0; 361 362 } 363 return; 364 } 365 366 // Shift the terrain to the left 367 advanceTerrain(terrainLower, 368 newTerrainType == TERRAIN_LOWER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY); 369 370 advanceTerrain(terrainUpper, newTerrainType == TERRAIN_UPPER_BLOCK ? SPRITE_TERRAIN_SOLID 371 : SPRITE_TERRAIN_EMPTY); 372 373 // Make new terrain to enter on the right 374 375 if (--newTerrainDuration == 0) { 376 if (newTerrainType == TERRAIN_EMPTY) { 377 378 newTerrainType = (random(3) == 0) ? TERRAIN_UPPER_BLOCK : TERRAIN_LOWER_BLOCK; 379 380 newTerrainDuration = 2 + random(10); 381 } else { 382 newTerrainType 383 = TERRAIN_EMPTY; 384 newTerrainDuration = 10 + random(10); 385 } 386 } 387 388 389 if (buttonPushed) { 390 if (heroPos <= HERO_POSITION_RUN_LOWER_2) heroPos 391 = HERO_POSITION_JUMP_1; 392 buttonPushed = false; 393 digitalWrite(PIN_BUZZER,HIGH); 394 395 } 396 397 if (drawHero(heroPos, terrainUpper, terrainLower, distance >> 398 3)) { 399 playing = false; // The hero collided with something. Too bad. 400 401 for (int i = 0; i <= 2; i++) { 402 digitalWrite(PIN_BUZZER, HIGH); 403 404 delay(100); 405 digitalWrite(PIN_BUZZER, LOW); 406 delay(100); 407 408 } 409 } else { 410 if (heroPos == HERO_POSITION_RUN_LOWER_2 || heroPos == 411 HERO_POSITION_JUMP_8) { 412 heroPos = HERO_POSITION_RUN_LOWER_1; 413 } else 414 if ((heroPos >= HERO_POSITION_JUMP_3 && heroPos <= HERO_POSITION_JUMP_5) && terrainLower[HERO_HORIZONTAL_POSITION] 415 != SPRITE_TERRAIN_EMPTY) { 416 heroPos = HERO_POSITION_RUN_UPPER_1; 417 } 418 else if (heroPos >= HERO_POSITION_RUN_UPPER_1 && terrainLower[HERO_HORIZONTAL_POSITION] 419 == SPRITE_TERRAIN_EMPTY) { 420 heroPos = HERO_POSITION_JUMP_5; 421 } else 422 if (heroPos == HERO_POSITION_RUN_UPPER_2) { 423 heroPos = HERO_POSITION_RUN_UPPER_1; 424 425 } else { 426 ++heroPos; 427 } 428 ++distance; 429 430 digitalWrite(PIN_AUTOPLAY, 431 terrainLower[HERO_HORIZONTAL_POSITION + 2] == SPRITE_TERRAIN_EMPTY ? HIGH : LOW); 432 433 } 434 delay(100); 435 digitalWrite(PIN_BUZZER,LOW); 436}
Downloadable files
The schematic
This will show you how to connect all the parts together as not all wiring was shown in the cover image.
The schematic
Comments
Only logged in users can leave comments