This shows you the differences between two versions of the page.
pm:prj2022:cstan:endless_runner [2022/05/27 11:13] catalina.maftei [Rezultate Obţinute] |
pm:prj2022:cstan:endless_runner [2022/06/01 22:43] (current) catalina.maftei [Jurnal] |
||
---|---|---|---|
Line 9: | Line 9: | ||
Endless Runner este un joc interactiv. | Endless Runner este un joc interactiv. | ||
- | Printr-o simpla apasare de buton, jocul incepe iar jucatorul trebuie sa se concentreze pentru a reusi sa sara peste toate obstacolele. Cu fiecare apasare pe buton, personajul din joc sare peste obiecte, iar scorul se mareste. In momentul in care jucatorul a atins un obiect,jocul se termina si se afiseaza scorul final . | + | Printr-o simpla apasare de buton, jocul incepe iar jucatorul trebuie sa se concentreze pentru a reusi sa sara peste toate obstacolele. Cu fiecare apasare pe buton, personajul din joc sare peste obiecte, iar scorul se mareste. In momentul in care jucatorul a atins un obiect,jocul se termina si se afiseaza scorul final si se aude un mic sunet sa te anunte ca ai pierdut. |
+ | Daca jucatorul doreste sa reporneasca jocul, trebuie sa apese pe buton dupa ce afiseaza pe ecran textul "Game Over. Start a new game" si sa astepte 5 secunde, iar mai apoi jocul va reporni. | ||
</note> | </note> | ||
Line 30: | Line 31: | ||
Lista de Componente: | Lista de Componente: | ||
- Arduino UNO | - Arduino UNO | ||
- | - 16 x 2 Character LCD: https://www.banggood.com/custlink/vDm... | + | - 16 x 2 Character LCD |
- Breadboard | - Breadboard | ||
- Jumper Wires | - Jumper Wires | ||
- | - Push Button: https://www.banggood.com/custlink/3KD... | + | - Button |
- Battery Connector | - Battery Connector | ||
- | - 9V Battery | + | - Buzzer |
- | - Variable Resistors 103 | + | |
Schema : | Schema : | ||
- | {{ :pm:prj2022:cstan:whatsapp_image_2022-04-21_at_20.56.31.jpeg?300 |}} | + | {{ :pm:prj2022:cstan:schemaa.png?300 |}} |
</note> | </note> | ||
Line 50: | Line 50: | ||
Pe partea de Software Design, pot spune ca am inclus biblioteca folosita LiquidCrystal.h pentru utilizarea LCD 16×2. | Pe partea de Software Design, pot spune ca am inclus biblioteca folosita LiquidCrystal.h pentru utilizarea LCD 16×2. | ||
- | #include <LiquidCrystal.h> | + | {{:pm:prj2022:cstan:cod.txt|}} |
- | #define PIN_BUTTON 2 | + | </note> |
- | #define PIN_AUTOPLAY 1 | + | ===== Rezultate Obţinute ===== |
- | #define PIN_READWRITE 10 | + | <note tip> |
+ | In urma realizarii proiectului,rezultatele au fost cele dorite reusind sa ma joc propriul meu joc Chrome Dino . | ||
- | #define PIN_CONTRAST 12 | + | {{ :pm:prj2022:cstan:1.jpeg?300 |}} |
- | #define SPRITE_RUN1 1 | + | {{ :pm:prj2022:cstan:2.jpeg?300 |}} |
- | #define SPRITE_RUN2 2 | + | {{ :pm:prj2022:cstan:3.jpeg?300 |}} |
+ | </note> | ||
- | #define SPRITE_JUMP 3 | ||
- | #define SPRITE_JUMP_UPPER '.' // Use the '.' character for the head | ||
- | #define SPRITE_JUMP_LOWER 4 | + | ===== Jurnal ===== |
- | #define SPRITE_TERRAIN_EMPTY ' ' // User the ' ' character | + | <note> |
- | #define SPRITE_TERRAIN_SOLID 5 | + | Initial, jocul a fost gandit in alt mod, dar dintr-o mica problema cu LCD-ul a trebuit sa fie schimbat si sa ajunga la aceasta forma finala. |
- | + | ||
- | #define SPRITE_TERRAIN_SOLID_RIGHT 6 | + | |
- | + | ||
- | #define SPRITE_TERRAIN_SOLID_LEFT 7 | + | |
- | + | ||
- | #define HERO_HORIZONTAL_POSITION 1 // Horizontal position of hero on screen | + | |
- | + | ||
- | #define TERRAIN_WIDTH 16 | + | |
- | + | ||
- | #define TERRAIN_EMPTY 0 | + | |
- | + | ||
- | #define TERRAIN_LOWER_BLOCK 1 | + | |
- | + | ||
- | #define TERRAIN_UPPER_BLOCK 2 | + | |
- | + | ||
- | #define HERO_POSITION_OFF 0 // Hero is invisible | + | |
- | + | ||
- | #define HERO_POSITION_RUN_LOWER_1 1 // Hero is running on lower row (pose 1) | + | |
- | + | ||
- | #define HERO_POSITION_RUN_LOWER_2 2 // (pose 2) | + | |
- | + | ||
- | #define HERO_POSITION_JUMP_1 3 // Starting a jump | + | |
- | + | ||
- | #define HERO_POSITION_JUMP_2 4 // Half-way up | + | |
- | + | ||
- | #define HERO_POSITION_JUMP_3 5 // Jump is on upper row | + | |
- | + | ||
- | #define HERO_POSITION_JUMP_4 6 // Jump is on upper row | + | |
- | + | ||
- | #define HERO_POSITION_JUMP_5 7 // Jump is on upper row | + | |
- | + | ||
- | #define HERO_POSITION_JUMP_6 8 // Jump is on upper row | + | |
- | + | ||
- | #define HERO_POSITION_JUMP_7 9 // Half-way down | + | |
- | + | ||
- | #define HERO_POSITION_JUMP_8 10 // About to land | + | |
- | + | ||
- | #define HERO_POSITION_RUN_UPPER_1 11 // Hero is running on upper row (pose 1) | + | |
- | + | ||
- | #define HERO_POSITION_RUN_UPPER_2 12 // (pose 2) | + | |
- | + | ||
- | LiquidCrystal lcd(11, 9, 6, 5, 4, 3); | + | |
- | + | ||
- | static char terrainUpper[TERRAIN_WIDTH + 1]; | + | |
- | + | ||
- | static char terrainLower[TERRAIN_WIDTH + 1]; | + | |
- | + | ||
- | static bool buttonPushed = false; | + | |
- | + | ||
- | void initializeGraphics(){ | + | |
- | static byte graphics[] = { | + | |
- | // Run position 1 | + | |
- | B01100, | + | |
- | B01100, | + | |
- | B00000, | + | |
- | B01110, | + | |
- | B11100, | + | |
- | B01100, | + | |
- | B11010, | + | |
- | B10011, | + | |
- | // Run 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 i; | + | |
- | // Skip using character 0, this allows lcd.print() to be used to | + | |
- | + | ||
- | // quickly draw multiple characters | + | |
- | + | ||
- | for (i = 0; i < 7; ++i) { | + | |
- | lcd.createChar(i + 1, &graphics[i * 8]); | + | |
- | } | + | |
- | for (i = 0; i < TERRAIN_WIDTH; ++i) { | + | |
- | terrainUpper[i] = SPRITE_TERRAIN_EMPTY; | + | |
- | terrainLower[i] = SPRITE_TERRAIN_EMPTY; | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | // Slide the terrain to the left in half-character increments | + | |
- | // | + | |
- | void advanceTerrain(char* terrain, byte newTerrain){ | + | |
- | for (int i = 0; i < TERRAIN_WIDTH; ++i) { | + | |
- | char current = terrain[i]; | + | |
- | char next = (i == TERRAIN_WIDTH-1) ? newTerrain : terrain[i+1]; | + | |
- | switch (current){ | + | |
- | case SPRITE_TERRAIN_EMPTY: | + | |
- | terrain[i] = (next == SPRITE_TERRAIN_SOLID) ? SPRITE_TERRAIN_SOLID_RIGHT : SPRITE_TERRAIN_EMPTY; | + | |
- | break; | + | |
- | case SPRITE_TERRAIN_SOLID: | + | |
- | terrain[i] = (next == SPRITE_TERRAIN_EMPTY) ? SPRITE_TERRAIN_SOLID_LEFT : SPRITE_TERRAIN_SOLID; | + | |
- | break; | + | |
- | case SPRITE_TERRAIN_SOLID_RIGHT: | + | |
- | terrain[i] = SPRITE_TERRAIN_SOLID; | + | |
- | break; | + | |
- | case SPRITE_TERRAIN_SOLID_LEFT: | + | |
- | terrain[i] = SPRITE_TERRAIN_EMPTY; | + | |
- | break; | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | bool drawHero(byte position, char* terrainUpper, char* terrainLower, unsigned int score) { | + | |
- | bool collide = false; | + | |
- | char upperSave = terrainUpper[HERO_HORIZONTAL_POSITION]; | + | |
- | char lowerSave = terrainLower[HERO_HORIZONTAL_POSITION]; | + | |
- | byte upper, lower; | + | |
- | switch (position) { | + | |
- | case HERO_POSITION_OFF: | + | |
- | upper = lower = SPRITE_TERRAIN_EMPTY; | + | |
- | break; | + | |
- | case HERO_POSITION_RUN_LOWER_1: | + | |
- | upper = SPRITE_TERRAIN_EMPTY; | + | |
- | lower = SPRITE_RUN1; | + | |
- | break; | + | |
- | case HERO_POSITION_RUN_LOWER_2: | + | |
- | upper = SPRITE_TERRAIN_EMPTY; | + | |
- | lower = SPRITE_RUN2; | + | |
- | break; | + | |
- | case HERO_POSITION_JUMP_1: | + | |
- | case HERO_POSITION_JUMP_8: | + | |
- | upper = SPRITE_TERRAIN_EMPTY; | + | |
- | lower = SPRITE_JUMP; | + | |
- | break; | + | |
- | case HERO_POSITION_JUMP_2: | + | |
- | case HERO_POSITION_JUMP_7: | + | |
- | upper = SPRITE_JUMP_UPPER; | + | |
- | lower = SPRITE_JUMP_LOWER; | + | |
- | break; | + | |
- | case HERO_POSITION_JUMP_3: | + | |
- | case HERO_POSITION_JUMP_4: | + | |
- | case HERO_POSITION_JUMP_5: | + | |
- | case HERO_POSITION_JUMP_6: | + | |
- | upper = SPRITE_JUMP; | + | |
- | lower = SPRITE_TERRAIN_EMPTY; | + | |
- | break; | + | |
- | case HERO_POSITION_RUN_UPPER_1: | + | |
- | upper = SPRITE_RUN1; | + | |
- | lower = SPRITE_TERRAIN_EMPTY; | + | |
- | break; | + | |
- | case HERO_POSITION_RUN_UPPER_2: | + | |
- | upper = SPRITE_RUN2; | + | |
- | lower = SPRITE_TERRAIN_EMPTY; | + | |
- | break; | + | |
- | } | + | |
- | if (upper != ' ') { | + | |
- | terrainUpper[HERO_HORIZONTAL_POSITION] = upper; | + | |
- | collide = (upperSave == SPRITE_TERRAIN_EMPTY) ? false : true; | + | |
- | } | + | |
- | if (lower != ' ') { | + | |
- | terrainLower[HERO_HORIZONTAL_POSITION] = lower; | + | |
- | collide |= (lowerSave == SPRITE_TERRAIN_EMPTY) ? false : true; | + | |
- | } | + | |
- | + | ||
- | byte digits = (score > 9999) ? 5 : (score > 999) ? 4 : (score > 99) ? 3 : (score > 9) ? 2 : 1; | + | |
- | + | ||
- | // Draw the scene | + | |
- | + | ||
- | terrainUpper[TERRAIN_WIDTH] = '\0'; | + | |
- | + | ||
- | terrainLower[TERRAIN_WIDTH] = '\0'; | + | |
- | + | ||
- | char temp = terrainUpper[16-digits]; | + | |
- | + | ||
- | terrainUpper[16-digits] = '\0'; | + | |
- | + | ||
- | lcd.setCursor(0,0); | + | |
- | + | ||
- | lcd.print(terrainUpper); | + | |
- | + | ||
- | terrainUpper[16-digits] = temp; | + | |
- | + | ||
- | lcd.setCursor(0,1); | + | |
- | + | ||
- | lcd.print(terrainLower); | + | |
- | + | ||
- | lcd.setCursor(16 - digits,0); | + | |
- | lcd.print(score); | + | |
- | + | ||
- | + | ||
- | terrainUpper[HERO_HORIZONTAL_POSITION] = upperSave; | + | |
- | + | ||
- | terrainLower[HERO_HORIZONTAL_POSITION] = lowerSave; | + | |
- | + | ||
- | return collide; | + | |
- | } | + | |
- | + | ||
- | // Handle the button push as an interrupt | + | |
- | void buttonPush() { | + | |
- | buttonPushed = true; | + | |
- | } | + | |
- | + | ||
- | void setup(){ | + | |
- | pinMode(PIN_READWRITE, OUTPUT); | + | |
- | digitalWrite(PIN_READWRITE, LOW); | + | |
- | pinMode(PIN_CONTRAST, OUTPUT); | + | |
- | digitalWrite(PIN_CONTRAST, LOW); | + | |
- | pinMode(PIN_BUTTON, INPUT); | + | |
- | digitalWrite(PIN_BUTTON, HIGH); | + | |
- | pinMode(PIN_AUTOPLAY, OUTPUT); | + | |
- | digitalWrite(PIN_AUTOPLAY, HIGH); | + | |
- | + | ||
- | // Digital pin 2 maps to interrupt 0 | + | |
- | attachInterrupt(0/*PIN_BUTTON*/, buttonPush, FALLING); | + | |
- | + | ||
- | initializeGraphics(); | + | |
- | + | ||
- | lcd.begin(16, 2); | + | |
- | } | + | |
- | + | ||
- | void loop(){ | + | |
- | static byte heroPos = HERO_POSITION_RUN_LOWER_1; | + | |
- | static byte newTerrainType = TERRAIN_EMPTY; | + | |
- | static byte newTerrainDuration = 1; | + | |
- | static bool playing = false; | + | |
- | static bool blink = false; | + | |
- | static unsigned int distance = 0; | + | |
- | + | ||
- | if (!playing) { | + | |
- | drawHero((blink) ? HERO_POSITION_OFF : heroPos, terrainUpper, terrainLower, distance >> 3); | + | |
- | if (blink) { | + | |
- | lcd.setCursor(0,0); | + | |
- | lcd.print("Game Over"); | + | |
- | } | + | |
- | delay(250); | + | |
- | blink = !blink; | + | |
- | if (buttonPushed) { | + | |
- | initializeGraphics(); | + | |
- | heroPos = HERO_POSITION_RUN_LOWER_1; | + | |
- | playing = true; | + | |
- | buttonPushed = false; | + | |
- | distance = 0; | + | |
- | } | + | |
- | return; | + | |
- | } | + | |
- | + | ||
- | // Shift the terrain to the left | + | |
- | advanceTerrain(terrainLower, newTerrainType == TERRAIN_LOWER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY); | + | |
- | + | ||
- | advanceTerrain(terrainUpper, newTerrainType == TERRAIN_UPPER_BLOCK ? SPRITE_TERRAIN_SOLID : SPRITE_TERRAIN_EMPTY); | + | |
- | + | ||
- | // Make new terrain to enter on the right | + | |
- | if (--newTerrainDuration == 0) { | + | |
- | if (newTerrainType == TERRAIN_EMPTY) { | + | |
- | newTerrainType = (random(3) == 0) ? TERRAIN_UPPER_BLOCK : TERRAIN_LOWER_BLOCK; | + | |
- | newTerrainDuration = 2 + random(10); | + | |
- | } else { | + | |
- | newTerrainType = TERRAIN_EMPTY; | + | |
- | newTerrainDuration = 10 + random(10); | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | if (buttonPushed) { | + | |
- | if (heroPos <= HERO_POSITION_RUN_LOWER_2) heroPos = HERO_POSITION_JUMP_1; | + | |
- | buttonPushed = false; | + | |
- | } | + | |
- | + | ||
- | if (drawHero(heroPos, terrainUpper, terrainLower, distance >> 3)) { | + | |
- | playing = false; // The hero collided with something. Too bad. | + | |
- | } else { | + | |
- | if (heroPos == HERO_POSITION_RUN_LOWER_2 || heroPos == HERO_POSITION_JUMP_8) { | + | |
- | heroPos = HERO_POSITION_RUN_LOWER_1; | + | |
- | } else if ((heroPos >= HERO_POSITION_JUMP_3 && heroPos <= HERO_POSITION_JUMP_5) && terrainLower[HERO_HORIZONTAL_POSITION] != SPRITE_TERRAIN_EMPTY) { | + | |
- | heroPos = HERO_POSITION_RUN_UPPER_1; | + | |
- | } else if (heroPos >= HERO_POSITION_RUN_UPPER_1 && terrainLower[HERO_HORIZONTAL_POSITION] == SPRITE_TERRAIN_EMPTY) { | + | |
- | heroPos = HERO_POSITION_JUMP_5; | + | |
- | } else if (heroPos == HERO_POSITION_RUN_UPPER_2) { | + | |
- | heroPos = HERO_POSITION_RUN_UPPER_1; | + | |
- | } else { | + | |
- | ++heroPos; | + | |
- | } | + | |
- | ++distance; | + | |
- | + | ||
- | digitalWrite(PIN_AUTOPLAY, terrainLower[HERO_HORIZONTAL_POSITION + 2] == SPRITE_TERRAIN_EMPTY ? HIGH : LOW); | + | |
- | } | + | |
- | delay(100); | + | |
- | } | + | |
+ | Acestea sunt cateva poze de pe parcursul realizarii acestui proiect: | ||
+ | {{ :pm:prj2022:cstan:whatsapp_image_2022-05-27_at_11.11.58.jpeg?300 |}} | ||
+ | {{ :pm:prj2022:cstan:whatsapp_image_2022-05-27_at_11.11.59.jpeg?300 |}} | ||
+ | A fost o reala provocare sa incerc sa modific proiectul din forma initiala gandita pentru a ajunge la aceasta forma finala, dar totul a meritat. | ||
+ | {{ :pm:prj2022:cstan:1.jpeg?300 |}} | ||
</note> | </note> | ||
- | ===== Rezultate Obţinute ===== | + | ===== Concluzii ===== |
- | <note tip> | + | <note> |
- | In urma realizarii proiectului,rezultatele au fost cele dorite reusind sa ma joc propriul meu joc Chrome Dino . | + | A fost un proiect la care am lucrat cu drag si am reusit sa ma descurc singura. A fost un lucru nou pe care l-am facut dar care m-a atras foarte mult si care a reusit sa imi capteze atentia imediat. |
- | {{ :pm:prj2022:cstan:whatsapp_image_2022-05-27_at_11.11.58.jpeg?300 |}} | ||
- | |||
- | {{ :pm:prj2022:cstan:whatsapp_image_2022-05-27_at_11.11.59.jpeg?300 |}} | ||
</note> | </note> | ||
- | ===== Concluzii ===== | + | ===== Bibliografie/Resurse ===== |
<note> | <note> | ||
- | A fost un proiect la care am lucrat cu drag si am reusit sa ma descurc singura. A fost un lucru nou pe care l-am facut dar care m-a atras foarte mult si care a reusit sa imi capteze atentia imediat. | + | https://www.youtube.com/watch?v=09RtqG4561o&ab_channel=IdeasTV |
+ | </note> | ||
- | </note> | ||
- | ===== Download ===== | ||
- | <note warning> | ||
- | 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ă ;-). | ||
- | 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> | ||
- | ===== Jurnal ===== | + | ===== Download ===== |
- | <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 ===== | + | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> |
- | <note> | ||
- | https://www.youtube.com/watch?v=09RtqG4561o&ab_channel=IdeasTV | ||
- | </note> | ||
- | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | ||