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.