This shows you the differences between two versions of the page.
pm:prj2024:sseverin:andrei.napruiu [2024/05/23 23:48] andrei.napruiu [Software Design] |
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 89: | Line 80: | ||
- Controlul mingii în jocul Pong, incluzând detectarea coliziunilor cu pereții și paletele. | - Controlul mingii în jocul Pong, incluzând detectarea coliziunilor cu pereții și paletele. | ||
- Actualizarea scorurilor și afișarea acestora pe display. | - Actualizarea scorurilor și afișarea acestora pe display. | ||
- | - Detectarea intrărilor analogice de la potențiometre pentru controlul paletelor. | + | - Detectarea intrărilor analogice de la joystick-uri pentru controlul paletelor. |
- **Surse și funcții implementate**: | - **Surse și funcții implementate**: | ||
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> | ||