This is an old revision of the document!
Scopul acestui proiect este să ofere utilizatorilor un joc Super Mario, care poate fi jucat în timpul liber. Proiectul a fost creat pentru a fi ușor de jucat și de înțeles, fiind util și pentru învățarea conceptelor hardware și software.
#include <Wire.h> #include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define NOTE_B0 31 #define NOTE_C1 33 #define NOTE_CS1 35 #define NOTE_D1 37 #define NOTE_DS1 39 #define NOTE_E1 41 #define NOTE_F1 44 #define NOTE_FS1 46 #define NOTE_G1 49 #define NOTE_GS1 52 #define NOTE_A1 55 #define NOTE_AS1 58 #define NOTE_B1 62 #define NOTE_C2 65 #define NOTE_CS2 69 #define NOTE_D2 73 #define NOTE_DS2 78 #define NOTE_E2 82 #define NOTE_F2 87 #define NOTE_FS2 93 #define NOTE_G2 98 #define NOTE_GS2 104 #define NOTE_A2 110 #define NOTE_AS2 117 #define NOTE_B2 123 #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 #define NOTE_C8 4186 #define NOTE_CS8 4435 #define NOTE_D8 4699 #define NOTE_DS8 4978 #define REST 0
#define run_1 0 #define run_2 1 #define jump_high 2 #define jump_half_head 3 #define jump_half_body 4
#define upperObject1 5 #define lowerObject1 6 #define empty 7 #define RED_LED 3 int man_up_pos=0; int man_low_pos=0; long ts = 0; int buzzer = 8; int mode = 0; bool game_over = false; static int delay_time = 130; static bool buttonPushed = false; static byte currentPos; static byte currentPosUp; static byte currentPosDown; static int score = 0; static bool playing = false; static bool scoring =false; const int jump_button = 2; const int buzzerPin = 8; static int upperBG[17] = {7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; static int lowerBG[17] = {7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7}; int mode_change = 0;
int tempo = 200;
int gameOver[] = { NOTE_C5,-4, NOTE_G4,-4, NOTE_E4,4, NOTE_A4,-8, NOTE_B4,-8, NOTE_A4,-8, NOTE_GS4,-8, NOTE_AS4,-8, NOTE_GS4,-8, NOTE_G4,8, NOTE_D4,8, NOTE_E4,-2, };
void graphics(){
byte man[64] = { // position 1 B01100, B01100, B00000, B01110, B11100, B01100, B11010, B10011, // position 2 B01100, B01100, B00000, B01100, B01100, B01100, B01100, B01110, // Jump B01100, B01100, B00000, B11110, B01101, B11111, B10000, B00000, // Jump lower B11110, B01101, B11111, B10000, B00000, B00000, B00000, B00000, // Ground B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111, // Ground right B00011, B00011, B00011, B00011, B00011, B00011, B00011, B00011, // Ground left B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000 }; int g; for (g = 0; g < 8; g++) { lcd.createChar(g, &man[g*8]); }
}
void startGame(){
lcd.setCursor (1,1); lcd.print("Press Up to Start!"); lcd.setCursor (0,1); currentPos = run_1;
}
void drawmanWalk(){
man_low_pos=1; lcd.setCursor(0,1); currentPos = run_2; lcd.write(byte(currentPos)); delay(120); lcd.setCursor(0,1); currentPos = run_1; lcd.write(byte(currentPos)); delay(120); detect();
}
void drawmanJump(){
man_low_pos=1; man_up_pos=1; lcd.setCursor (0,0); currentPosUp = jump_half_head; lcd.write(byte(currentPosUp)); lcd.setCursor (0,1); currentPosDown = jump_half_body; lcd.write(byte(currentPosDown)); detect();
tone(buzzer, NOTE_A6, 100); delay(110); drawObject();
man_low_pos=0; man_up_pos=1; lcd.setCursor (0,0); currentPosUp = jump_high; lcd.write(byte(currentPosUp)); lcd.setCursor (0,1); lcd.print(" "); detect(); delay(110); drawObject(); detect(); delay(140); drawObject(); detect();
man_low_pos=1; man_up_pos=1; lcd.setCursor (0,0); currentPosUp = jump_half_head; lcd.write(byte(currentPosUp)); lcd.setCursor (0,1); currentPosDown = jump_half_body; lcd.write(byte(currentPosDown)); delay(140); lcd.setCursor(0,0); lcd.print(" "); man_up_pos=0; man_low_pos=1; detect();
}
void objectRandom (int upperBG[], int lowerBG[]){
int ObjectPos = random(5,10);
switch (ObjectPos){
case upperObject1: lowerBG[16] = empty; if (lowerBG[15] == lowerObject1) upperBG[16] = empty; else upperBG[16] = upperObject1; break; case lowerObject1: if ((lowerBG[15] == lowerObject1)|| (lowerBG[14] == lowerObject1)|| (lowerBG[13] == lowerObject1)|| (upperBG[15] == upperObject1)){ lowerBG[16] = empty; } else lowerBG[16] = lowerObject1; break; case empty: case 8: case 9: case 10: upperBG[16] = empty; lowerBG[16] = empty; break; }
}
void detect(){
if((man_up_pos==1 && upperBG[0]!=7)|| (man_low_pos==1&&lowerBG[0]!=7)){ lcd.clear(); lcd.setCursor(1,0); playing = false; scoring = false; }
}
void drawObject (){
if(millis() - ts > 300) { ts = millis(); objectRandom(upperBG,lowerBG); } for (int i = 0; i < 16; i++){ upperBG[i]=upperBG[i+1]; lowerBG[i]=lowerBG[i+1]; } if(upperBG[0]!=7){ lcd.setCursor(0,0); lcd.write(byte(upperBG[0])); } else if(man_up_pos==0){ lcd.setCursor(0,0); lcd.print(" "); }
if(lowerBG[0]!=7){ lcd.setCursor(0,1); lcd.write(byte(lowerBG[0])); } else if(man_low_pos==0){ lcd.setCursor(0,1); lcd.print(" "); }
for (int i = 1; i < 16; i++){ lcd.setCursor(i,0); lcd.write(byte(upperBG[i])); lcd.setCursor(i,1); lcd.write(byte(lowerBG[i])); }
}
void over(){
digitalWrite(RED_LED, HIGH); int wholenote = (60000 * 4) / 200; int noteDuration = 0; for(int i = 0; i < 24; i+=2){ int divider = gameOver[i + 1]; if (divider > 0) { noteDuration = (wholenote) / divider; } else if (divider < 0) { noteDuration = (wholenote) / abs(divider); noteDuration *= 1.5; } tone(buzzer, gameOver[i], noteDuration * 0.9); delay(noteDuration); noTone(buzzer); }
lcd.clear(); lcd.setCursor (5,1); lcd.print ("Game Over!"); lcd.setCursor (3,2); lcd.print ("Your Score:"); lcd.setCursor (14,2); lcd.print (score); delay(delay_time); game_over = true;
}
void setup() {
Serial.begin(9600); pinMode(jump_button, INPUT); digitalWrite(jump_button, HIGH); graphics(); lcd.begin(20, 4); lcd.backlight(); pinMode(buzzerPin, OUTPUT); pinMode(RED_LED, OUTPUT); digitalWrite(RED_LED, LOW);
}
void loop() {
while(game_over) { buttonPushed = (digitalRead(jump_button) == LOW); if(buttonPushed) { lcd.clear(); buttonPushed = false; playing = false; scoring = false; score = 0; for(int i = 0; i < 17; i++) { upperBG[i]= empty; lowerBG[i] = empty; } game_over = false; } } buttonPushed = (digitalRead(jump_button) == LOW); if (!playing && score == 0) { startGame(); digitalWrite(RED_LED, LOW); if (buttonPushed) { graphics(); playing = true; scoring = true; buttonPushed = false; lcd.clear(); } } if(!playing && score > 0) { over(); } if (playing){ drawObject(); drawmanWalk(); if((mode == 0 || mode == 1 ) && buttonPushed){ drawmanJump(); buttonPushed = false; } if(mode == 1) { if (lowerBG[3] == lowerObject1){ digitalWrite(RED_LED, HIGH); } else { digitalWrite(RED_LED, LOW); } } if(mode == 2) { if (man_low_pos==1 && lowerBG[2]!=7){ drawmanJump(); } } }
if (scoring == true){
score++; }
}
Proiectul m-a ajutat să aprofundez conceptele studiate la laboratoarele de PM, mai ales să înțeleg utilizarea protocolului I2C.
Melodia SuperMario : https://github.com/robsoncouto/arduino-songs/blob/master/supermariobros/supermariobros.ino
Configurare I2C: https://www.youtube.com/watch?v=EAeuxjtkumM&t=125s