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