![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Erts
Dependencies: BSP_DISCO_F413ZH
Diff: main.cpp
- 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(); +} +