2018 US Projekt - Stack Attack (Grupa 9) Haris Salman Amir Muminović Glavni program.
Dependencies: SPI_TFT_ILI9341 Sprites TFT_fonts mbed
Diff: main.cpp
- Revision:
- 0:88e77eadd8e1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Jul 02 20:23:26 2018 +0000 @@ -0,0 +1,400 @@ +#include "mbed.h" +#include "stdio.h" +#include "string" +#include "vector" + +#include "SPI_TFT_ILI9341.h" +#include "GraphicsDisplay.h" + +#include "Arial12x12.h" +#include "Arial24x23.h" +#include "Arial28x28.h" +#include "font_big.h" + +#include "Sprites.h" + +// Konstante: Velicina kutije, padding sa lijeva +#define BoxSize 30 +#define LPAD 10 + +using std::vector; + +// MOSI, MISO, SCK, CS, RESET, DC, NAME +SPI_TFT_ILI9341 display(PTD2, PTD3, PTD1, PTE2, PTA20, PTD5, "display"); +AnalogIn Jx(PTB1); +AnalogIn Jy(PTB2); +DigitalIn BTN(PTE5); +Timer deb; + +// Master ticker za igru +Ticker gridTicker; + +vector<vector<bool> > mapa; + +double OffsetX, OffsetY; +bool paused(false); +bool gameover(false); +bool toggleDraw(true); + +int generateRandom(); +void gameOver(); + +class Claw { + int position, target; + bool hasBox; + double moveTime; // Vrijeme neophodno da se ruka pomjeri sa jedne lokacije na drugu, u milisekundama +public: + Claw() : position(0), target(generateRandom()), hasBox(true), moveTime(1000) {} + + void GiveBox() { + if (position == 0 && !hasBox){ + hasBox = true; + target = generateRandom(); + } + } + + void MoveClaw() { + GiveBox(); + if (target > position) position++; + else if (target < position) position--; + else if (target == position) BaciBox(); + } + + void BaciBox() { + hasBox = false; + if (mapa[5][position]){ + bool kraj(true); + for(int i(0); i<5; i++) if(mapa[i][position]==0) kraj=false; + if(kraj) gameOver(); + } + mapa[5][position] = true; // Dodaj kutiju u + target = 0; // Pokupi novu na pocetku + } + + void DrawClaw() { + // x0 y0 sirina visina *bitmap + if(!hasBox) display.Bitmap(position*BoxSize + LPAD, 0, BoxSize, BoxSize, claw); + else display.Bitmap(position*BoxSize + LPAD, 0, BoxSize, BoxSize, clawBoxColor); + } + + void drawBlank(){ + display.fillrect(position*BoxSize + LPAD, 0, position*BoxSize + BoxSize + LPAD, BoxSize, White); + } + + void TickerFja(){ + drawBlank(); + MoveClaw(); + DrawClaw(); + } +}; + +class Player{ + short int x, y; +public: + Player() : x(5),y(0){} + + void PomjeriDesno(){ + if(x < 9){ //Ako moze jos ici desno + if (mapa[y][x+1] == 0 && mapa[y+1][x+1] == 0){ //Ako desno nije kutija + drawBlank(y,x); drawBlank(y+1,x); + x++; + } + else{ // Ako jeste kutija + if (x+1 < 9){ // Ako nije kutija na kraju + if (mapa[y][x+2] == 0 && mapa[y+1][x+1] == 0){ // Ako ima mjesta za pomjeranje kutije + drawBlank(y,x); drawBlank(y+1,x); + x++; //Update lokacije + mapa[y][x] = 0; //Brisi kutiju + mapa[y][x+1] = 1; //Pomjeri kutiju na novu lokaciju + } + } + } + } + } + + void PomjeriLijevo(){ + if(x > 0){ //Ako moze jos ici lijevo + if (mapa[y][x-1] == 0 && mapa[y+1][x-1] == 0){ // Ako lijevo nije kutija + drawBlank(y,x); drawBlank(y+1,x); + x--; + } else { // Ako jeste kutija + if (x-1 > 0){ //Ako nije kutija na kraju + if (mapa[y][x-2] == 0 && mapa[y+1][x-1] == 0){ // Ako ima mjesta za pomjeranje kutije + drawBlank(y,x); drawBlank(y+1,x); + x--; //Update lokacije + mapa[y][x] = 0; //Brisi kutiju + mapa[y][x-1] = 1; //Pomjeri kutiju na novu lokaciju + } + } + } + } + } + + void PomjeriGore(){ + // Provjeri da ima od sta ispod sebe da odskoci, kao i ako je dosao do vrha + if(y == 0 || (y < 6 && mapa[y-1][x] == 1)){ + drawBlank(y,x); + y++; + } + } + + void PomjeriGoreDesno(){ + if(y == 0 || (y < 6 && mapa[y-1][x] == 1)){ + if (x < 9 && y < 6){ //Ima prostora za skok + if (mapa[y+1][x+1] == 0){ // Pomjeri igraca ako nema kutije + drawBlank(y,x); drawBlank(y+1,x); + x++; + y++; + } + else { // Ako ima kutije, pomakni kutiju + if (x < 8){ // Ako nije boundary + if (mapa[y+1][x+2] == 0) {// Ako se moze pomaci desno + drawBlank(y,x); drawBlank(y+1,x); + x++; + y++; + mapa[y][x] = 0; // Nema tu kutije + mapa[y][x+1] = 1; // Sad je pomaknuta desno + } + } + } + } + } + } + + void PomjeriGoreLijevo(){ + if(y == 0 || (y < 6 && mapa[y-1][x] == 1)){ + if (x > 0 && y < 6){ //Ima prostora za skok + if (mapa[y+1][x-1] == 0){ // Pomjeri igraca ako nema kutije + drawBlank(y,x); drawBlank(y+1,x); + x--; + y++; + } + else { // Ako ima kutije, pomakni kutiju + if (x - 2 > 0){ // Ako nije boundary + if (mapa[y+1][x-2] == 0) {// Ako se moze pomaci desno + drawBlank(y,x); drawBlank(y+1,x); + x--; + y++; + mapa[y][x] = 0; // Nema tu kutije + mapa[y][x-1] = 1; // Sad je pomaknuta desno + } + } + } + } + } + } + + void DaLiJeZiv(){ + if (mapa[y+1][x]) gameOver(); + } + + int GetX(){ return x; } + int GetY(){ return y; } + void SetX(int Ox){ x = Ox; } + void SetY(int Oy){ y = Oy; } + + void drawPlayer(){ + // x0 y0 širina visina *bitmap + display.Bitmap(x*BoxSize + LPAD + 1, (5-y)*BoxSize, BoxSize, 2*BoxSize + 1, charColor); + } + + void drawBlank(int row, int column){ + display.fillrect(row*BoxSize + LPAD + 1, column*BoxSize, row*BoxSize + BoxSize + LPAD, column*BoxSize + BoxSize - 1, White); + } +}; + +// Vraca random broj od 0 do 99 jer FRDM nema sat za random seed +int generateRandom(){ + int random(int((Jx+Jy+1) * (rand()%100))%10); + if(random < 0) random *= -1; + return random; +} + +class Grid{ + Player p; + Claw c; + int score; +public: + Grid(){ setupMap(); } + + Player& Igrac(){ return p; } + + void setupMap(){ + p.SetX(5); + p.SetY(0); + score = 0; + mapa.resize(0); + vector<bool> novi(10, false); + for (int i(0); i < 6; i++) mapa.push_back(novi); + + mapa[0][0] = mapa[0][1] = mapa[0][7] = true; + } + + int GetScore(){ return score; } + + void gravity(){ + if(p.GetY()>0 && !mapa[p.GetY()-1][p.GetX()]) p.SetY(p.GetY()-1); + } + + void masterTicker(){ + /*if(BTN){ + gridTicker.detach(); + pause(); + gridTicker.attach(this, &Grid::masterTicker, 1); + }*/ + c.TickerFja(); + readJoystick(); + p.drawPlayer(); + drawMap(); + } + + void drawMap(){ + drawBorders(); + displayScore(); + + // Crtanje mape ovisno o matrici prisustva + for(int i(0); i<6; i++){ + for(int j(0); j<10; j++){ + if(mapa[i][j]) drawBox(j, 6-i); + else if((i==p.GetY() || i==p.GetY()+1) && j==p.GetX()) continue; + else drawBlank(j, 6-i); + } + } + calculatePoints(); + if(toggleDraw = !toggleDraw) refreshMapa(); + p.DaLiJeZiv(); + } + + void refreshMapa(){ + // Kad padaju kutije, treba se pozivati svaku sekundu + // Gravitacija igrača + gravity(); + for(int i(1); i<6; i++){ + for(int j(0); j<10; j++){ + if (mapa[i][j] && !mapa[i-1][j]){ + mapa[i][j] = false; + mapa[i-1][j] = true; + } + } + } + } + + void calculatePoints(){ + bool rowFull(true); + // Vidi kakvo je stanje + for (int i(0); i < 10; i++){ + if (mapa[0][i] == 0) rowFull = false; + } + // Ako je red pun, briši sve i dodaj bodove + if (rowFull){ + for (int i(0); i < 10; i++) mapa[0][i] = 0; + score += 100; + displayScore(); + } + } + + void drawBox(int row, int column){ + display.rect(row*BoxSize + LPAD, column*BoxSize, row*BoxSize + BoxSize + LPAD, column*BoxSize + BoxSize, Black); + display.line(row*BoxSize + LPAD, column*BoxSize, row*BoxSize + BoxSize + LPAD, column*BoxSize + BoxSize, Black); + display.line(row*BoxSize + BoxSize + LPAD, column*BoxSize, row*BoxSize + LPAD, column*BoxSize + BoxSize, Black); + } + + void drawBlank(int row, int column){ + display.fillrect(row*BoxSize + LPAD + 1, column*BoxSize, row*BoxSize + BoxSize + LPAD, column*BoxSize + BoxSize - 1, White); + } + + // Nacrtaj granice igre + void drawBorders(){ + display.line(LPAD - 1, 0, LPAD - 1, 211, Black); // Lijeva granica + display.line(311, 0, 311, 210, Black); // Desna granica + display.line(LPAD - 1, 211, 311, 211, Black); // Donja granica + } + + void displayScore(){ + display.locate(166, 219); + display.printf("SCORE:%6d", score); + } + + void readJoystick(){ + // Debouncing džojstika + if(deb.read_ms()<0.4) return; + deb.reset(); + + int x = Jx*3.3 - 0.4; // 0 = Lijevo, 1 = Ništa, 2 = Desno + int y = Jy*3.3 - 0.4; // 0 = Dole, 1 = Ništa, 2 = Gore + + if(x == 0){ + if(y == 0) p.PomjeriGoreLijevo(); + else p.PomjeriLijevo(); + } else if(x == 2){ + if(y == 0) p.PomjeriGoreDesno(); + else p.PomjeriDesno(); + } else if(y == 0) p.PomjeriGore(); + } +}; + +Grid g; + +// Iskljuceno radi problema sa InterruptIn +void pause(){ + // Resetuje igru ako je trenutno kraj + if(gameover){ + gameover = false; + display.cls(); + g.setupMap(); + return; + } + + if(deb.read_ms()>1000){ + // Toggle trenutno stanje pauze + paused = !paused; + + if(paused){ + display.locate(LPAD, 219); + display.printf("PAUZA"); + while(paused); + } else { + // Obriši tekst za pauzu, nastavi igru + display.fillrect(LPAD, 219, 70, 231, White); + } + } + deb.reset(); +} + +void gameOver(){ + gridTicker.detach(); + gameover = true; + display.cls(); + + display.locate(58, 100); + display.set_font((unsigned char*) Arial28x28); + display.printf("GAME OVER"); + display.set_font((unsigned char*) Arial12x12); + display.locate(100, 140); + display.printf("SCORE:%6d", g.GetScore()); + //display.locate(70, 180); + //display.printf("Press Joystick to restart..."); + + while(1){ + if(gameover) wait(0.1); + else break; + } +} + +// -------------------------------------------------------------------------- // + +int main() { + display.claim(stdout); + display.set_orientation(1); + display.background(White); + display.foreground(Black); + display.cls(); + display.set_font((unsigned char*) Arial12x12); + + deb.start(); + gridTicker.attach(&g, &Grid::masterTicker, 0.25); + + while(1) { + wait(1); + } +} \ No newline at end of file