This shows you the differences between two versions of the page.
|
pm:prj2024:sseverin:andrei.napruiu [2024/05/27 15:47] andrei.napruiu [Descrierea codului aplicației] |
pm:prj2024:sseverin:andrei.napruiu [2024/05/28 20:29] (current) andrei.napruiu [Rezultate Obţinute] |
||
|---|---|---|---|
| Line 64: | Line 64: | ||
| ===== Software Design ===== | ===== Software Design ===== | ||
| - | |||
| - | |||
| - | <note tip> | ||
| - | Descrierea codului aplicaţiei (firmware): | ||
| - | * mediu de dezvoltare (if any) (e.g. AVR Studio, CodeVisionAVR) | ||
| - | * librării şi surse 3rd-party (e.g. Procyon AVRlib) | ||
| - | * algoritmi şi structuri pe care plănuiţi să le implementaţi | ||
| - | * (etapa 3) surse şi funcţii implementate | ||
| - | </note> | ||
| ==== Descrierea codului aplicației ==== | ==== Descrierea codului aplicației ==== | ||
| Line 99: | Line 90: | ||
| ==== Stadiul actual al implementării software ==== | ==== Stadiul actual al implementării software ==== | ||
| - | TODO | + | Codul sursă: [[https://github.com/andreinapruiu/Pong-Game-Arduino|GitHub Link]] |
| - | Codul sursă: | + | === Funcții create și utilizate === |
| - | <code> | + | |
| - | #include <Wire.h> | + | |
| - | #include <LiquidCrystal_I2C.h> | + | |
| - | const int SW_pin = 4; // digital pin connected to switch output | + | 1. **setup** - Inițializează afișajele LCD, setează modurile pinurilor pentru butoane, LED-uri și buzzer, creează caracterul personalizat al mingii și pregătește jocul pentru selecția inițială a modului și pornirea jocului. |
| - | const int player1 = A1; // analog pin connected to Y output | + | |
| - | const int player2 = A0; // analog pin connected to Y output | + | |
| - | const unsigned long PADDLE_RATE = 45; | + | 2. **loop** - Bucla principală a jocului care gestionează mișcarea mingii, mișcarea paletelor, actualizarea scorului și apelarea funcției `drawScore` când este necesară o actualizare. |
| - | const unsigned long BALL_RATE = 0; | + | |
| - | const uint8_t PADDLE_HEIGHT = 12; | + | |
| - | int player1Score = 0; | + | |
| - | int player2Score = 0; | + | |
| - | int maxScore = 8; | + | |
| - | int BEEPER = 12; | + | |
| - | bool resetBall = false; | + | |
| - | #define SCREEN_WIDTH 16 // LCD display width, in characters | + | |
| - | #define SCREEN_HEIGHT 2 // LCD display height, in lines | + | |
| - | #define RESET_BUTTON 3 | + | |
| - | LiquidCrystal_I2C lcd(0x27, SCREEN_WIDTH, SCREEN_HEIGHT); // Set the LCD I2C address | + | 3. **drawScore** - Actualizează scorurile, cronometrul și rundele câștigate pe cel de-al doilea afișaj LCD, asigurându-se că doar părțile necesare sunt actualizate pentru a evita pâlpâirea. |
| - | void drawCourt(); | + | 4. **showStartMessage** - Afișează mesajul de pornire pe primul afișaj LCD pentru a informa jucătorii că jocul este gata de jucat. |
| - | void drawScore(); | + | |
| - | uint8_t ball_x = 8, ball_y = 1; | + | 5. **showBallPossession** - Afișează un mesaj care indică ce jucător deține mingea la începutul rundei. |
| - | uint8_t ball_dir_x = 1, ball_dir_y = 1; | + | |
| - | unsigned long ball_update; | + | |
| - | unsigned long paddle_update; | + | 6. **ledShowAndPlayMelody** - Aprinde LED-urile și redă o melodie folosind buzzer-ul când un jucător câștigă o rundă sau un joc. |
| - | const uint8_t PLAYER2_X = 2; | + | |
| - | uint8_t player2_y = 0; | + | |
| - | const uint8_t PLAYER_X = 13; | + | 7. **waitForRestart** - Afișează un mesaj care solicită jucătorilor să apese un buton pentru a începe o nouă rundă. Așteaptă până când butonul este apăsat. |
| - | uint8_t player1_y = 0; | + | |
| - | void setup() { | + | 8. **resetRound** - Resetează scorurile pentru runda curentă și pregătește jocul pentru runda următoare, afișând din nou mesajul de pornire. |
| - | lcd.init(); | + | |
| - | lcd.backlight(); | + | |
| - | unsigned long start = millis(); | + | |
| - | pinMode(BEEPER, OUTPUT); | + | |
| - | pinMode(SW_pin, INPUT); | + | |
| - | pinMode(RESET_BUTTON, INPUT_PULLUP); | + | |
| - | digitalWrite(SW_pin, HIGH); | + | |
| - | lcd.clear(); | + | |
| - | drawCourt(); | + | |
| - | drawScore(); | + | |
| - | while (millis() - start < 2000); | + | |
| - | ball_update = millis(); | + | 9. **resetGame** - Resetează toate scorurile și rundele câștigate, pregătind jocul pentru un nou meci de la început și afișează mesajul de pornire. |
| - | paddle_update = ball_update; | + | |
| - | } | + | |
| - | void loop() { | + | 10. **gameOver** - Afișează un mesaj care indică ce jucător a câștigat jocul. |
| - | bool update = false; | + | |
| - | unsigned long time = millis(); | + | |
| - | static bool up_state = false; | + | 11. **selectMode** - Permite jucătorilor să selecteze între modul single-player și multiplayer folosind joystick-ul și butonul de selecție. |
| - | static bool down_state = false; | + | |
| - | if (resetBall) | + | 12. **displayModeMenu** - Afișează meniul de selecție a modului pe cel de-al doilea afișaj LCD. |
| - | { | + | |
| - | if (player1Score == maxScore || player2Score == maxScore) | + | |
| - | { | + | |
| - | gameOver(); | + | |
| - | } | + | |
| - | else { | + | |
| - | lcd.clear(); | + | |
| - | drawScore(); | + | |
| - | drawCourt(); | + | |
| - | ball_x = random(7, 9); | + | |
| - | ball_y = random(0, 1); | + | |
| - | do | + | |
| - | { | + | |
| - | ball_dir_x = random(-1, 2); | + | |
| - | } while (ball_dir_x == 0); | + | |
| - | do | + | 13. **waitForModeSelection** - Instrucționează jucătorul să verifice cel de-al doilea afișaj pentru selecția modului și așteaptă selectarea modului. |
| - | { | + | |
| - | ball_dir_y = random(-1, 2); | + | |
| - | } while (ball_dir_y == 0); | + | |
| - | resetBall = false; | + | 14. **movePlayer2Automatically** - Mișcă automat paleta jucătorului 2 pe baza poziției mingii, utilizată în modul single-player. |
| - | } | + | |
| - | } | + | |
| - | if (time > ball_update) { | + | 15. **setup** - Inițializează jocul prin configurarea afișajelor LCD, a pinurilor de intrare/ieșire și a condițiilor de pornire pentru joc. |
| - | uint8_t new_x = ball_x + ball_dir_x; | + | |
| - | uint8_t new_y = ball_y + ball_dir_y; | + | |
| - | // Check if we hit the vertical walls | + | 16. **loop** - Bucla principală a jocului care rulează continuu, gestionând intrările jucătorilor, mișcarea mingii, actualizările scorurilor și schimbările de stare ale jocului. |
| - | if (new_x == 0 || new_x == 15) { | + | |
| - | if (new_x == 0) { | + | |
| - | player1Score += 1; | + | |
| - | lcd.clear(); | + | |
| - | soundPoint(); | + | |
| - | resetBall = true; | + | |
| - | } | + | |
| - | else if (new_x == 15) { | + | |
| - | player2Score += 1; | + | |
| - | lcd.clear(); | + | |
| - | soundPoint(); | + | |
| - | resetBall = true; | + | |
| - | } | + | |
| - | ball_dir_x = -ball_dir_x; | + | |
| - | new_x += ball_dir_x + ball_dir_x; | + | |
| - | } | + | |
| - | // Check if we hit the horizontal walls. | + | 17. **waitForRestart** - Afișează un mesaj care cere jucătorilor să apese un buton pentru a începe o nouă rundă și așteaptă apăsarea butonului. |
| - | if (new_y == 0 || new_y == 1) { | + | |
| - | soundBounce(); | + | |
| - | ball_dir_y = -ball_dir_y; | + | |
| - | new_y += ball_dir_y + ball_dir_y; | + | |
| - | } | + | |
| - | // Check if we hit the player 2 paddle | + | 18. **resetRound** - Resetează scorurile pentru runda curentă și pregătește jocul pentru o nouă rundă, afișând mesajul de pornire. |
| - | if (new_x == PLAYER2_X && new_y == player2_y) { | + | |
| - | soundBounce(); | + | |
| - | ball_dir_x = -ball_dir_x; | + | |
| - | new_x += ball_dir_x + ball_dir_x; | + | |
| - | } | + | |
| - | // Check if we hit the player 1 paddle | + | 19. **resetGame** - Resetează toate variabilele jocului la stările inițiale, pregătind pentru un nou joc. |
| - | if (new_x == PLAYER_X && new_y == player1_y) { | + | |
| - | soundBounce(); | + | |
| - | ball_dir_x = -ball_dir_x; | + | |
| - | new_x += ball_dir_x + ball_dir_x; | + | |
| - | } | + | |
| - | lcd.setCursor(ball_x, ball_y); | + | 20. **gameOver** - Afișează un mesaj care indică ce jucător a câștigat jocul. |
| - | lcd.print(" "); | + | |
| - | lcd.setCursor(new_x, new_y); | + | |
| - | lcd.print("O"); | + | |
| - | ball_x = new_x; | + | |
| - | ball_y = new_y; | + | |
| - | ball_update += BALL_RATE; | + | 21. **selectMode** - Gestionează selecția modului single-player sau multiplayer de către jucător. |
| - | update = true; | + | 22. **displayModeMenu** - Afișează meniul de selecție a modului pe cel de-al doilea afișaj LCD. |
| - | } | + | |
| - | if (time > paddle_update) { | + | 23. **waitForModeSelection** - Afișează instrucțiuni pentru a verifica al doilea afișaj pentru selecția modului și așteaptă alegerea jucătorului. |
| - | paddle_update += PADDLE_RATE; | + | |
| - | // Player 2 paddle | + | 24. **movePlayer2Automatically** - Mișcă automat paleta jucătorului 2 pentru a urmări mingea în modul single-player. |
| - | lcd.setCursor(PLAYER2_X, player2_y); | + | |
| - | lcd.print(" "); | + | |
| - | if (analogRead(player2) < 475) { | + | |
| - | player2_y = 0; | + | |
| - | } | + | |
| - | if (analogRead(player2) > 550) { | + | |
| - | player2_y = 1; | + | |
| - | } | + | |
| - | lcd.setCursor(PLAYER2_X, player2_y); | + | |
| - | lcd.print("|"); | + | |
| - | // Player 1 paddle | ||
| - | lcd.setCursor(PLAYER_X, player1_y); | ||
| - | lcd.print(" "); | ||
| - | if (analogRead(player1) < 475) { | ||
| - | player1_y = 0; | ||
| - | } | ||
| - | if (analogRead(player1) > 550) { | ||
| - | player1_y = 1; | ||
| - | } | ||
| - | up_state = down_state = false; | ||
| - | lcd.setCursor(PLAYER_X, player1_y); | ||
| - | lcd.print("|"); | ||
| - | } | ||
| - | update = true; | ||
| - | |||
| - | if (update) { | ||
| - | drawScore(); | ||
| - | if (digitalRead(SW_pin) == 0) // Player pressed button to stop the game | ||
| - | { | ||
| - | gameOver(); | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | |||
| - | // de implementat functiile | ||
| - | </code> | ||
| > Elementul de noutate al proiectului este dat de posibilitatea de a interacționa direct cu sistemul prin intermediul joystickurilor. | > Elementul de noutate al proiectului este dat de posibilitatea de a interacționa direct cu sistemul prin intermediul joystickurilor. | ||
| Line 292: | Line 150: | ||
| - [[pm:lab:lab6-2023-2024|]] | - [[pm:lab:lab6-2023-2024|]] | ||
| - | === Video Demo === | ||
| - | TODO | ||
| ===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
| - | <note tip> | + | [[https://youtu.be/NIuy8t1Exc0?si=EKHTQ3DRj8NNWOY8|Youtube Link]] |
| - | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | |
| - | </note> | + | |
| ===== Concluzii ===== | ===== Concluzii ===== | ||
| Line 305: | Line 159: | ||
| ===== Download ===== | ===== Download ===== | ||
| - | <note warning> | + | <note tip> |
| - | O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului: surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-). | + | Arhiva care conține toate fișierele create pentru acest proiect se poate descărca de pe link-ul de [[https://github.com/andreinapruiu/Pong-Game-Arduino|GitHub]]. |
| - | + | ||
| - | 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**. | + | |
| </note> | </note> | ||
| - | ===== Jurnal ===== | ||
| - | |||
| - | <note tip> | ||
| - | Puteți avea și o secțiune de jurnal în care să poată urmări asistentul de proiect progresul proiectului. | ||
| - | </note> | ||
| ===== Bibliografie/Resurse ===== | ===== Bibliografie/Resurse ===== | ||
| - | <note> | + | ==== Hardware Utilizat ==== |
| - | Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. | + | |
| - | </note> | + | 1. **Placă Arduino** |
| + | * [[https://www.optimusdigital.ro/ro/index.php?controller=attachment&id_attachment=143|Arduino Uno Fake]] | ||
| + | |||
| + | 2. **Afișaj LCD I2C** | ||
| + | * [[https://www.optimusdigital.ro/ro/index.php?controller=attachment&id_attachment=29|LCD 1602 I2C]] | ||
| + | |||
| + | 3. **Joystick-uri Analogice** | ||
| + | * [[https://www.optimusdigital.ro/ro/senzori-senzori-de-atingere/742-modul-joystick-ps2-biaxial-negru-cu-5-pini.html?search_query=joystick&results=42|Joystick Module]] | ||
| + | |||
| + | 4. **Butoane Digitale** | ||
| + | * [[https://www.adafruit.com/product/367|Push Buttons]] | ||
| + | |||
| + | 5. **Buzzer** | ||
| + | * [[https://www.adafruit.com/product/1536|Buzzer Module]] | ||
| + | |||
| + | ==== Software Utilizat ==== | ||
| + | |||
| + | 1. **Arduino IDE** | ||
| + | * [[https://www.arduino.cc/en/software|Arduino IDE Download]] | ||
| + | |||
| + | 2. **Configurare Display** | ||
| + | * [[https://lastminuteengineers.com/i2c-lcd-arduino-tutorial/?utm_content=cmp-true|I2C Display]] | ||
| + | |||
| + | 2. **Biblioteci Arduino** | ||
| + | * **Wire.h** | ||
| + | * [[https://www.arduino.cc/en/Reference/Wire|Arduino Wire Library]] | ||
| + | * **LiquidCrystal_I2C.h** | ||
| + | * [[https://github.com/johnrickman/LiquidCrystal_I2C|LiquidCrystal I2C Library]] | ||
| <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | ||