
Snake game for IMP class.
Dependencies: mbed Terminal SerialTerminal TSI MMA8451Q
main.cpp@0:ca75772f63a0, 2019-12-13 (annotated)
- Committer:
- lpiwowar
- Date:
- Fri Dec 13 10:14:54 2019 +0000
- Revision:
- 0:ca75772f63a0
Initial commit;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
lpiwowar | 0:ca75772f63a0 | 1 | #include <stdlib.h> |
lpiwowar | 0:ca75772f63a0 | 2 | #include "mbed.h" |
lpiwowar | 0:ca75772f63a0 | 3 | #include "TSISensor.h" |
lpiwowar | 0:ca75772f63a0 | 4 | #include "SerialTerminal.h" |
lpiwowar | 0:ca75772f63a0 | 5 | #include "MMA8451Q.h" |
lpiwowar | 0:ca75772f63a0 | 6 | |
lpiwowar | 0:ca75772f63a0 | 7 | #define MMA8451_I2C_ADDRESS (0x1d<<1) |
lpiwowar | 0:ca75772f63a0 | 8 | |
lpiwowar | 0:ca75772f63a0 | 9 | PwmOut rled(LED_RED); |
lpiwowar | 0:ca75772f63a0 | 10 | PwmOut gled(LED_GREEN); |
lpiwowar | 0:ca75772f63a0 | 11 | Timeout timeout; |
lpiwowar | 0:ca75772f63a0 | 12 | |
lpiwowar | 0:ca75772f63a0 | 13 | PinName const SDA = PTE25; /** < I2C serial data */ |
lpiwowar | 0:ca75772f63a0 | 14 | PinName const SCL = PTE24; /** < I2C serial clock */ |
lpiwowar | 0:ca75772f63a0 | 15 | |
lpiwowar | 0:ca75772f63a0 | 16 | /** Accelerometer */ |
lpiwowar | 0:ca75772f63a0 | 17 | MMA8451Q acc(SDA, SCL, MMA8451_I2C_ADDRESS); |
lpiwowar | 0:ca75772f63a0 | 18 | |
lpiwowar | 0:ca75772f63a0 | 19 | //Baud rate values: 57600, 115200, 460800 |
lpiwowar | 0:ca75772f63a0 | 20 | /** Access terminal via USB */ |
lpiwowar | 0:ca75772f63a0 | 21 | SerialTerminal term(USBTX, USBRX, 460800); |
lpiwowar | 0:ca75772f63a0 | 22 | |
lpiwowar | 0:ca75772f63a0 | 23 | const int FIELD_WIDTH = 60; /** < Width of game field */ |
lpiwowar | 0:ca75772f63a0 | 24 | const int FIELD_HEIGHT = 20; /** < Height of game field */ |
lpiwowar | 0:ca75772f63a0 | 25 | const int INIT_SNAKE_X = 30; /** < Snake initial x coordinates */ |
lpiwowar | 0:ca75772f63a0 | 26 | const int INIT_SNAKE_Y = 10; /** < Snake initial y coordinates */ |
lpiwowar | 0:ca75772f63a0 | 27 | |
lpiwowar | 0:ca75772f63a0 | 28 | /** @brief Stores the game field. ('#' = Snake + walls) */ |
lpiwowar | 0:ca75772f63a0 | 29 | char field[FIELD_HEIGHT][FIELD_WIDTH] = {}; |
lpiwowar | 0:ca75772f63a0 | 30 | |
lpiwowar | 0:ca75772f63a0 | 31 | //////////////////////////////////////////////////////////////////////////////// |
lpiwowar | 0:ca75772f63a0 | 32 | /// SNAKE - start /// |
lpiwowar | 0:ca75772f63a0 | 33 | //////////////////////////////////////////////////////////////////////////////// |
lpiwowar | 0:ca75772f63a0 | 34 | |
lpiwowar | 0:ca75772f63a0 | 35 | /** Values for direction of snake */ |
lpiwowar | 0:ca75772f63a0 | 36 | enum snake_move {SNAKE_UP, SNAKE_DOWN, SNAKE_LEFT, SNAKE_RIGHT, SNAKE_NONE}; |
lpiwowar | 0:ca75772f63a0 | 37 | typedef enum snake_move snake_move_T; |
lpiwowar | 0:ca75772f63a0 | 38 | |
lpiwowar | 0:ca75772f63a0 | 39 | /** Stores facts about one cell of snake */ |
lpiwowar | 0:ca75772f63a0 | 40 | typedef struct snake_cell_struct snake_cell_T; |
lpiwowar | 0:ca75772f63a0 | 41 | struct snake_cell_struct { |
lpiwowar | 0:ca75772f63a0 | 42 | short x; /** < X coordinates within @var field */ |
lpiwowar | 0:ca75772f63a0 | 43 | short y; /** < Y coordinates within @var field */ |
lpiwowar | 0:ca75772f63a0 | 44 | bool head; /** < True if cell is head (first cell) */ |
lpiwowar | 0:ca75772f63a0 | 45 | snake_cell_T *next_cell; /** < Pointer to next cell of snake */ |
lpiwowar | 0:ca75772f63a0 | 46 | }; |
lpiwowar | 0:ca75772f63a0 | 47 | |
lpiwowar | 0:ca75772f63a0 | 48 | /** |
lpiwowar | 0:ca75772f63a0 | 49 | * @brif Creates first cell of snake and returns pointer to it. Atribute |
lpiwowar | 0:ca75772f63a0 | 50 | * head is set to true. |
lpiwowar | 0:ca75772f63a0 | 51 | * @param x X coordinates of location where the snake should be spawned. |
lpiwowar | 0:ca75772f63a0 | 52 | * @param y Y coordinates of location where the snake should be spawned. |
lpiwowar | 0:ca75772f63a0 | 53 | * @return pointer to the first cell of snake |
lpiwowar | 0:ca75772f63a0 | 54 | */ |
lpiwowar | 0:ca75772f63a0 | 55 | snake_cell_T *init_snake(int x, int y) { |
lpiwowar | 0:ca75772f63a0 | 56 | snake_cell_T *new_snake = (snake_cell_T *)malloc(sizeof(snake_cell_T)); |
lpiwowar | 0:ca75772f63a0 | 57 | if(new_snake == NULL) { |
lpiwowar | 0:ca75772f63a0 | 58 | term.printf("Error: malloc()\r\n"); |
lpiwowar | 0:ca75772f63a0 | 59 | exit(1); |
lpiwowar | 0:ca75772f63a0 | 60 | } |
lpiwowar | 0:ca75772f63a0 | 61 | |
lpiwowar | 0:ca75772f63a0 | 62 | new_snake->x = x; |
lpiwowar | 0:ca75772f63a0 | 63 | new_snake->y = y; |
lpiwowar | 0:ca75772f63a0 | 64 | new_snake->next_cell = NULL; |
lpiwowar | 0:ca75772f63a0 | 65 | new_snake->head = true; |
lpiwowar | 0:ca75772f63a0 | 66 | |
lpiwowar | 0:ca75772f63a0 | 67 | return new_snake; |
lpiwowar | 0:ca75772f63a0 | 68 | } |
lpiwowar | 0:ca75772f63a0 | 69 | |
lpiwowar | 0:ca75772f63a0 | 70 | /** |
lpiwowar | 0:ca75772f63a0 | 71 | * @brief Frees all memory allocated for Snake. |
lpiwowar | 0:ca75772f63a0 | 72 | * @param snake Pointer to first cell of Snake |
lpiwowar | 0:ca75772f63a0 | 73 | */ |
lpiwowar | 0:ca75772f63a0 | 74 | void destroy_snake(snake_cell_T *snake) { |
lpiwowar | 0:ca75772f63a0 | 75 | snake_cell_T *snake_cell_tmp = NULL; |
lpiwowar | 0:ca75772f63a0 | 76 | while(snake != NULL) { |
lpiwowar | 0:ca75772f63a0 | 77 | snake_cell_tmp = snake; |
lpiwowar | 0:ca75772f63a0 | 78 | snake = snake->next_cell; |
lpiwowar | 0:ca75772f63a0 | 79 | free(snake_cell_tmp); |
lpiwowar | 0:ca75772f63a0 | 80 | } |
lpiwowar | 0:ca75772f63a0 | 81 | } |
lpiwowar | 0:ca75772f63a0 | 82 | |
lpiwowar | 0:ca75772f63a0 | 83 | /** |
lpiwowar | 0:ca75772f63a0 | 84 | * @brief Appends cell to the end of Snake. |
lpiwowar | 0:ca75772f63a0 | 85 | * @param snake Snake which should contain the new cell. |
lpiwowar | 0:ca75772f63a0 | 86 | * @param snake_cell Cell which should be appended to the Snake. |
lpiwowar | 0:ca75772f63a0 | 87 | */ |
lpiwowar | 0:ca75772f63a0 | 88 | void append_cell_to_snake(snake_cell_T *snake, snake_cell_T *snake_cell) { |
lpiwowar | 0:ca75772f63a0 | 89 | |
lpiwowar | 0:ca75772f63a0 | 90 | while(snake != NULL) { |
lpiwowar | 0:ca75772f63a0 | 91 | if(snake->next_cell == NULL) { |
lpiwowar | 0:ca75772f63a0 | 92 | snake->next_cell = snake_cell; |
lpiwowar | 0:ca75772f63a0 | 93 | break; |
lpiwowar | 0:ca75772f63a0 | 94 | } |
lpiwowar | 0:ca75772f63a0 | 95 | snake = snake->next_cell; |
lpiwowar | 0:ca75772f63a0 | 96 | } |
lpiwowar | 0:ca75772f63a0 | 97 | |
lpiwowar | 0:ca75772f63a0 | 98 | } |
lpiwowar | 0:ca75772f63a0 | 99 | |
lpiwowar | 0:ca75772f63a0 | 100 | const int WALL = -1; /** < Return value if Snake hit the wall */ |
lpiwowar | 0:ca75772f63a0 | 101 | const int FOOD_FOUND = 1; /** < Return value if Snake ate the food */ |
lpiwowar | 0:ca75772f63a0 | 102 | /** |
lpiwowar | 0:ca75772f63a0 | 103 | * @brief Updates the position of Snake. If the position where the snake |
lpiwowar | 0:ca75772f63a0 | 104 | * wants to move contains food ('*') it returns @var FOOD_FOUND and |
lpiwowar | 0:ca75772f63a0 | 105 | * creates new snake cell and appends it to the snake. If the position |
lpiwowar | 0:ca75772f63a0 | 106 | * where the snake wants to move contains wall ('#') it returns |
lpiwowar | 0:ca75772f63a0 | 107 | * WALL. Also updates coordinates coordinates of snake based on |
lpiwowar | 0:ca75772f63a0 | 108 | * direction in which the snake is moving. |
lpiwowar | 0:ca75772f63a0 | 109 | * @param snake Snake whose coordinates should be updated. |
lpiwowar | 0:ca75772f63a0 | 110 | * @param move_direction In which direction is the snake moving. |
lpiwowar | 0:ca75772f63a0 | 111 | * @return 0 if success. WALL if snake hit the wall. FOOD_FOUND if snake ate |
lpiwowar | 0:ca75772f63a0 | 112 | * the food. |
lpiwowar | 0:ca75772f63a0 | 113 | */ |
lpiwowar | 0:ca75772f63a0 | 114 | int update_snake_pos(snake_cell_T *snake, snake_move_T move_direction) { |
lpiwowar | 0:ca75772f63a0 | 115 | |
lpiwowar | 0:ca75772f63a0 | 116 | bool food_found = false; |
lpiwowar | 0:ca75772f63a0 | 117 | |
lpiwowar | 0:ca75772f63a0 | 118 | switch(move_direction) { |
lpiwowar | 0:ca75772f63a0 | 119 | case SNAKE_UP: if(field[snake->y-1][snake->x] == '#') |
lpiwowar | 0:ca75772f63a0 | 120 | return WALL; |
lpiwowar | 0:ca75772f63a0 | 121 | else if(field[snake->y-1][snake->x] == '*') |
lpiwowar | 0:ca75772f63a0 | 122 | food_found = true; |
lpiwowar | 0:ca75772f63a0 | 123 | break; |
lpiwowar | 0:ca75772f63a0 | 124 | |
lpiwowar | 0:ca75772f63a0 | 125 | case SNAKE_DOWN: if(field[snake->y+1][snake->x] == '#') |
lpiwowar | 0:ca75772f63a0 | 126 | return WALL; |
lpiwowar | 0:ca75772f63a0 | 127 | else if(field[snake->y+1][snake->x] == '*') |
lpiwowar | 0:ca75772f63a0 | 128 | food_found = true; |
lpiwowar | 0:ca75772f63a0 | 129 | break; |
lpiwowar | 0:ca75772f63a0 | 130 | |
lpiwowar | 0:ca75772f63a0 | 131 | case SNAKE_RIGHT: if(field[snake->y][snake->x+1] == '#') |
lpiwowar | 0:ca75772f63a0 | 132 | return WALL; |
lpiwowar | 0:ca75772f63a0 | 133 | else if(field[snake->y][snake->x+1] == '*') |
lpiwowar | 0:ca75772f63a0 | 134 | food_found = true; |
lpiwowar | 0:ca75772f63a0 | 135 | break; |
lpiwowar | 0:ca75772f63a0 | 136 | |
lpiwowar | 0:ca75772f63a0 | 137 | case SNAKE_LEFT: if(field[snake->y][snake->x-1] == '#') |
lpiwowar | 0:ca75772f63a0 | 138 | return WALL; |
lpiwowar | 0:ca75772f63a0 | 139 | else if(field[snake->y][snake->x-1] == '*') |
lpiwowar | 0:ca75772f63a0 | 140 | food_found = true; |
lpiwowar | 0:ca75772f63a0 | 141 | break; |
lpiwowar | 0:ca75772f63a0 | 142 | } |
lpiwowar | 0:ca75772f63a0 | 143 | |
lpiwowar | 0:ca75772f63a0 | 144 | snake_cell_T *new_cell = NULL; |
lpiwowar | 0:ca75772f63a0 | 145 | snake_cell_T *save_snake = snake; |
lpiwowar | 0:ca75772f63a0 | 146 | int prev_x = 0; |
lpiwowar | 0:ca75772f63a0 | 147 | int prev_y = 0; |
lpiwowar | 0:ca75772f63a0 | 148 | int tmp = 0; |
lpiwowar | 0:ca75772f63a0 | 149 | |
lpiwowar | 0:ca75772f63a0 | 150 | while(snake != NULL) { |
lpiwowar | 0:ca75772f63a0 | 151 | |
lpiwowar | 0:ca75772f63a0 | 152 | if(food_found && snake->next_cell == NULL) { |
lpiwowar | 0:ca75772f63a0 | 153 | new_cell = init_snake(snake->x, snake->y); |
lpiwowar | 0:ca75772f63a0 | 154 | new_cell->head = false; |
lpiwowar | 0:ca75772f63a0 | 155 | } |
lpiwowar | 0:ca75772f63a0 | 156 | |
lpiwowar | 0:ca75772f63a0 | 157 | if(snake->head) { |
lpiwowar | 0:ca75772f63a0 | 158 | switch(move_direction) { |
lpiwowar | 0:ca75772f63a0 | 159 | case SNAKE_UP: |
lpiwowar | 0:ca75772f63a0 | 160 | prev_x = snake->x; prev_y = snake->y; |
lpiwowar | 0:ca75772f63a0 | 161 | field[snake->y][snake->x] = ' '; |
lpiwowar | 0:ca75772f63a0 | 162 | snake->y -= 1; |
lpiwowar | 0:ca75772f63a0 | 163 | field[snake->y][snake->x] = '#'; |
lpiwowar | 0:ca75772f63a0 | 164 | break; |
lpiwowar | 0:ca75772f63a0 | 165 | case SNAKE_DOWN: |
lpiwowar | 0:ca75772f63a0 | 166 | prev_x = snake->x; prev_y = snake->y; |
lpiwowar | 0:ca75772f63a0 | 167 | field[snake->y][snake->x] = ' '; |
lpiwowar | 0:ca75772f63a0 | 168 | snake->y += 1; |
lpiwowar | 0:ca75772f63a0 | 169 | field[snake->y][snake->x] = '#'; |
lpiwowar | 0:ca75772f63a0 | 170 | break; |
lpiwowar | 0:ca75772f63a0 | 171 | case SNAKE_RIGHT: |
lpiwowar | 0:ca75772f63a0 | 172 | prev_x = snake->x; prev_y = snake->y; |
lpiwowar | 0:ca75772f63a0 | 173 | field[snake->y][snake->x] = ' '; |
lpiwowar | 0:ca75772f63a0 | 174 | snake->x += 1; |
lpiwowar | 0:ca75772f63a0 | 175 | field[snake->y][snake->x] = '#'; |
lpiwowar | 0:ca75772f63a0 | 176 | break; |
lpiwowar | 0:ca75772f63a0 | 177 | case SNAKE_LEFT: |
lpiwowar | 0:ca75772f63a0 | 178 | prev_x = snake->x; prev_y = snake->y; |
lpiwowar | 0:ca75772f63a0 | 179 | field[snake->y][snake->x] = ' '; |
lpiwowar | 0:ca75772f63a0 | 180 | snake->x -= 1; |
lpiwowar | 0:ca75772f63a0 | 181 | field[snake->y][snake->x] = '#'; |
lpiwowar | 0:ca75772f63a0 | 182 | break; |
lpiwowar | 0:ca75772f63a0 | 183 | } |
lpiwowar | 0:ca75772f63a0 | 184 | } else { |
lpiwowar | 0:ca75772f63a0 | 185 | field[snake->y][snake->x] = ' '; |
lpiwowar | 0:ca75772f63a0 | 186 | field[prev_y][prev_x] = '#'; |
lpiwowar | 0:ca75772f63a0 | 187 | tmp = snake->x; snake->x = prev_x; prev_x = tmp; |
lpiwowar | 0:ca75772f63a0 | 188 | tmp = snake->y; snake->y = prev_y; prev_y = tmp; |
lpiwowar | 0:ca75772f63a0 | 189 | } |
lpiwowar | 0:ca75772f63a0 | 190 | |
lpiwowar | 0:ca75772f63a0 | 191 | snake = snake->next_cell; |
lpiwowar | 0:ca75772f63a0 | 192 | } |
lpiwowar | 0:ca75772f63a0 | 193 | |
lpiwowar | 0:ca75772f63a0 | 194 | if(food_found) { |
lpiwowar | 0:ca75772f63a0 | 195 | append_cell_to_snake(save_snake, new_cell); |
lpiwowar | 0:ca75772f63a0 | 196 | return FOOD_FOUND; |
lpiwowar | 0:ca75772f63a0 | 197 | } |
lpiwowar | 0:ca75772f63a0 | 198 | else { |
lpiwowar | 0:ca75772f63a0 | 199 | return 0; |
lpiwowar | 0:ca75772f63a0 | 200 | } |
lpiwowar | 0:ca75772f63a0 | 201 | } |
lpiwowar | 0:ca75772f63a0 | 202 | |
lpiwowar | 0:ca75772f63a0 | 203 | //////////////////////////////////////////////////////////////////////////////// |
lpiwowar | 0:ca75772f63a0 | 204 | /// SNAKE - end /// |
lpiwowar | 0:ca75772f63a0 | 205 | //////////////////////////////////////////////////////////////////////////////// |
lpiwowar | 0:ca75772f63a0 | 206 | |
lpiwowar | 0:ca75772f63a0 | 207 | //////////////////////////////////////////////////////////////////////////////// |
lpiwowar | 0:ca75772f63a0 | 208 | /// MENU - start /// |
lpiwowar | 0:ca75772f63a0 | 209 | //////////////////////////////////////////////////////////////////////////////// |
lpiwowar | 0:ca75772f63a0 | 210 | |
lpiwowar | 0:ca75772f63a0 | 211 | typedef enum {EASY, DIFFICULT, SUPER_DIFFICULT} difficulty_T; |
lpiwowar | 0:ca75772f63a0 | 212 | TSISensor tsi; |
lpiwowar | 0:ca75772f63a0 | 213 | |
lpiwowar | 0:ca75772f63a0 | 214 | void print_menu(difficulty_T difficulty, float time_left) { |
lpiwowar | 0:ca75772f63a0 | 215 | term.cls(); |
lpiwowar | 0:ca75772f63a0 | 216 | term.move_cursor_up(FIELD_HEIGHT + 3); |
lpiwowar | 0:ca75772f63a0 | 217 | |
lpiwowar | 0:ca75772f63a0 | 218 | for(int i = 0; i != FIELD_HEIGHT/3; i++) |
lpiwowar | 0:ca75772f63a0 | 219 | term.printf("\r\n"); |
lpiwowar | 0:ca75772f63a0 | 220 | |
lpiwowar | 0:ca75772f63a0 | 221 | for(int i = 0; i != (FIELD_WIDTH - strlen("Please select dificulty)"))/2; i++) |
lpiwowar | 0:ca75772f63a0 | 222 | term.printf(" "); |
lpiwowar | 0:ca75772f63a0 | 223 | |
lpiwowar | 0:ca75772f63a0 | 224 | term.printf("Please selectt dificulty (%1.1f)", time_left); |
lpiwowar | 0:ca75772f63a0 | 225 | term.printf("\r\n"); |
lpiwowar | 0:ca75772f63a0 | 226 | |
lpiwowar | 0:ca75772f63a0 | 227 | for(int i = 0; i != (FIELD_WIDTH - strlen("Please select dificulty)"))/2; i++) |
lpiwowar | 0:ca75772f63a0 | 228 | term.printf(" "); |
lpiwowar | 0:ca75772f63a0 | 229 | |
lpiwowar | 0:ca75772f63a0 | 230 | switch(difficulty) { |
lpiwowar | 0:ca75772f63a0 | 231 | case EASY: |
lpiwowar | 0:ca75772f63a0 | 232 | term.printf("[*]Eeasy [ ]Difficult [ ]Super Difficult\r\n"); |
lpiwowar | 0:ca75772f63a0 | 233 | break; |
lpiwowar | 0:ca75772f63a0 | 234 | case DIFFICULT: |
lpiwowar | 0:ca75772f63a0 | 235 | term.printf("[ ]Eeasy [*]Difficult [ ]Super Difficult\r\n"); |
lpiwowar | 0:ca75772f63a0 | 236 | break; |
lpiwowar | 0:ca75772f63a0 | 237 | case SUPER_DIFFICULT: |
lpiwowar | 0:ca75772f63a0 | 238 | term.printf("[ ]Eeasy [ ]Difficult [*]Super Difficult\r\n"); |
lpiwowar | 0:ca75772f63a0 | 239 | break; |
lpiwowar | 0:ca75772f63a0 | 240 | } |
lpiwowar | 0:ca75772f63a0 | 241 | } |
lpiwowar | 0:ca75772f63a0 | 242 | |
lpiwowar | 0:ca75772f63a0 | 243 | difficulty_T get_difficulty() { |
lpiwowar | 0:ca75772f63a0 | 244 | difficulty_T save_state = EASY; |
lpiwowar | 0:ca75772f63a0 | 245 | float total_time = 10.0; |
lpiwowar | 0:ca75772f63a0 | 246 | float elapsed_time = 0.0; |
lpiwowar | 0:ca75772f63a0 | 247 | while(1) { |
lpiwowar | 0:ca75772f63a0 | 248 | |
lpiwowar | 0:ca75772f63a0 | 249 | float percentage = tsi.readPercentage(); |
lpiwowar | 0:ca75772f63a0 | 250 | |
lpiwowar | 0:ca75772f63a0 | 251 | if(percentage <= 0.3 && percentage >= 0.05) { |
lpiwowar | 0:ca75772f63a0 | 252 | print_menu(EASY, total_time - elapsed_time); |
lpiwowar | 0:ca75772f63a0 | 253 | save_state = EASY; |
lpiwowar | 0:ca75772f63a0 | 254 | } else if(percentage > 0.3 && percentage <= 0.6) { |
lpiwowar | 0:ca75772f63a0 | 255 | print_menu(DIFFICULT, total_time - elapsed_time); |
lpiwowar | 0:ca75772f63a0 | 256 | save_state = DIFFICULT; |
lpiwowar | 0:ca75772f63a0 | 257 | } else if(percentage > 0.6) { |
lpiwowar | 0:ca75772f63a0 | 258 | print_menu(SUPER_DIFFICULT, total_time - elapsed_time); |
lpiwowar | 0:ca75772f63a0 | 259 | save_state = SUPER_DIFFICULT; |
lpiwowar | 0:ca75772f63a0 | 260 | } else { |
lpiwowar | 0:ca75772f63a0 | 261 | print_menu(save_state, total_time - elapsed_time); |
lpiwowar | 0:ca75772f63a0 | 262 | } |
lpiwowar | 0:ca75772f63a0 | 263 | |
lpiwowar | 0:ca75772f63a0 | 264 | wait(0.1); |
lpiwowar | 0:ca75772f63a0 | 265 | elapsed_time += 0.1; |
lpiwowar | 0:ca75772f63a0 | 266 | if(elapsed_time > 10.0) |
lpiwowar | 0:ca75772f63a0 | 267 | break; |
lpiwowar | 0:ca75772f63a0 | 268 | } |
lpiwowar | 0:ca75772f63a0 | 269 | |
lpiwowar | 0:ca75772f63a0 | 270 | return save_state; |
lpiwowar | 0:ca75772f63a0 | 271 | } |
lpiwowar | 0:ca75772f63a0 | 272 | |
lpiwowar | 0:ca75772f63a0 | 273 | //////////////////////////////////////////////////////////////////////////////// |
lpiwowar | 0:ca75772f63a0 | 274 | /// MENU - end /// |
lpiwowar | 0:ca75772f63a0 | 275 | //////////////////////////////////////////////////////////////////////////////// |
lpiwowar | 0:ca75772f63a0 | 276 | |
lpiwowar | 0:ca75772f63a0 | 277 | /** |
lpiwowar | 0:ca75772f63a0 | 278 | * @brief Initializes the game field with walls and snake. |
lpiwowar | 0:ca75772f63a0 | 279 | */ |
lpiwowar | 0:ca75772f63a0 | 280 | void init_field() { |
lpiwowar | 0:ca75772f63a0 | 281 | for(int i = 0; i < FIELD_WIDTH; i++) |
lpiwowar | 0:ca75772f63a0 | 282 | field[0][i] = '#'; |
lpiwowar | 0:ca75772f63a0 | 283 | |
lpiwowar | 0:ca75772f63a0 | 284 | for(int y = 1; y < FIELD_HEIGHT - 1; y++) { |
lpiwowar | 0:ca75772f63a0 | 285 | field[y][0] = '#'; |
lpiwowar | 0:ca75772f63a0 | 286 | field[y][FIELD_WIDTH - 1] = '#'; |
lpiwowar | 0:ca75772f63a0 | 287 | |
lpiwowar | 0:ca75772f63a0 | 288 | if(y == INIT_SNAKE_Y) |
lpiwowar | 0:ca75772f63a0 | 289 | field[INIT_SNAKE_Y][INIT_SNAKE_X] = '#'; |
lpiwowar | 0:ca75772f63a0 | 290 | |
lpiwowar | 0:ca75772f63a0 | 291 | for(int x = 1; x < FIELD_WIDTH - 1; x++) { |
lpiwowar | 0:ca75772f63a0 | 292 | field[y][x] = ' '; |
lpiwowar | 0:ca75772f63a0 | 293 | } |
lpiwowar | 0:ca75772f63a0 | 294 | } |
lpiwowar | 0:ca75772f63a0 | 295 | |
lpiwowar | 0:ca75772f63a0 | 296 | for(int i = 0; i < FIELD_WIDTH; i++) |
lpiwowar | 0:ca75772f63a0 | 297 | field[FIELD_HEIGHT - 1][i] = '#'; |
lpiwowar | 0:ca75772f63a0 | 298 | } |
lpiwowar | 0:ca75772f63a0 | 299 | |
lpiwowar | 0:ca75772f63a0 | 300 | /** |
lpiwowar | 0:ca75772f63a0 | 301 | * @brief Prints the game field. |
lpiwowar | 0:ca75772f63a0 | 302 | */ |
lpiwowar | 0:ca75772f63a0 | 303 | void print_field(SerialTerminal &term) { |
lpiwowar | 0:ca75772f63a0 | 304 | for(int y = 0; y < FIELD_HEIGHT; y++) { |
lpiwowar | 0:ca75772f63a0 | 305 | |
lpiwowar | 0:ca75772f63a0 | 306 | for(int x = 0; x < FIELD_WIDTH; x++) |
lpiwowar | 0:ca75772f63a0 | 307 | term.printf("%c", field[y][x]); |
lpiwowar | 0:ca75772f63a0 | 308 | |
lpiwowar | 0:ca75772f63a0 | 309 | term.printf("\r\n"); |
lpiwowar | 0:ca75772f63a0 | 310 | } |
lpiwowar | 0:ca75772f63a0 | 311 | } |
lpiwowar | 0:ca75772f63a0 | 312 | |
lpiwowar | 0:ca75772f63a0 | 313 | /** |
lpiwowar | 0:ca75772f63a0 | 314 | * @brief Clears the terminal. |
lpiwowar | 0:ca75772f63a0 | 315 | */ |
lpiwowar | 0:ca75772f63a0 | 316 | void clear_field(SerialTerminal &term) { |
lpiwowar | 0:ca75772f63a0 | 317 | term.cls(); |
lpiwowar | 0:ca75772f63a0 | 318 | term.move_cursor_up(FIELD_HEIGHT + 3); |
lpiwowar | 0:ca75772f63a0 | 319 | } |
lpiwowar | 0:ca75772f63a0 | 320 | |
lpiwowar | 0:ca75772f63a0 | 321 | /** |
lpiwowar | 0:ca75772f63a0 | 322 | * @brief Generates food and puts it to the game field. |
lpiwowar | 0:ca75772f63a0 | 323 | */ |
lpiwowar | 0:ca75772f63a0 | 324 | void generate_food() { |
lpiwowar | 0:ca75772f63a0 | 325 | bool not_found = true; |
lpiwowar | 0:ca75772f63a0 | 326 | |
lpiwowar | 0:ca75772f63a0 | 327 | while(not_found) { |
lpiwowar | 0:ca75772f63a0 | 328 | int food_x = (rand() % (FIELD_WIDTH - 6)) + 3; |
lpiwowar | 0:ca75772f63a0 | 329 | int food_y = (rand() % (FIELD_HEIGHT - 6)) + 3; |
lpiwowar | 0:ca75772f63a0 | 330 | |
lpiwowar | 0:ca75772f63a0 | 331 | if(field[food_y][food_x] == ' ') { |
lpiwowar | 0:ca75772f63a0 | 332 | field[food_y][food_x] = '*'; |
lpiwowar | 0:ca75772f63a0 | 333 | not_found = false; |
lpiwowar | 0:ca75772f63a0 | 334 | } |
lpiwowar | 0:ca75772f63a0 | 335 | } |
lpiwowar | 0:ca75772f63a0 | 336 | } |
lpiwowar | 0:ca75772f63a0 | 337 | |
lpiwowar | 0:ca75772f63a0 | 338 | /** |
lpiwowar | 0:ca75772f63a0 | 339 | * @brief Gets the direction of required direction of snake based on values |
lpiwowar | 0:ca75772f63a0 | 340 | * from accelerometer. |
lpiwowar | 0:ca75772f63a0 | 341 | */ |
lpiwowar | 0:ca75772f63a0 | 342 | snake_move_T get_direction(int score_counter) { |
lpiwowar | 0:ca75772f63a0 | 343 | float up_down = acc.getAccX(); /* - = UP, + = DOWN */ |
lpiwowar | 0:ca75772f63a0 | 344 | float left_right = acc.getAccY(); /* - = LEFT, + = RIGHT */ |
lpiwowar | 0:ca75772f63a0 | 345 | |
lpiwowar | 0:ca75772f63a0 | 346 | static snake_move_T remember_last_dir = SNAKE_NONE; |
lpiwowar | 0:ca75772f63a0 | 347 | |
lpiwowar | 0:ca75772f63a0 | 348 | if(abs(up_down) > abs(left_right)) { |
lpiwowar | 0:ca75772f63a0 | 349 | if(up_down <= -0.25) { |
lpiwowar | 0:ca75772f63a0 | 350 | if(score_counter != 0 && remember_last_dir == SNAKE_DOWN) |
lpiwowar | 0:ca75772f63a0 | 351 | return remember_last_dir; |
lpiwowar | 0:ca75772f63a0 | 352 | remember_last_dir = SNAKE_UP; |
lpiwowar | 0:ca75772f63a0 | 353 | return SNAKE_UP; |
lpiwowar | 0:ca75772f63a0 | 354 | } |
lpiwowar | 0:ca75772f63a0 | 355 | |
lpiwowar | 0:ca75772f63a0 | 356 | if(up_down >= 0.25) { |
lpiwowar | 0:ca75772f63a0 | 357 | if(score_counter != 0 && remember_last_dir == SNAKE_UP) |
lpiwowar | 0:ca75772f63a0 | 358 | return remember_last_dir; |
lpiwowar | 0:ca75772f63a0 | 359 | remember_last_dir = SNAKE_DOWN; |
lpiwowar | 0:ca75772f63a0 | 360 | return SNAKE_DOWN; |
lpiwowar | 0:ca75772f63a0 | 361 | } |
lpiwowar | 0:ca75772f63a0 | 362 | |
lpiwowar | 0:ca75772f63a0 | 363 | } else { |
lpiwowar | 0:ca75772f63a0 | 364 | if (left_right <= -0.25) { |
lpiwowar | 0:ca75772f63a0 | 365 | if(score_counter != 0 && remember_last_dir == SNAKE_RIGHT) |
lpiwowar | 0:ca75772f63a0 | 366 | return remember_last_dir; |
lpiwowar | 0:ca75772f63a0 | 367 | remember_last_dir = SNAKE_LEFT; |
lpiwowar | 0:ca75772f63a0 | 368 | return SNAKE_LEFT; |
lpiwowar | 0:ca75772f63a0 | 369 | } |
lpiwowar | 0:ca75772f63a0 | 370 | |
lpiwowar | 0:ca75772f63a0 | 371 | if (left_right >= 0.25) { |
lpiwowar | 0:ca75772f63a0 | 372 | if(score_counter != 0 && remember_last_dir == SNAKE_LEFT) |
lpiwowar | 0:ca75772f63a0 | 373 | return remember_last_dir; |
lpiwowar | 0:ca75772f63a0 | 374 | remember_last_dir = SNAKE_RIGHT; |
lpiwowar | 0:ca75772f63a0 | 375 | return SNAKE_RIGHT; |
lpiwowar | 0:ca75772f63a0 | 376 | } |
lpiwowar | 0:ca75772f63a0 | 377 | } |
lpiwowar | 0:ca75772f63a0 | 378 | |
lpiwowar | 0:ca75772f63a0 | 379 | if(remember_last_dir != SNAKE_NONE) |
lpiwowar | 0:ca75772f63a0 | 380 | return remember_last_dir; |
lpiwowar | 0:ca75772f63a0 | 381 | else |
lpiwowar | 0:ca75772f63a0 | 382 | return SNAKE_RIGHT; |
lpiwowar | 0:ca75772f63a0 | 383 | } |
lpiwowar | 0:ca75772f63a0 | 384 | |
lpiwowar | 0:ca75772f63a0 | 385 | /** |
lpiwowar | 0:ca75772f63a0 | 386 | * @brief The higher the score the shorter time this function waits. If the |
lpiwowar | 0:ca75772f63a0 | 387 | * snake is moving horizontally the function waits shorter period of |
lpiwowar | 0:ca75772f63a0 | 388 | * time to compensate that letter's height is bigger than width; |
lpiwowar | 0:ca75772f63a0 | 389 | */ |
lpiwowar | 0:ca75772f63a0 | 390 | void score_wait(int score_counter, |
lpiwowar | 0:ca75772f63a0 | 391 | snake_move_T snake_direction, |
lpiwowar | 0:ca75772f63a0 | 392 | difficulty_T difficulty) { |
lpiwowar | 0:ca75772f63a0 | 393 | |
lpiwowar | 0:ca75772f63a0 | 394 | float time = 1; |
lpiwowar | 0:ca75772f63a0 | 395 | |
lpiwowar | 0:ca75772f63a0 | 396 | if (difficulty == EASY) time = 1; |
lpiwowar | 0:ca75772f63a0 | 397 | else if (difficulty == DIFFICULT) time = 0.6; |
lpiwowar | 0:ca75772f63a0 | 398 | else if(difficulty == SUPER_DIFFICULT) time = 0.4; |
lpiwowar | 0:ca75772f63a0 | 399 | |
lpiwowar | 0:ca75772f63a0 | 400 | if (score_counter > 5) time = time / 3; |
lpiwowar | 0:ca75772f63a0 | 401 | else if (score_counter > 10) time = time / 5; |
lpiwowar | 0:ca75772f63a0 | 402 | else if (score_counter > 15) time = time / 6; |
lpiwowar | 0:ca75772f63a0 | 403 | |
lpiwowar | 0:ca75772f63a0 | 404 | if(snake_direction == SNAKE_RIGHT || snake_direction == SNAKE_LEFT) |
lpiwowar | 0:ca75772f63a0 | 405 | wait(time/2); |
lpiwowar | 0:ca75772f63a0 | 406 | else |
lpiwowar | 0:ca75772f63a0 | 407 | wait(time); |
lpiwowar | 0:ca75772f63a0 | 408 | |
lpiwowar | 0:ca75772f63a0 | 409 | } |
lpiwowar | 0:ca75772f63a0 | 410 | |
lpiwowar | 0:ca75772f63a0 | 411 | //void blick_red_diode() { |
lpiwowar | 0:ca75772f63a0 | 412 | //} |
lpiwowar | 0:ca75772f63a0 | 413 | |
lpiwowar | 0:ca75772f63a0 | 414 | /** |
lpiwowar | 0:ca75772f63a0 | 415 | * @brief Lights up diode with collor corresponding to actual speed of the |
lpiwowar | 0:ca75772f63a0 | 416 | * snake. (e.g.: snake moves slowly => green, snakes moves fast => red) |
lpiwowar | 0:ca75772f63a0 | 417 | */ |
lpiwowar | 0:ca75772f63a0 | 418 | void light_up_diode(int score_counter, difficulty_T difficulty) { |
lpiwowar | 0:ca75772f63a0 | 419 | static bool lock = false; |
lpiwowar | 0:ca75772f63a0 | 420 | if(lock) return; |
lpiwowar | 0:ca75772f63a0 | 421 | |
lpiwowar | 0:ca75772f63a0 | 422 | float new_red = 1.0 - (1.0/2.0 * (float)score_counter); |
lpiwowar | 0:ca75772f63a0 | 423 | float new_green = 0.0 + (1.0/2.0 * (float)score_counter); |
lpiwowar | 0:ca75772f63a0 | 424 | rled = new_red; |
lpiwowar | 0:ca75772f63a0 | 425 | gled = new_green; |
lpiwowar | 0:ca75772f63a0 | 426 | |
lpiwowar | 0:ca75772f63a0 | 427 | if(new_green >= 0.99) { |
lpiwowar | 0:ca75772f63a0 | 428 | lock = true; |
lpiwowar | 0:ca75772f63a0 | 429 | //timeout.attach(&blick_red_diode, 10000); |
lpiwowar | 0:ca75772f63a0 | 430 | } |
lpiwowar | 0:ca75772f63a0 | 431 | } |
lpiwowar | 0:ca75772f63a0 | 432 | |
lpiwowar | 0:ca75772f63a0 | 433 | int main(void) { |
lpiwowar | 0:ca75772f63a0 | 434 | rled = 1; gled = 1; |
lpiwowar | 0:ca75772f63a0 | 435 | |
lpiwowar | 0:ca75772f63a0 | 436 | term.hide_cursor(); |
lpiwowar | 0:ca75772f63a0 | 437 | init_field(); |
lpiwowar | 0:ca75772f63a0 | 438 | generate_food(); |
lpiwowar | 0:ca75772f63a0 | 439 | |
lpiwowar | 0:ca75772f63a0 | 440 | difficulty_T difficulty = get_difficulty(); |
lpiwowar | 0:ca75772f63a0 | 441 | snake_cell_T *snake = init_snake(INIT_SNAKE_X, INIT_SNAKE_Y); |
lpiwowar | 0:ca75772f63a0 | 442 | int ret_update_snake = update_snake_pos(snake, SNAKE_RIGHT); |
lpiwowar | 0:ca75772f63a0 | 443 | |
lpiwowar | 0:ca75772f63a0 | 444 | int score_counter = 0; |
lpiwowar | 0:ca75772f63a0 | 445 | while(42) { |
lpiwowar | 0:ca75772f63a0 | 446 | clear_field(term); |
lpiwowar | 0:ca75772f63a0 | 447 | |
lpiwowar | 0:ca75772f63a0 | 448 | snake_move_T snake_direction = get_direction(score_counter); |
lpiwowar | 0:ca75772f63a0 | 449 | ret_update_snake = update_snake_pos(snake, snake_direction); |
lpiwowar | 0:ca75772f63a0 | 450 | |
lpiwowar | 0:ca75772f63a0 | 451 | if(ret_update_snake == WALL) |
lpiwowar | 0:ca75772f63a0 | 452 | break; |
lpiwowar | 0:ca75772f63a0 | 453 | else if(ret_update_snake == FOOD_FOUND) { |
lpiwowar | 0:ca75772f63a0 | 454 | generate_food(); |
lpiwowar | 0:ca75772f63a0 | 455 | score_counter++; |
lpiwowar | 0:ca75772f63a0 | 456 | } |
lpiwowar | 0:ca75772f63a0 | 457 | |
lpiwowar | 0:ca75772f63a0 | 458 | |
lpiwowar | 0:ca75772f63a0 | 459 | term.printf("Score:%d\r\n", score_counter); |
lpiwowar | 0:ca75772f63a0 | 460 | print_field(term); |
lpiwowar | 0:ca75772f63a0 | 461 | |
lpiwowar | 0:ca75772f63a0 | 462 | score_wait(score_counter, snake_direction, difficulty); |
lpiwowar | 0:ca75772f63a0 | 463 | light_up_diode(score_counter, difficulty); |
lpiwowar | 0:ca75772f63a0 | 464 | } |
lpiwowar | 0:ca75772f63a0 | 465 | |
lpiwowar | 0:ca75772f63a0 | 466 | clear_field(term); |
lpiwowar | 0:ca75772f63a0 | 467 | destroy_snake(snake); |
lpiwowar | 0:ca75772f63a0 | 468 | term.printf("GAME OVER! (You score: %d)", score_counter); |
lpiwowar | 0:ca75772f63a0 | 469 | destroy_snake(snake); |
lpiwowar | 0:ca75772f63a0 | 470 | } |