Igra u kojoj se nasumično uključuju i isključuju LED, a korisnik mora ponoviti redoslijed kojim su se uključivale. Redoslijed paljenja bira se preko potenciometra za označavanje željene LED i tipkala za potvrdu odabira. Povratne informacije o igri (poraz/nova razina/pobjeda) su napravljene uz pomoć prikladnih svjetlosnih i zvučnih efekata.
Dependencies: mbed zvucniEfekti
Diff: main.cpp
- Revision:
- 0:f1138da8bd35
diff -r 000000000000 -r f1138da8bd35 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Dec 01 13:17:00 2021 +0000 @@ -0,0 +1,312 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mbed.h" +#include "zvucniEfekti.h" + +#define MAX_BROJ_SEKVENCE 10 +#define SAMPLEFREQ 8000 + +InterruptIn tipkaloFlipLED(D12); +DigitalOut ledZaProvjeru(D6); + +Ticker sampleRate; +AnalogOut zvucnik(PA_5); +AnalogIn potenciometar(A0); +DigitalIn tipkalo(D9); + +int kontrolaZvuka; // globalna varijabla za odabir koji zvuk se pušta (u + // funkciji sviraj) na piezo + +class Igra { +private: + int brojLedica; + DigitalOut *ledice; + float vrijednostiZaPotenciometar[10]; + +public: + Igra(DigitalOut *led, int brLED) { + ledice = led; + brojLedica = brLED; + + float korak = 1. / brojLedica; + for (int i = 0; i < brojLedica + 1; i++) { + if (i == 0) { + vrijednostiZaPotenciometar[i] = 0; + } else { + vrijednostiZaPotenciometar[i] = + vrijednostiZaPotenciometar[i - 1] + korak; + } + } + + tipkalo.mode(PullUp); + + srand(time(0)); + } + + /* + globalna varijabla kontrolaZvuka: + 0 -> gameStart + 1 -> nextLevel + 2 -> finalLevel + 3 -> gameWon + 4 -> gameOver + */ + void sviraj() { + static int i = 0; + + switch (kontrolaZvuka) { + case 0: + zvucnik.write_u16(zvukGameStart[i] << 8); + i++; + if (i == brojSamplovaZvukGameStart) { + i = 0; + zvucnik.write_u16(0); + sampleRate.detach(); + } + break; + + case 1: + zvucnik.write_u16(zvukNextLevel[i] << 8); + i++; + if (i == brojSamplovaZvukNextLevel) { + i = 0; + zvucnik.write_u16(0); + sampleRate.detach(); + } + break; + + case 2: + zvucnik.write_u16(zvukFinalLevel[i] << 8); + i++; + if (i == brojSamplovaZvukFinalLevel) { + i = 0; + zvucnik.write_u16(0); + sampleRate.detach(); + } + break; + + case 3: + zvucnik.write_u16(zvukGameWon[i] << 8); + i++; + if (i == brojSamplovaZvukGameWon) { + i = 0; + zvucnik.write_u16(0); + sampleRate.detach(); + } + break; + + case 4: + zvucnik.write_u16(zvukGameOver[i] << 8); + i++; + if (i == brojSamplovaZvukGameOver) { + i = 0; + zvucnik.write_u16(0); + sampleRate.detach(); + } + break; + } + } + + void generirajRandomSekvencu(int brojUzoraka, int *sekvenca) { + ugasiSveLED(); + for (int i = 0; i < brojUzoraka; i++) { + int num = (rand() % brojLedica); // random broj između 0 i brLED + sekvenca[i] = num; // spremi u sekvencu zbog kasnije usporedbe generiranog + // i pogađanog + + // upali i ugasi random LED + wait_ms(500); + ledice[num] = 1; + wait_ms(500); + ledice[num] = 0; + wait_ms(500); + } + wait(2); + } + + void spremiUnosKorisnika(int brojUzoraka, int *sekvenca) { + for (int k = 0; k < brojUzoraka; k++) { + for (;;) { + for (int i = 0; i < brojLedica; i++) { + if (potenciometar >= vrijednostiZaPotenciometar[i] && + potenciometar < vrijednostiZaPotenciometar[i + 1]) { + ledice[i] = 1; + } else { + ledice[i] = 0; + } + } + + if (tipkalo == 0) { + wait_ms(50); // debounce + if (tipkalo == 0) { + for (int j = 0; j < brojLedica; j++) { + if (ledice[j].read() == 1) { + sekvenca[k] = j; + + // da korisnih ima feedback da je ucitan njegov odabir + ledice[j] = 0; + wait_ms(500); + ledice[j] = 1; + } + } + // cekaj dok tipkalo ne ode u jedan (radi ko rising edge) + // da ove beskonacne petlje nema bi spremil 4x istu vrijednost u + // array (jer radi brzo) + do { + } while (tipkalo.read() == 0); + break; + } + } + } + } + } + /* + funkcija vraca 0 za razlicite arraye, a 1 za iste + */ + int provjeriSekvence(int *generiranaSekvenca, int *unesenaSekvenca, + int brojUzorakaSekvence) { + int i = 0; + for (i = 0; i < brojUzorakaSekvence; i++) { + if (generiranaSekvenca[i] != unesenaSekvenca[i]) { + return 0; // poraz + } + } + return 1; // sljedeca razina/pobjeda + } + + void ugasiSveLED() { + for (int i = 0; i < brojLedica; i++) { + ledice[i] = 0; + } + } + + void sljedecaRazina(int finalniLevel) { + ugasiSveLED(); + if (finalniLevel != 0) { + kontrolaZvuka = 2; + } else { + kontrolaZvuka = 1; + } + sampleRate.attach(this, &Igra::sviraj, 1.0 / SAMPLEFREQ); + for (int i = 0; i < brojLedica; i++) { + ledice[i] = 1; + wait_us(100000); + ledice[i] = 0; + } + wait_us(100000); + } + + void novaIgra() { + kontrolaZvuka = 0; + sampleRate.attach(this, &Igra::sviraj, 1.0 / SAMPLEFREQ); + wait(2); + } + + void pobjeda() { + ugasiSveLED(); + kontrolaZvuka = 3; + sampleRate.attach(this, &Igra::sviraj, 1.0 / SAMPLEFREQ); + + // chaser effekt 5x sim tam + int i = 0; + do { + + for (int j = 0; j < brojLedica; j++) { + ledice[j] = 1; + wait_us(60000); + ledice[j] = 0; + } + + for (int j = brojLedica - 1; j >= 0; + j--) // -1 jer sizeof(arr) za arr[20] npr daje 20 a zadnji element je + // 19 + { + ledice[j] = 1; + wait_us(60000); + ledice[j] = 0; + } + + i++; + } while (i < 10); + wait(2); + } + + void poraz() { + ugasiSveLED(); + kontrolaZvuka = 4; + sampleRate.attach(this, &Igra::sviraj, 1.0 / SAMPLEFREQ); + int i = 0; + do { + + for (int j = 0; j < brojLedica; j++) { + ledice[j] = 1; + } + wait_us(500000); + + ugasiSveLED(); + wait_us(500000); + + i++; + } while (i < 3); + wait(2); + } +}; + +void flipLED() { ledZaProvjeru = !ledZaProvjeru; } + +int main() { + wait(1); + tipkaloFlipLED.mode(PullUp); + tipkaloFlipLED.rise(&flipLED); + // inicijalizacija pinova za igru + DigitalOut led[] = {D2, D4, D7, D8, D10, D11}; + int brojLedica = sizeof(led) / sizeof(led[0]); + + // spremanje generiranih i unesenih vrijednosti + int generiranaSekvenca[MAX_BROJ_SEKVENCE] = {0}; + int unosKorisnika[MAX_BROJ_SEKVENCE] = {0}; + + // postavke i logika igre + int brojUzorakaSekvence = 3; // kolko puta se LED pale/gase + int pobjedaPorazZastavica; + int trenutniLevel = 0; + int finalniLevel = 2; + + Igra igra(led, brojLedica); + + while (true) { + if (trenutniLevel == 0) { + igra.novaIgra(); + } + igra.generirajRandomSekvencu(brojUzorakaSekvence, generiranaSekvenca); + igra.spremiUnosKorisnika(brojUzorakaSekvence, unosKorisnika); + pobjedaPorazZastavica = igra.provjeriSekvence( + generiranaSekvenca, unosKorisnika, brojUzorakaSekvence); + + switch (pobjedaPorazZastavica) { + case 0: + igra.poraz(); + brojUzorakaSekvence = 3; + trenutniLevel = 0; + break; + case 1: + if (trenutniLevel == finalniLevel - 1) { + igra.sljedecaRazina(1); // 1 -> šalji zvuk finalLevel + brojUzorakaSekvence++; + trenutniLevel++; + } else if (trenutniLevel == finalniLevel) { + igra.pobjeda(); + brojUzorakaSekvence = 3; + trenutniLevel = 0; + } else { + igra.sljedecaRazina(0); // 0 -> šalji zvuk nextLevel + brojUzorakaSekvence++; + trenutniLevel++; + } + break; + } + } +}