This is an old revision of the document!
O schemă bloc cu toate modulele proiectului vostru, atât software cât şi hardware însoţită de o descriere a acestora precum şi a modului în care interacţionează.
!Potentiometrele din schema reprezinta Joystick-uri!
Pinii (de la stanga la dreapta):
!Piesa de pe breadboard-ul din stanga reprezinta un cititor de card SD! Pinii (de la stanga la dreapta):
Exemplu de schemă bloc: http://www.robs-projects.com/mp3proj/newplayer.html
Biblioteci utilizate:
Funcții:
void setup() {
Serial.begin(9600); pinMode(BEEPER, OUTPUT); tone(BEEPER, 440, 200); delay(250);
if (!sd.begin(chipSelect, SD_SCK_MHZ(10))) { Serial.println(F("SD init failed!")); } else { Serial.println(F("SD init OK.")); }
wholenote = (60000L * 4) / marioTempo;
display.begin(); display.setFont(u8g2_font_6x10_tf); display.firstPage(); do { display.drawStr(0, 10, "Initializare..."); display.drawStr(0, 20, sd.begin(chipSelect, SD_SCK_MHZ(10)) ? "SD OK" : "Eroare SD");
char buf[12]; strcpy_P(buf, FILENAME); if (musicFile.open(buf, O_RDONLY)) { display.drawStr(0, 30, "mario.txt OK"); musicFile.close(); } else { display.drawStr(0, 30, "Fisier lipsa"); } } while (display.nextPage());
delay(3000);
pinMode(SW_pin, INPUT); pinMode(RESET_BUTTON, INPUT_PULLUP); digitalWrite(SW_pin, HIGH);
// Calibrare joystick-uri player1_center = analogRead(player1); player2_center = analogRead(player2);
ball_update = millis(); paddle_update = ball_update;
}
void loop() {
unsigned long now = millis(); bool update = false;
if (resetBall) { (player1Score == maxScore || player2Score == maxScore) ? gameOver() : resetGame(); }
if (now > ball_update) { updateBallPosition(); update = true; }
if (now > paddle_update) { updatePaddlePositions(); update = true; }
if (update) { drawFrame(); }
playMarioTheme();
}
display.firstPage(); do { drawCourt(); drawScore(); display.drawPixel(ball_x, ball_y); display.drawVLine(PLAYER2_X, player2_y, PADDLE_HEIGHT); display.drawVLine(PLAYER_X, player1_y, PADDLE_HEIGHT); } while (display.nextPage());
}
ball_x = random(45, 50); ball_y = random(23, 33); do { ball_dir_x = random(-1, 2); } while (ball_dir_x == 0); do { ball_dir_y = random(-1, 2); } while (ball_dir_y == 0); resetBall = false;
}
display.drawFrame(0, 0, 128, 64);
}
void drawScore() {
char buf[4]; sprintf(buf, "%d", player2Score); display.drawStr(45, 10, buf); sprintf(buf, "%d", player1Score); display.drawStr(75, 10, buf);
}
display.firstPage(); do { display.drawStr(20, 25, (player1Score > player2Score) ? "Player 1" : "Player 2"); display.drawStr(40, 40, "won"); } while (display.nextPage()); delay(2000); player1Score = player2Score = 0; resetBall = true; ball_update = paddle_update = millis();
}
uint8_t new_x = ball_x + ball_dir_x; uint8_t new_y = ball_y + ball_dir_y;
if (new_x == 0 || new_x == 127) handleVerticalWallCollision(new_x); if (new_y == 0 || new_y == 63) { soundBounce(); ball_dir_y = -ball_dir_y; new_y += ball_dir_y * 2; }
if ((new_x == PLAYER2_X && new_y >= player2_y && new_y <= player2_y + PADDLE_HEIGHT) || (new_x == PLAYER_X && new_y >= player1_y && new_y <= player1_y + PADDLE_HEIGHT)) { soundBounce(); ball_dir_x = -ball_dir_x; new_x += ball_dir_x * 2; }
ball_x = new_x; ball_y = new_y; ball_update += BALL_RATE;
}
paddle_update += PADDLE_RATE;
int val2 = analogRead(player2); if (val2 < player2_center - DEADZONE) player2_y--; if (val2 > player2_center + DEADZONE) player2_y++; constrainPaddlePosition(player2_y);
int val1 = analogRead(player1); if (val1 < player1_center - DEADZONE) player1_y--; if (val1 > player1_center + DEADZONE) player1_y++; constrainPaddlePosition(player1_y);
}
if (paddle_y < 1) paddle_y = 1; if (paddle_y + PADDLE_HEIGHT > 63) paddle_y = 63 - PADDLE_HEIGHT;
}
void handleVerticalWallCollision(uint8_t new_x) {
if (new_x == 0) { player1Score++; soundPoint(); resetBall = true; } else { player2Score++; soundPoint(); resetBall = true; } ball_dir_x = -ball_dir_x;
}
void initMusic() {
if (musicInitialized) return; char buf[12]; strcpy_P(buf, FILENAME); if (musicFile.open(buf, O_RDONLY)) { Serial.println(F("Fisier mario.txt deschis.")); } else { Serial.println(F("Eroare deschidere mario.txt")); } musicInitialized = true;
}
if (!musicInitialized) { initMusic(); return; } if (!musicFile.isOpen()) return;
unsigned long now = millis();
if (!isNotePlaying && now - noteStartTime >= pauseDuration) { if (!musicFile.available()) musicFile.rewind();
char line[20]; uint8_t idx = 0; char ch; while (musicFile.available() && idx < sizeof(line) - 1) { ch = musicFile.read(); if (ch == '\n') break; line[idx++] = ch; } line[idx] = '\0';
char* commaPtr = strchr(line, ','); if (commaPtr) { *commaPtr = '\0'; int freq = atoi(line); int dur = atoi(commaPtr + 1); noteDuration = (dur > 0) ? (wholenote / dur) : ((wholenote / abs(dur)) * 1.5); if (freq != REST) tone(BEEPER, freq); isNotePlaying = true; noteStartTime = now; } }
if (isNotePlaying && now - noteStartTime >= noteDuration * 0.9) { noTone(BEEPER); isNotePlaying = false; pauseDuration = noteDuration * 0.1; noteStartTime = now; }
}
Sunt mândru că am reușit să implementez acest proiect, rezultând într-un joc simplu dar captivant!
Fişierele se încarcă pe wiki folosind facilitatea Add Images or other files. Namespace-ul în care se încarcă fişierele este de tipul :pm:prj20??:c? sau :pm:prj20??:c?:nume_student (dacă este cazul). Exemplu: Dumitru Alin, 331CC → :pm:prj2009:cc:dumitru_alin.