Erts

Dependencies:   BSP_DISCO_F413ZH

Revision:
0:a3870e86460b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Feb 06 10:16:50 2022 +0100
@@ -0,0 +1,304 @@
+#include "mbed.h"
+#include "stm32f413h_discovery_lcd.h"
+
+#define SCREEN_REFRESH_PERIOD 0.15
+#define START_SNAKE_LENGTH 4
+#define GAME_BG (uint16_t)0x010200
+
+enum Mode{
+    MAIN_MENU,
+    GAME,
+    END_GAME
+};
+
+enum Dirrection {
+    LEFT, UP, RIGHT, DOWN
+};
+
+// simulator
+// InterruptIn bLeft(p5);
+// InterruptIn bUp(p6);
+// InterruptIn bRight(p7);
+// InterruptIn bDown(p8);
+// PwmOut speaker(p21);
+// PwmOut led(p9);
+// DigitalIn toggglePause(p10);
+// real device
+InterruptIn bLeft(PA_1);
+InterruptIn bUp(PA_2);
+InterruptIn bRight(PA_3);
+InterruptIn bDown(PA_4);
+PwmOut speaker(PA_5);
+PwmOut led(PA_6);
+DigitalIn toggglePause(PA_7);
+
+Timeout alertTimeout;
+Ticker gameTicker;
+Ticker mainTicker;
+
+Mode mode = MAIN_MENU;
+Dirrection direction = UP;
+
+#define MAX_X 34
+#define MAX_Y 34
+
+int X[MAX_X*MAX_Y] = {5, 5, 5, 5};
+int Y[MAX_X*MAX_Y] = {30, 29, 28, 27};
+
+int targetX, targetY;
+
+int snakeLength = START_SNAKE_LENGTH;
+int score = 0;
+
+bool isEndGame = true;
+
+void drawSquare(int x, int y){
+    BSP_LCD_FillRect(x*231/MAX_X+1, y*231/MAX_Y+1, 5, 5);
+}
+
+void drawTarget(int x, int y){
+    BSP_LCD_FillRect(x*231/MAX_X+1, y*231/MAX_Y+1, 5, 5);
+}
+
+void turnOffToneAndLed(void) {
+  led = 0;
+  speaker = 0;
+}
+
+void playToneAndLed(float frequency, float volume) {
+    led = 1.0;
+    speaker.period(1.0 / frequency);
+    speaker = volume;
+}
+
+void turnOnForTime(float time) {
+  playToneAndLed(400.0, 0.5);
+  alertTimeout.attach(&turnOffToneAndLed,time);
+}
+
+void initGame(){
+    direction = UP;
+    snakeLength = START_SNAKE_LENGTH;
+    score = 0;
+    mode = GAME;
+}
+
+void initMainMenuScreen(){
+    snakeLength = START_SNAKE_LENGTH;
+    score = 0;
+    
+    BSP_LCD_Clear(GAME_BG);
+    BSP_LCD_SetBackColor (GAME_BG);
+    BSP_LCD_SetTextColor(LCD_COLOR_GRAY);
+
+    BSP_LCD_SetTextColor (LCD_COLOR_YELLOW);
+    BSP_LCD_SetFont(&Font20);
+    BSP_LCD_DisplayStringAt(0, 40, (uint8_t*)"SNAKE GAME", CENTER_MODE);
+    BSP_LCD_SetFont(&Font16);
+    BSP_LCD_DisplayStringAt(0, 80, (uint8_t*)"Start game", CENTER_MODE);
+    BSP_LCD_DisplayStringAt(0, 100, (uint8_t*)"Press any key", CENTER_MODE);
+
+    BSP_LCD_SetTextColor(LCD_COLOR_GRAY);
+    BSP_LCD_FillRect (130, 155, 5, 5);
+    
+    BSP_LCD_SetTextColor(LCD_COLOR_GRAY);
+    BSP_LCD_FillRect (112, 155, 5, 5);
+    BSP_LCD_SetTextColor(LCD_COLOR_YELLOW);
+    BSP_LCD_FillRect (100, 155, 5, 5);
+    BSP_LCD_FillRect (106, 155, 5, 5);
+    BSP_LCD_FillRect (100, 162, 5, 5);
+    BSP_LCD_FillRect (100, 169, 5, 5);
+    BSP_LCD_FillRect (100, 176, 5, 5);
+    BSP_LCD_FillRect (94, 176, 5, 5);
+    BSP_LCD_FillRect (88, 176, 5, 5);
+    BSP_LCD_FillRect (82, 176, 5, 5);
+    BSP_LCD_FillRect (76, 176, 5, 5);
+    BSP_LCD_FillRect (70, 176, 5, 5);
+    BSP_LCD_FillRect (64, 176, 5, 5);
+    BSP_LCD_FillRect (58, 176, 5, 5);
+    BSP_LCD_FillRect (52, 176, 5, 5);
+    BSP_LCD_FillRect (52, 183, 5, 5);
+    BSP_LCD_FillRect (52, 190, 5, 5);
+}
+
+void initGameScreen(){
+    BSP_LCD_Clear(GAME_BG);
+    BSP_LCD_SetBackColor(GAME_BG);
+    BSP_LCD_SetTextColor(LCD_COLOR_GRAY);
+    BSP_LCD_SetFont(&Font8);
+    
+    BSP_LCD_SetTextColor(LCD_COLOR_YELLOW);
+
+    for(int i = 0; i < snakeLength - 1; i++)
+        drawSquare(X[i], Y[i]);
+    
+    char buffer[64];
+    sprintf(buffer, "Score: %d", score);
+    BSP_LCD_DisplayStringAt(10, 10, (uint8_t*)buffer, LEFT_MODE);
+    
+    BSP_LCD_SetTextColor(LCD_COLOR_GRAY);
+    drawSquare(X[snakeLength - 1], Y[snakeLength - 1]);
+
+    drawTarget(targetX, targetY);
+}
+
+
+void initEndGameScreen(){
+    BSP_LCD_Clear(GAME_BG);
+    BSP_LCD_SetBackColor (GAME_BG);
+    BSP_LCD_SetTextColor(LCD_COLOR_GRAY);
+    
+    BSP_LCD_SetFont(&Font24);
+    BSP_LCD_SetTextColor(LCD_COLOR_RED);
+    BSP_LCD_DisplayStringAt(0, 20, (uint8_t*)"GAME OVER", CENTER_MODE);
+    
+    BSP_LCD_SetFont(&Font16);
+    BSP_LCD_SetTextColor(LCD_COLOR_YELLOW);
+    char buffer[64];
+    sprintf(buffer, "Score: %d", score);
+    BSP_LCD_DisplayStringAt(0, 80, (uint8_t*)buffer, CENTER_MODE);
+
+    BSP_LCD_SetFont(&Font16);
+    BSP_LCD_SetTextColor(LCD_COLOR_YELLOW);
+    BSP_LCD_DisplayStringAt(120, 215, (uint8_t*)"Play again",LEFT_MODE);
+    BSP_LCD_DisplayStringAt(8, 215, (uint8_t*)"Home", LEFT_MODE);
+}
+
+void initScreen(){
+    switch (mode) {
+        case MAIN_MENU:
+            initMainMenuScreen();
+            break;
+        case GAME:
+            initGameScreen();
+            break;
+        case END_GAME:
+            initEndGameScreen();
+            break;
+    }
+}
+
+void initTarget(){
+    bool isSet = true;
+    do{
+        isSet = true;
+        srand (time(NULL));
+        targetX = (rand() % (MAX_X - 2)) + 1;
+        targetY = (rand() % (MAX_Y - 2)) + 1;
+        
+        for(int i = 0; i < snakeLength; i++)
+            if(X[i] == targetX && Y[i] == targetY)
+                isSet = false;
+    }while(!isSet);
+}
+
+void initPause(){
+    BSP_LCD_SetTextColor (LCD_COLOR_YELLOW);
+    BSP_LCD_SetFont(&Font16);
+    BSP_LCD_DisplayStringAt(0, 100, (uint8_t*)"Game paused", CENTER_MODE);
+}
+
+void gameTick(){
+    if(!toggglePause){
+        if(mode != GAME) return;
+
+        int headX = X[snakeLength - 1];
+        int headY = Y[snakeLength - 1];
+        
+        switch(direction){
+            case UP:
+                Y[snakeLength - 1] = Y[snakeLength - 1] - 1;
+                if(Y[snakeLength - 1] == 0)
+                    Y[snakeLength - 1] = MAX_Y - 1;
+                break;
+            case DOWN:
+                Y[snakeLength - 1] = (Y[snakeLength - 1] + 1) % MAX_Y;
+                if(Y[snakeLength - 1] == 0) Y[snakeLength - 1] = 1;
+                break;
+            case LEFT:
+                X[snakeLength - 1] = X[snakeLength - 1] - 1;
+                if(X[snakeLength - 1] == 0)
+                    X[snakeLength - 1] = MAX_X - 1;
+                break;
+            case RIGHT:
+                X[snakeLength - 1] = (X[snakeLength - 1] + 1) % MAX_X;
+                if(X[snakeLength - 1] == 0) X[snakeLength - 1] = 1;
+                break;
+        }
+
+        if(X[snakeLength - 1] == targetX && Y[snakeLength - 1] == targetY){
+            turnOnForTime(0.5);
+            score++;
+            snakeLength++;
+            X[snakeLength - 1] = X[snakeLength - 2];
+            Y[snakeLength - 1] = Y[snakeLength - 2];
+            initTarget();
+        }else
+            for(int i = 0; i < snakeLength - 2; i++){
+                X[i] = X[i+1];
+                Y[i] = Y[i+1];
+            }
+        X[snakeLength - 2] = headX;
+        Y[snakeLength - 2] = headY;
+        
+        for(int i = 0; i < snakeLength; i++){
+            if(X[snakeLength - 1] == X[i] && Y[snakeLength - 1] == Y[i] && i != snakeLength - 1){
+                isEndGame = false;
+                mode = END_GAME;
+                break;
+            }
+        }
+    }
+    else{
+        if(mode != GAME) return;
+        initPause();
+    }
+}
+
+void controller(Dirrection newDirection){
+    switch (mode) {
+        case MAIN_MENU:
+            mode = GAME;
+            break;
+        case GAME:
+            if(abs(direction - newDirection) != 2)
+                direction = newDirection;
+            break;
+        case END_GAME:
+            if(newDirection == LEFT)
+                mode = MAIN_MENU;
+            else if(newDirection == RIGHT)
+                initGame();
+            break;
+    }
+}
+
+void clickLeft(){
+    controller(LEFT);
+}
+
+void clickUp(){
+    controller(UP);
+}
+
+void clickRight(){
+    controller(RIGHT);
+}
+
+void clickDown(){
+    controller(DOWN);
+}
+
+int main() {
+    BSP_LCD_Init();
+
+    bLeft.rise(&clickLeft);
+    bUp.rise(&clickUp);
+    bRight.rise(&clickRight);
+    bDown.rise(&clickDown);
+    gameTicker.attach(&gameTick, SCREEN_REFRESH_PERIOD);
+    mainTicker.attach(&initScreen, SCREEN_REFRESH_PERIOD);
+    
+    initTarget();
+}
+