In questo articolo si vedrà in che modo realizzare un gioco interattivo con Arduino utilizzando un telecomando e un ricevitore IR.
Non vi sono restrizioni sul telecomando da usare, in quanto ad ogni avvio sarà possibile mappare i tasti in qualsiasi modo si desidera.
Il gioco consiste nel premere i tasti associati al simbolo che compare sul display LCD. Man mano che si sale di livello il gioco sarà più difficile in quanto i simboli si muoveranno più velocemente. Il punteggio sale nel momento in cui si premono i tasti giusti, altrimenti diminuisce,
Per realizzare tale progetto occorre utilizzare i seguenti componenti:
- 1x board di Arduino Uno
- 1x display LCD
- 1x potenziometro da 10k
- 1x buzzer passivo
- 1x ricevitore IR
- 1x telecomando
- vari jumper
Ecco un video che illustra il progetto:
Il diagramma di collegamento è il seguente:
In alto a sinistra dello schermo è presente il livello, in alto a destra il punteggio. Se il punteggio è minore di zero comparirà la scritta Game Over nella seconda riga. Inoltre nella seconda riga compariranno i vari simboli che si muoveranno da sinistra verso destra o viceversa.
Il codice è il seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
#include <Wire.h> #include <IRremote.h> //libreria per utilizzare a pieno le potenzialità del ricevitore IR #include <LiquidCrystal.h> //libreria per utilizzare a pieno le potenzialità del display char up = 3; char down = 1; char ok = 2; // Definizione di tre caratteri da utilizzare per il display LCD byte up1[8] = { B00100, B01110, B10101, B00100, B00100, B00100, B00100, B00100 }; byte down1[8] = { B00100, B00100, B00100, B00100, B00100, B10101, B01110, B00100 }; byte ok1[8] = { B01110, B01010, B01110, B10000, B10100, B11000, B10100, B10010 }; int RECV_PIN = 2; // Pin in cui è collegato il ricevitore IR //Le varie scritte che compariranno sul display LCD le quali riportano le regole del gioco char* howtoplay[23] = { "> FAST IR GAME <", " Press key ", "You have to", "press the key,", "that you see on", "the screen, when", "it is beetween", "the fences (#).", "It ist getting", "faster and there", "will be symbols", "that you do not", "have to hit!", "Try to get to", "Level 10 and win", "the game. Before", "you start, you", "have to define", "the keys on your", "remote control", "to play the game", " Have fun !!", "" }; int buzzer=13; String keyNames[] = {"up", "down", "right", "left", "ok", "+", "-", "#", "*"}; //vettore nel quali sono riportati i tasti del telecomando da utilizzare String keySymb[] = {"", "", "", "", "", "", "", "", ""}; long keys[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int keycount = 7; int lev; int xpos = 1; int xadd = 1; int xleft; int xright; int xstart = 0; int xend = 15; int actSym = 0; int score; //punteggio totale int scorePerLev; //punteggio per livello int scoreNextLev = 50; // Punteggio dopo il quale si passera' al livello eccessivo int gameState = -1; bool pressed = false; IRrecv irrecv(RECV_PIN); decode_results results; LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //i digital pin utilizzati dal display LCD void setup() { lcd.begin(16,2); // colonne e righe che compongono il display lcd.createChar(up, up1); lcd.createChar(down, down1); lcd.createChar(ok, ok1); keySymb[0] = "\3"; keySymb[1] = "\1"; keySymb[2] = "\176"; keySymb[3] = "\177"; keySymb[4] = "\2"; keySymb[5] = "+"; keySymb[6] = "-"; keySymb[7] = "#"; keySymb[8] = "*"; irrecv.enableIRIn(); // Si inizia con la ricezione info(); //funzione nella quale sono presente le istruzioni che permettono di leggere le regole //è possibile eliminare tale istruzione, in tal modo da saltare la presentazione delle regole randomSeed(analogRead(1)); } void loop() { // definizione dei tasti da utilizzare if (gameState == -1) { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Define Keys to"); lcd.setCursor(0, 1); lcd.print("play the game..."); tone(buzzer,440,500); delay(3000); pressed = false; for (int i = 0; i < keycount; i++) { pressed = false; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Key for:"); lcd.print(keyNames[i]); while (pressed != true) { if (irrecv.decode(&results)) { keys[i] = results.value; lcd.setCursor(0, 1); lcd.print(" ok!"); Serial.println(keys[i]); delay(500); irrecv.resume(); //ricevo il prossimo valore pressed = true; } } pressed = false; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Repaet key!"); lcd.print(keyNames[i]); irrecv.resume(); while (pressed != true) { if (irrecv.decode(&results)) { if (keys[i] == results.value) { lcd.setCursor(0, 1); lcd.print("is the same!"); tone(buzzer,440,500); delay(500); pressed = true; } else { lcd.setCursor(0, 1); lcd.print("wrong!"); tone(buzzer,440,500); delay(500); lcd.setCursor(0, 1); lcd.print(" "); } irrecv.resume(); } } } gameState = 0; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Keys done!"); tone(buzzer,440,500); delay(2000); } // Select Level if (gameState == 0) { lev = 1; lcd.clear(); lcd.setCursor(0, 0); lcd.print("Select Level+ok"); lcd.setCursor(0, 1); lcd.print("Level: "); lcd.print(lev); irrecv.resume(); pressed = false; Serial.println("Level"); Serial.println(pressed); while (pressed != true) { if (irrecv.decode(&results)) { Serial.println(results.value); if (results.value == keys[0]) lev++; if (results.value == keys[1]) lev--; if (results.value == keys[4]) pressed = true; if (lev < 1) lev = 1; if (lev > 10) lev = 10; lcd.setCursor(7, 1); lcd.print(lev); lcd.print(" "); irrecv.resume(); } delay(250); } lcd.setCursor(0, 0); lcd.print("Ok! Play in "); delay(2000); lcd.clear(); gameState = 1; //gameplay principale score = 0; scorePerLev = 0; keycount = 7; xleft = 4; xright = 11; drawField(""); irrecv.resume(); Serial.println("Level Set"); } // Main Game if (gameState == 1) { xpos = 0; xadd = 1; int k = 0; bool rightkey = false; pressed = false; actSym = floor(random(0, keycount)); while (pressed != true) { Serial.println(xpos); if (irrecv.decode(&results)) { for (int i = 0; i < keycount; i++) { if (results.value == keys[i]) { rightkey = true; k = i; } } if (rightkey == true) { scorePerLev++; if (xpos <= xleft || xpos >= xright) { score = score - (4 + lev); tone(buzzer,880,300); delay(300); } if (actSym == k) { lcd.setCursor(xpos, 1); lcd.print(" "); score++; drawField(""); changeDirection(); } else { score = score - (2 + lev); drawField(" :( "); tone(buzzer,880,300); delay(300); } actSym = floor(random(0, keycount)); rightkey = false; } delay(10); irrecv.resume(); if (scorePerLev == scoreNextLev) { scorePerLev = 0; lev++; drawField(""); if (lev < 11) { lcd.setCursor(0, 1); lcd.print("Next level!"); waitForOK(); // Check for score and display message here later lcd.setCursor(0, 1); lcd.print(" "); } else { gameState = 5; pressed = true; } } } lcd.setCursor(xpos, 1); lcd.print(" "); xpos = xpos + xadd; if (xpos == xend + 1 || xpos == xstart - 1) { if (actSym < 7) { score = score - (2 * (lev + 5)); drawField(" :( "); } else { drawField(""); } changeDirection(); actSym = floor(random(0, keycount)); tone(buzzer,880,300); delay(300); } lcd.setCursor(xpos, 1); lcd.print(keySymb[actSym]); delay(200 - (lev * 10)); if (score < 0) { gameState = 9; pressed = true; } } // Main Game loop End } // Win // ################## if (gameState == 5) { tone(buzzer,440,300); delay(300); lcd.setCursor(0, 1); lcd.print("You win the Game"); lcd.setCursor(0, 0); lcd.print("Bravo! "); tone(buzzer,440,500); waitForOK(); gameState = 0; } // Game Over // ################## if (gameState == 9) { tone(buzzer,440,300); delay(300); for (int i = 0; i < 5; i++) { lcd.setCursor(0, 1); lcd.print(" "); delay(200); lcd.setCursor(0, 1); lcd.print(" Game over! "); tone(buzzer,440,500); delay(300); } waitForOK(); gameState = 0; } } void info () { int i = 0; while (howtoplay[i] != "") { lcd.clear(); lcd.setCursor(0, 0); lcd.print(howtoplay[i]); lcd.setCursor(0, 1); lcd.print(howtoplay[i + 1]); tone(buzzer,440,500); delay(300); waitForKey(); i++; } irrecv.resume(); } void drawField(String empty) { Serial.println("drawField"); int SCur; if (empty == "") empty = " "; lcd.setCursor(0, 0); lcd.print("################"); if (lev > 3) { xleft = floor(random(4, 7)); xright = xleft + 7; if (lev > 6) xright = xleft + 6; if (lev > 9) xright = xleft + 5; } if (lev > 4) keycount = 8; if (lev > 6) keycount = 9; lcd.setCursor(xleft + 1, 0); lcd.print(empty.substring(0, xright - xleft - 1)); lcd.setCursor(0, 0); lcd.print("L"); lcd.print(lev); if (score < 1000) SCur = 13; if (score < 100) SCur = 14; if (score < 10) SCur = 15; if (score < 0) SCur = 14; lcd.setCursor(SCur, 0); lcd.print(score); } void changeDirection() { xpos = xstart; xadd = 1; if (lev > 3) { int dir = floor(random(0, 2)); if (dir == 1) { xpos = xend; xadd = -1; } } } void waitForKey () { bool press = false; irrecv.resume(); while (press == false) { if (irrecv.decode(&results)) { if (results.value != 0) press = true; irrecv.resume(); delay(200); } } } void waitForOK() { delay(1000); bool press = false; irrecv.resume(); while (press == false) { if (irrecv.decode(&results)) { if (results.value == keys[4]) press = true; irrecv.resume(); delay(200); } } } |
Inoltre per chi fosse interessato è possibile creare una struttura 3D apposita per ospitare tutti i componenti e rendere il gioco più coinvolgente. Per coloro i quali sono intenzionati a creare tale struttura ecco qui il link github per farlo: https://github.com/LuigiMorelli/MoreWare/blob/master/Nano_con_LCD1602.zip
Link utili
- Arduino UNO R3
- Elegoo UNO R3
- Arduino Starter Kit per principianti
- Elegoo Advanced Starter Kit
- Arduino Nano
Seguici per non perdere le prossime novità!