Snake and Physics based jumping game with high scores and different difficulties.
Dependencies: N5110 SDFileSystem mbed
main.cpp@5:ae641b1d04fa, 2016-05-04 (annotated)
- Committer:
- el14jw
- Date:
- Wed May 04 15:01:20 2016 +0000
- Revision:
- 5:ae641b1d04fa
- Parent:
- 4:c2d920b17b14
Snake and Physics based jumping game
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
el14jw | 0:23a749719479 | 1 | /** |
el14jw | 0:23a749719479 | 2 | 2645 Project Games |
el14jw | 0:23a749719479 | 3 | @file main.cpp |
el14jw | 0:23a749719479 | 4 | |
el14jw | 0:23a749719479 | 5 | @brief Program Implementation |
el14jw | 5:ae641b1d04fa | 6 | @brief Revision 1.1 |
el14jw | 0:23a749719479 | 7 | @author Joel W. Webb |
el14jw | 0:23a749719479 | 8 | */ |
el14jw | 0:23a749719479 | 9 | |
el14jw | 0:23a749719479 | 10 | #include "main.h" |
el14jw | 0:23a749719479 | 11 | |
el14jw | 0:23a749719479 | 12 | |
el14jw | 0:23a749719479 | 13 | // Joystick Polling code taken from joystick example code |
el14jw | 0:23a749719479 | 14 | /// Enumerated type to store joystick direction |
el14jw | 0:23a749719479 | 15 | enum DirectionName { |
el14jw | 0:23a749719479 | 16 | UP, |
el14jw | 0:23a749719479 | 17 | DOWN, |
el14jw | 0:23a749719479 | 18 | LEFT, |
el14jw | 0:23a749719479 | 19 | RIGHT, |
el14jw | 0:23a749719479 | 20 | CENTRE, |
el14jw | 0:23a749719479 | 21 | UNKNOWN |
el14jw | 0:23a749719479 | 22 | }; |
el14jw | 0:23a749719479 | 23 | |
el14jw | 0:23a749719479 | 24 | /// Struct for storing data about default Joystick position and Current position |
el14jw | 0:23a749719479 | 25 | struct JoyStick { |
el14jw | 0:23a749719479 | 26 | float x; // current x value |
el14jw | 0:23a749719479 | 27 | float x0; // 'centred' x value |
el14jw | 0:23a749719479 | 28 | float y; // current y value |
el14jw | 0:23a749719479 | 29 | float y0; // 'centred' y value |
el14jw | 0:23a749719479 | 30 | DirectionName direction; // current direction |
el14jw | 0:23a749719479 | 31 | }; |
el14jw | 0:23a749719479 | 32 | typedef struct JoyStick Joystick; |
el14jw | 5:ae641b1d04fa | 33 | /// Global Joystick struct for storing data about default Joystick position and Current position |
el14jw | 0:23a749719479 | 34 | Joystick joystick; |
el14jw | 5:ae641b1d04fa | 35 | |
el14jw | 0:23a749719479 | 36 | /// Ticker interrput for polling the joystick |
el14jw | 0:23a749719479 | 37 | Ticker pollJoystick; |
el14jw | 4:c2d920b17b14 | 38 | /// Ticker for controlling refresh rate of games |
el14jw | 2:80a91a737e17 | 39 | Ticker gametick; |
el14jw | 5:ae641b1d04fa | 40 | /// Ticker for sctrolling the refresh rate of the display |
el14jw | 5:ae641b1d04fa | 41 | Ticker screentick; |
el14jw | 4:c2d920b17b14 | 42 | /// File pointer for accessing SD card locations |
el14jw | 5:ae641b1d04fa | 43 | FILE *fp = NULL; |
el14jw | 0:23a749719479 | 44 | |
el14jw | 0:23a749719479 | 45 | |
el14jw | 0:23a749719479 | 46 | int main() |
el14jw | 0:23a749719479 | 47 | { |
el14jw | 0:23a749719479 | 48 | initInputs(); |
el14jw | 0:23a749719479 | 49 | playSound(tune_intro); |
el14jw | 0:23a749719479 | 50 | |
el14jw | 4:c2d920b17b14 | 51 | int snakeDifficulty = 1; |
el14jw | 1:c4928de1f922 | 52 | int plinkDifficulty = 0; |
el14jw | 0:23a749719479 | 53 | while (true) { |
el14jw | 1:c4928de1f922 | 54 | |
el14jw | 0:23a749719479 | 55 | // Main menu screen |
el14jw | 1:c4928de1f922 | 56 | int select = menu(menuList,3); |
el14jw | 0:23a749719479 | 57 | |
el14jw | 0:23a749719479 | 58 | // Selected Snake |
el14jw | 0:23a749719479 | 59 | if (select == 0) { |
el14jw | 1:c4928de1f922 | 60 | // If select = 3 or -1 then user has chosen 'Back' button |
el14jw | 1:c4928de1f922 | 61 | while( !(select == 3 || select ==-1) ) { |
el14jw | 0:23a749719479 | 62 | |
el14jw | 0:23a749719479 | 63 | // Snake selection screen |
el14jw | 1:c4928de1f922 | 64 | select = menu(snakeList,5); |
el14jw | 1:c4928de1f922 | 65 | if (select == 0) { |
el14jw | 1:c4928de1f922 | 66 | // Play Snake game |
el14jw | 1:c4928de1f922 | 67 | snake(snakeDifficulty); |
el14jw | 1:c4928de1f922 | 68 | } |
el14jw | 0:23a749719479 | 69 | // Selected Difficulty |
el14jw | 1:c4928de1f922 | 70 | else if (select == 1) { |
el14jw | 0:23a749719479 | 71 | // Difficulty selection screen |
el14jw | 1:c4928de1f922 | 72 | int tempdiff = snakeDifficulty; |
el14jw | 1:c4928de1f922 | 73 | snakeDifficulty = menu(difficultyList,4); |
el14jw | 1:c4928de1f922 | 74 | if (snakeDifficulty == -1) { |
el14jw | 1:c4928de1f922 | 75 | snakeDifficulty = tempdiff; |
el14jw | 1:c4928de1f922 | 76 | } |
el14jw | 0:23a749719479 | 77 | } |
el14jw | 1:c4928de1f922 | 78 | // Highscore |
el14jw | 1:c4928de1f922 | 79 | else if (select == 2) { |
el14jw | 1:c4928de1f922 | 80 | fp = fopen("/sd/snakehighscore.txt", "r"); |
el14jw | 1:c4928de1f922 | 81 | wait(0.05); |
el14jw | 1:c4928de1f922 | 82 | int stored_top_score = -1; // -1 to demonstrate it has changed after reading |
el14jw | 1:c4928de1f922 | 83 | |
el14jw | 1:c4928de1f922 | 84 | lcd.clear(); |
el14jw | 1:c4928de1f922 | 85 | if (fp == NULL) { // if it can't open the file then print error message |
el14jw | 1:c4928de1f922 | 86 | lcd.printString("No Results",0,0); |
el14jw | 1:c4928de1f922 | 87 | wait(2.0); |
el14jw | 1:c4928de1f922 | 88 | } else { // opened file so can write |
el14jw | 5:ae641b1d04fa | 89 | while ( ! (g_buttonA_flag | g_buttonjoy_flag)) { |
el14jw | 1:c4928de1f922 | 90 | fscanf(fp,"%d",&stored_top_score); // ensure data type matches - note address operator (&) |
el14jw | 1:c4928de1f922 | 91 | fclose(fp); // ensure you close the file after reading |
el14jw | 1:c4928de1f922 | 92 | lcd.printString("Highscore:",10,0); |
el14jw | 1:c4928de1f922 | 93 | if (stored_top_score != -2) { |
el14jw | 1:c4928de1f922 | 94 | char buffer[14]; |
el14jw | 1:c4928de1f922 | 95 | sprintf(buffer,"%d",stored_top_score); |
el14jw | 1:c4928de1f922 | 96 | lcd.printString(buffer,0,1); |
el14jw | 1:c4928de1f922 | 97 | } else { |
el14jw | 1:c4928de1f922 | 98 | lcd.printString("No Saved Score",0,1); |
el14jw | 1:c4928de1f922 | 99 | } |
el14jw | 1:c4928de1f922 | 100 | lcd.printString(">> Back",0,2); |
el14jw | 1:c4928de1f922 | 101 | sleep(); |
el14jw | 1:c4928de1f922 | 102 | } |
el14jw | 1:c4928de1f922 | 103 | g_buttonjoy_flag = 0; |
el14jw | 1:c4928de1f922 | 104 | g_buttonA_flag = 0; |
el14jw | 1:c4928de1f922 | 105 | } |
el14jw | 1:c4928de1f922 | 106 | } |
el14jw | 1:c4928de1f922 | 107 | |
el14jw | 0:23a749719479 | 108 | } |
el14jw | 0:23a749719479 | 109 | } |
el14jw | 0:23a749719479 | 110 | |
el14jw | 1:c4928de1f922 | 111 | // Selected Plink |
el14jw | 0:23a749719479 | 112 | else if (select == 1) { |
el14jw | 5:ae641b1d04fa | 113 | |
el14jw | 1:c4928de1f922 | 114 | // If select = 3 or -1 then user has chosen 'Back' button |
el14jw | 1:c4928de1f922 | 115 | while( !(select == 3 || select ==-1) ) { |
el14jw | 0:23a749719479 | 116 | |
el14jw | 1:c4928de1f922 | 117 | select = menu(plinkList,5); |
el14jw | 1:c4928de1f922 | 118 | // Start Plink |
el14jw | 1:c4928de1f922 | 119 | if (select == 0) { |
el14jw | 0:23a749719479 | 120 | playSound(tune_intro); |
el14jw | 1:c4928de1f922 | 121 | plink(plinkDifficulty); |
el14jw | 1:c4928de1f922 | 122 | } |
el14jw | 1:c4928de1f922 | 123 | // Difficulty selection |
el14jw | 1:c4928de1f922 | 124 | else if (select == 1) { |
el14jw | 1:c4928de1f922 | 125 | int tempdiff = plinkDifficulty; |
el14jw | 1:c4928de1f922 | 126 | plinkDifficulty = menu(difficultyList,4); |
el14jw | 1:c4928de1f922 | 127 | if (plinkDifficulty == -1) { |
el14jw | 1:c4928de1f922 | 128 | plinkDifficulty = tempdiff; |
el14jw | 1:c4928de1f922 | 129 | } |
el14jw | 1:c4928de1f922 | 130 | } |
el14jw | 1:c4928de1f922 | 131 | // Highscore |
el14jw | 1:c4928de1f922 | 132 | else if (select == 2) { |
el14jw | 1:c4928de1f922 | 133 | fp = fopen("/sd/plinkhighscore.txt", "r"); |
el14jw | 1:c4928de1f922 | 134 | wait(0.05); |
el14jw | 1:c4928de1f922 | 135 | int stored_top_score = -2; // -2 to demonstrate it has changed after reading |
el14jw | 1:c4928de1f922 | 136 | |
el14jw | 1:c4928de1f922 | 137 | lcd.clear(); |
el14jw | 1:c4928de1f922 | 138 | if (fp == NULL) { // if it can't open the file then print error message |
el14jw | 1:c4928de1f922 | 139 | lcd.printString("No Results",0,0); |
el14jw | 1:c4928de1f922 | 140 | wait(2.0); |
el14jw | 1:c4928de1f922 | 141 | } else { // opened file so can read |
el14jw | 1:c4928de1f922 | 142 | while ( ! (g_buttonA_flag || g_buttonjoy_flag)) { |
el14jw | 1:c4928de1f922 | 143 | fscanf(fp,"%d",&stored_top_score); // ensure data type matches - note address operator (&) |
el14jw | 1:c4928de1f922 | 144 | fclose(fp); // ensure you close the file after reading |
el14jw | 1:c4928de1f922 | 145 | lcd.printString("Highscore",10,0); |
el14jw | 1:c4928de1f922 | 146 | if (stored_top_score !=-2) { |
el14jw | 1:c4928de1f922 | 147 | char buffer[14]; |
el14jw | 1:c4928de1f922 | 148 | sprintf(buffer,"%d",stored_top_score); |
el14jw | 1:c4928de1f922 | 149 | lcd.printString(buffer,0,1); |
el14jw | 1:c4928de1f922 | 150 | } else { |
el14jw | 1:c4928de1f922 | 151 | lcd.printString("No Saved Score",0,1); |
el14jw | 1:c4928de1f922 | 152 | } |
el14jw | 1:c4928de1f922 | 153 | lcd.printString(">> Back",0,2); |
el14jw | 1:c4928de1f922 | 154 | sleep(); |
el14jw | 1:c4928de1f922 | 155 | } |
el14jw | 1:c4928de1f922 | 156 | g_buttonjoy_flag = 0; |
el14jw | 1:c4928de1f922 | 157 | g_buttonA_flag = 0; |
el14jw | 1:c4928de1f922 | 158 | } |
el14jw | 0:23a749719479 | 159 | } |
el14jw | 0:23a749719479 | 160 | } |
el14jw | 0:23a749719479 | 161 | } |
el14jw | 0:23a749719479 | 162 | } |
el14jw | 0:23a749719479 | 163 | } |
el14jw | 0:23a749719479 | 164 | |
el14jw | 0:23a749719479 | 165 | |
el14jw | 1:c4928de1f922 | 166 | // SNAKE |
el14jw | 0:23a749719479 | 167 | |
el14jw | 0:23a749719479 | 168 | void snake(int difficulty) |
el14jw | 0:23a749719479 | 169 | { |
el14jw | 0:23a749719479 | 170 | // Play the snake intro tune |
el14jw | 0:23a749719479 | 171 | playSound(tune_snakeintro); |
el14jw | 0:23a749719479 | 172 | // Creates an array for storing the snake body x and y data. The snake can be up to 880 cells long |
el14jw | 0:23a749719479 | 173 | cell snake[880]; |
el14jw | 1:c4928de1f922 | 174 | // Clears data from previous games |
el14jw | 1:c4928de1f922 | 175 | for (int i=0; i<880; i++) { |
el14jw | 1:c4928de1f922 | 176 | snake[i].x = 0; |
el14jw | 1:c4928de1f922 | 177 | snake[i].y = 0; |
el14jw | 1:c4928de1f922 | 178 | } |
el14jw | 1:c4928de1f922 | 179 | |
el14jw | 0:23a749719479 | 180 | cell food; |
el14jw | 0:23a749719479 | 181 | // Starting length is 5 cells |
el14jw | 0:23a749719479 | 182 | int length = 5; |
el14jw | 0:23a749719479 | 183 | // Starting 5 cells are x = 20 and y = 11,12,13,14 and 15 |
el14jw | 0:23a749719479 | 184 | for (int i=0; i<length; i++) { |
el14jw | 0:23a749719479 | 185 | snake[i].x = 20; |
el14jw | 0:23a749719479 | 186 | snake[i].y = 11+i; |
el14jw | 0:23a749719479 | 187 | } |
el14jw | 0:23a749719479 | 188 | |
el14jw | 0:23a749719479 | 189 | // Creates timer based on how hard you set the difficulty (default Medium) |
el14jw | 0:23a749719479 | 190 | gametick.attach(&gametick_isr,(0.4-(difficulty*0.15))); |
el14jw | 0:23a749719479 | 191 | // Initialise the snake_direction parameter as UP |
el14jw | 0:23a749719479 | 192 | DirectionName snake_direction = UP; |
el14jw | 0:23a749719479 | 193 | // Set the game over condition before while loop |
el14jw | 0:23a749719479 | 194 | int gameOver = 0; |
el14jw | 0:23a749719479 | 195 | |
el14jw | 1:c4928de1f922 | 196 | // Create the random food location flag (0 if food needs to be randomised and 1 if food still exists) |
el14jw | 0:23a749719479 | 197 | int rand_food = 0; |
el14jw | 0:23a749719479 | 198 | |
el14jw | 0:23a749719479 | 199 | while(!gameOver) { |
el14jw | 0:23a749719479 | 200 | // When the game ticker updates |
el14jw | 0:23a749719479 | 201 | if (g_gametick_flag) { |
el14jw | 0:23a749719479 | 202 | // Reset the ticker flag |
el14jw | 0:23a749719479 | 203 | g_gametick_flag = 0; |
el14jw | 1:c4928de1f922 | 204 | |
el14jw | 0:23a749719479 | 205 | // If the current snake_direction is the opposite of the joystick direction or the joystick direction is centerd or unknown then keep current direction |
el14jw | 0:23a749719479 | 206 | if ( !( (snake_direction == UP && joystick.direction == DOWN) || |
el14jw | 0:23a749719479 | 207 | (snake_direction == DOWN && joystick.direction == UP) || |
el14jw | 0:23a749719479 | 208 | (snake_direction == LEFT && joystick.direction == RIGHT) || |
el14jw | 0:23a749719479 | 209 | (snake_direction == RIGHT && joystick.direction == LEFT) || |
el14jw | 0:23a749719479 | 210 | (joystick.direction == CENTRE || joystick.direction == UNKNOWN) )) { |
el14jw | 0:23a749719479 | 211 | snake_direction = joystick.direction; |
el14jw | 0:23a749719479 | 212 | } |
el14jw | 0:23a749719479 | 213 | // Iterate through array and move each cell backwards as far as the length of the snake |
el14jw | 0:23a749719479 | 214 | for (int i=(length-1); i>0; i--) { |
el14jw | 0:23a749719479 | 215 | snake[i] = snake[i-1]; |
el14jw | 0:23a749719479 | 216 | } |
el14jw | 0:23a749719479 | 217 | // Then change the x or y coordinate of the first cell of the snake depending on which direction it is moving in |
el14jw | 0:23a749719479 | 218 | switch(snake_direction) { |
el14jw | 0:23a749719479 | 219 | case UP: |
el14jw | 0:23a749719479 | 220 | snake[0].y = snake[0].y - 1; |
el14jw | 0:23a749719479 | 221 | break; |
el14jw | 0:23a749719479 | 222 | case DOWN: |
el14jw | 0:23a749719479 | 223 | snake[0].y = snake[0].y + 1; |
el14jw | 0:23a749719479 | 224 | break; |
el14jw | 0:23a749719479 | 225 | case LEFT: |
el14jw | 0:23a749719479 | 226 | snake[0].x = snake[0].x - 1; |
el14jw | 0:23a749719479 | 227 | break; |
el14jw | 0:23a749719479 | 228 | case RIGHT: |
el14jw | 0:23a749719479 | 229 | snake[0].x = snake[0].x + 1; |
el14jw | 0:23a749719479 | 230 | break; |
el14jw | 0:23a749719479 | 231 | default: |
el14jw | 0:23a749719479 | 232 | error(); |
el14jw | 0:23a749719479 | 233 | } |
el14jw | 0:23a749719479 | 234 | |
el14jw | 0:23a749719479 | 235 | // If snake hits wall then game over |
el14jw | 0:23a749719479 | 236 | if ( (snake[0].x == 41) || (snake[0].x == 0) || (snake[0].y == 23) || (snake[0].y == 0 ) ) { |
el14jw | 0:23a749719479 | 237 | gameOver = 1; |
el14jw | 0:23a749719479 | 238 | } |
el14jw | 0:23a749719479 | 239 | // If snake hits self then game over |
el14jw | 0:23a749719479 | 240 | for (int i=1; i<length; i++) { |
el14jw | 0:23a749719479 | 241 | if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) { |
el14jw | 0:23a749719479 | 242 | gameOver = 1; |
el14jw | 0:23a749719479 | 243 | } |
el14jw | 0:23a749719479 | 244 | } |
el14jw | 1:c4928de1f922 | 245 | |
el14jw | 0:23a749719479 | 246 | // If the snake head is at the same value of x and y as the food then play tune and increase length by 2 |
el14jw | 0:23a749719479 | 247 | if (food.x == snake[0].x && food.y == snake[0].y) { |
el14jw | 0:23a749719479 | 248 | playSound(tune_snakeEat); |
el14jw | 0:23a749719479 | 249 | length += 2; |
el14jw | 0:23a749719479 | 250 | // Also set new random food to be generated |
el14jw | 0:23a749719479 | 251 | rand_food = 0; |
el14jw | 0:23a749719479 | 252 | } |
el14jw | 1:c4928de1f922 | 253 | |
el14jw | 0:23a749719479 | 254 | // Create a random location for the food that is not the same as a snake location |
el14jw | 0:23a749719479 | 255 | while(rand_food == 0) { |
el14jw | 0:23a749719479 | 256 | rand_food = 1; |
el14jw | 0:23a749719479 | 257 | food.x = rand(); |
el14jw | 0:23a749719479 | 258 | food.x = food.x %40 +1; |
el14jw | 0:23a749719479 | 259 | food.y = rand(); |
el14jw | 0:23a749719479 | 260 | food.y = food.y %22 +1; |
el14jw | 0:23a749719479 | 261 | for (int i=0; i<length; i++) { |
el14jw | 0:23a749719479 | 262 | if(food.x == snake[i].x && food.y == snake[i].y) { |
el14jw | 0:23a749719479 | 263 | rand_food = 0; |
el14jw | 0:23a749719479 | 264 | } |
el14jw | 0:23a749719479 | 265 | } |
el14jw | 0:23a749719479 | 266 | } |
el14jw | 1:c4928de1f922 | 267 | |
el14jw | 1:c4928de1f922 | 268 | // Drawing Display |
el14jw | 1:c4928de1f922 | 269 | lcd.clear(); |
el14jw | 1:c4928de1f922 | 270 | // Draws Boundary 2 thick |
el14jw | 1:c4928de1f922 | 271 | lcd.drawRect(0,0,83,47,0); |
el14jw | 1:c4928de1f922 | 272 | lcd.drawRect(1,1,81,45,0); |
el14jw | 1:c4928de1f922 | 273 | // Draws snake |
el14jw | 1:c4928de1f922 | 274 | for (int i=0; i<length; i++) { |
el14jw | 1:c4928de1f922 | 275 | lcd.drawRect(snake[i].x*2,snake[i].y*2,1,1,1); |
el14jw | 1:c4928de1f922 | 276 | } |
el14jw | 1:c4928de1f922 | 277 | // Draws food |
el14jw | 1:c4928de1f922 | 278 | lcd.drawRect(food.x*2,food.y*2,1,1,1); |
el14jw | 0:23a749719479 | 279 | lcd.refresh(); |
el14jw | 1:c4928de1f922 | 280 | |
el14jw | 0:23a749719479 | 281 | } |
el14jw | 0:23a749719479 | 282 | sleep(); |
el14jw | 0:23a749719479 | 283 | } |
el14jw | 1:c4928de1f922 | 284 | // End game ticker |
el14jw | 1:c4928de1f922 | 285 | gametick.detach(); |
el14jw | 1:c4928de1f922 | 286 | int score = length -5; // length -5 because starting length is 5 and a score without collecting anything should be 0 |
el14jw | 1:c4928de1f922 | 287 | lcd.clear(); |
el14jw | 2:80a91a737e17 | 288 | |
el14jw | 1:c4928de1f922 | 289 | // Read previous highscore if one exists |
el14jw | 1:c4928de1f922 | 290 | fp = fopen("/sd/snakehighscore.txt", "r"); |
el14jw | 1:c4928de1f922 | 291 | int current_high_score = -1; // -1 to demonstrate it has changed after reading |
el14jw | 1:c4928de1f922 | 292 | |
el14jw | 1:c4928de1f922 | 293 | if (fp == NULL) { // if it can't open the file then print error message |
el14jw | 1:c4928de1f922 | 294 | lcd.printString("Failed Read",0,5); |
el14jw | 1:c4928de1f922 | 295 | } else { // opened file so can write |
el14jw | 1:c4928de1f922 | 296 | fscanf(fp,"%d",¤t_high_score); // ensure data type matches - note address operator (&) |
el14jw | 1:c4928de1f922 | 297 | fclose(fp); // ensure you close the file after reading |
el14jw | 1:c4928de1f922 | 298 | } |
el14jw | 1:c4928de1f922 | 299 | |
el14jw | 1:c4928de1f922 | 300 | // Writing score to sd card if new high score |
el14jw | 1:c4928de1f922 | 301 | if (current_high_score < score && current_high_score != -1) { |
el14jw | 1:c4928de1f922 | 302 | fp = fopen("/sd/snakehighscore.txt", "w"); |
el14jw | 1:c4928de1f922 | 303 | if (fp == NULL) { // if it can't open the file then print error message |
el14jw | 1:c4928de1f922 | 304 | lcd.printString("No SD Card",0,5); |
el14jw | 1:c4928de1f922 | 305 | } else { // opened file so can write |
el14jw | 1:c4928de1f922 | 306 | fprintf(fp,"%d",score); // ensure data type matches |
el14jw | 1:c4928de1f922 | 307 | fclose(fp); // ensure you close the file after writing |
el14jw | 1:c4928de1f922 | 308 | } |
el14jw | 1:c4928de1f922 | 309 | } |
el14jw | 1:c4928de1f922 | 310 | |
el14jw | 1:c4928de1f922 | 311 | // Appropriate strings printed to LCD |
el14jw | 1:c4928de1f922 | 312 | lcd.printString("Game Over",20,0); |
el14jw | 5:ae641b1d04fa | 313 | if (current_high_score == -2) { |
el14jw | 5:ae641b1d04fa | 314 | lcd.printString("New High Score:",0,1); |
el14jw | 5:ae641b1d04fa | 315 | } else if (current_high_score != -1 && current_high_score < score) { |
el14jw | 1:c4928de1f922 | 316 | lcd.printString("New High Score",0,1); |
el14jw | 1:c4928de1f922 | 317 | lcd.printString("Previously",0,3); |
el14jw | 5:ae641b1d04fa | 318 | } else if (current_high_score != -1 && current_high_score >= score) { |
el14jw | 1:c4928de1f922 | 319 | lcd.printString("Score",0,1); |
el14jw | 1:c4928de1f922 | 320 | lcd.printString("High Score",0,3); |
el14jw | 1:c4928de1f922 | 321 | } else { |
el14jw | 1:c4928de1f922 | 322 | lcd.printString("Score:",0,1); |
el14jw | 1:c4928de1f922 | 323 | lcd.printString("No Previous",0,3); |
el14jw | 1:c4928de1f922 | 324 | } |
el14jw | 1:c4928de1f922 | 325 | // Print score |
el14jw | 1:c4928de1f922 | 326 | char buffer[14]; |
el14jw | 1:c4928de1f922 | 327 | sprintf(buffer,"%d",score); |
el14jw | 1:c4928de1f922 | 328 | lcd.printString(buffer,20,2); |
el14jw | 1:c4928de1f922 | 329 | // Print previous high-score |
el14jw | 5:ae641b1d04fa | 330 | if (current_high_score != -1 && current_high_score != -2) { |
el14jw | 1:c4928de1f922 | 331 | char str[14]; |
el14jw | 1:c4928de1f922 | 332 | sprintf(str,"%d",current_high_score); |
el14jw | 1:c4928de1f922 | 333 | lcd.printString(str,20,4); |
el14jw | 1:c4928de1f922 | 334 | } |
el14jw | 1:c4928de1f922 | 335 | |
el14jw | 0:23a749719479 | 336 | playSound(tune_gameOver); |
el14jw | 0:23a749719479 | 337 | wait(3.0); |
el14jw | 0:23a749719479 | 338 | g_buttonA_flag = 0; |
el14jw | 1:c4928de1f922 | 339 | g_buttonB_flag = 0; |
el14jw | 0:23a749719479 | 340 | g_buttonjoy_flag = 0; |
el14jw | 0:23a749719479 | 341 | } |
el14jw | 1:c4928de1f922 | 342 | |
el14jw | 1:c4928de1f922 | 343 | |
el14jw | 1:c4928de1f922 | 344 | // PLINK |
el14jw | 1:c4928de1f922 | 345 | |
el14jw | 1:c4928de1f922 | 346 | void plink(int difficulty) |
el14jw | 0:23a749719479 | 347 | { |
el14jw | 1:c4928de1f922 | 348 | playSound(tune_plinkintro); |
el14jw | 1:c4928de1f922 | 349 | lcd.clear(); |
el14jw | 3:02d9072a2507 | 350 | // Instead of damaging the program flow with global variables I pass a struct full of variables from one plink function to another. |
el14jw | 1:c4928de1f922 | 351 | |
el14jw | 3:02d9072a2507 | 352 | plinkvar pvar; |
el14jw | 3:02d9072a2507 | 353 | pvar.difficulty = difficulty; |
el14jw | 2:80a91a737e17 | 354 | |
el14jw | 3:02d9072a2507 | 355 | // Initialise plink variables |
el14jw | 3:02d9072a2507 | 356 | pvar = initpvar(pvar); |
el14jw | 2:80a91a737e17 | 357 | // Game ticker |
el14jw | 1:c4928de1f922 | 358 | int refreshRate = 100; |
el14jw | 1:c4928de1f922 | 359 | float tickerDelay = 1.0/refreshRate; |
el14jw | 3:02d9072a2507 | 360 | pvar.tickerDelay = tickerDelay; |
el14jw | 1:c4928de1f922 | 361 | gametick.attach(&gametick_isr,tickerDelay); |
el14jw | 5:ae641b1d04fa | 362 | // Update screen 30 fps |
el14jw | 5:ae641b1d04fa | 363 | tickerDelay = 1.0/30.0; |
el14jw | 5:ae641b1d04fa | 364 | screentick.attach(&screentick_isr,tickerDelay); |
el14jw | 3:02d9072a2507 | 365 | wait(0.25); |
el14jw | 2:80a91a737e17 | 366 | |
el14jw | 3:02d9072a2507 | 367 | while(!pvar.gameOver) { |
el14jw | 1:c4928de1f922 | 368 | if (g_gametick_flag) { |
el14jw | 5:ae641b1d04fa | 369 | g_gametick_flag = 0; |
el14jw | 1:c4928de1f922 | 370 | |
el14jw | 1:c4928de1f922 | 371 | // Screen scrolling |
el14jw | 3:02d9072a2507 | 372 | pvar = plinkScroll(pvar); |
el14jw | 1:c4928de1f922 | 373 | // Platform generation |
el14jw | 3:02d9072a2507 | 374 | pvar = plinkPlatGen(pvar); |
el14jw | 1:c4928de1f922 | 375 | // Collisions |
el14jw | 3:02d9072a2507 | 376 | pvar = plinkCollisions(pvar); |
el14jw | 3:02d9072a2507 | 377 | // Physics Engine |
el14jw | 3:02d9072a2507 | 378 | pvar = plinkPhysicsEngine(pvar); |
el14jw | 3:02d9072a2507 | 379 | // LCD drawing |
el14jw | 3:02d9072a2507 | 380 | pvar = plinkDrawScreen(pvar); |
el14jw | 1:c4928de1f922 | 381 | |
el14jw | 1:c4928de1f922 | 382 | } |
el14jw | 3:02d9072a2507 | 383 | // Sleep to conserve power until next interrupt |
el14jw | 3:02d9072a2507 | 384 | sleep(); |
el14jw | 0:23a749719479 | 385 | } |
el14jw | 1:c4928de1f922 | 386 | |
el14jw | 1:c4928de1f922 | 387 | gametick.detach(); |
el14jw | 1:c4928de1f922 | 388 | lcd.clear(); |
el14jw | 5:ae641b1d04fa | 389 | |
el14jw | 4:c2d920b17b14 | 390 | // Handle high scores and printing game over messages to LCD |
el14jw | 3:02d9072a2507 | 391 | pvar = plinkGameOver(pvar); |
el14jw | 5:ae641b1d04fa | 392 | |
el14jw | 4:c2d920b17b14 | 393 | } |
el14jw | 3:02d9072a2507 | 394 | |
el14jw | 3:02d9072a2507 | 395 | plinkvar initpvar(plinkvar pvar) |
el14jw | 3:02d9072a2507 | 396 | { |
el14jw | 3:02d9072a2507 | 397 | // Initial physics conditions |
el14jw | 3:02d9072a2507 | 398 | vector pos = {41,47}; |
el14jw | 3:02d9072a2507 | 399 | vector vel = {0,-25}; |
el14jw | 3:02d9072a2507 | 400 | vector acc = {0,10}; |
el14jw | 3:02d9072a2507 | 401 | pvar.pos = pos; |
el14jw | 3:02d9072a2507 | 402 | pvar.vel = vel; |
el14jw | 3:02d9072a2507 | 403 | pvar.acc = acc; |
el14jw | 3:02d9072a2507 | 404 | |
el14jw | 3:02d9072a2507 | 405 | // Initialising game parameters |
el14jw | 3:02d9072a2507 | 406 | pvar.height = 0; // This is the number of pixels that the lcd has 'scrolled' by |
el14jw | 3:02d9072a2507 | 407 | pvar.gameOver = 0; // When something consitutes a game over parameter this is set to 1 and the while loop is broken out of |
el14jw | 3:02d9072a2507 | 408 | pvar.platformWidth = 7 - (pvar.difficulty * 2); // Platform width is based on difficulty and also changed by power ups |
el14jw | 3:02d9072a2507 | 409 | cell powerUp = {42,-100}; // The first power up can be found at these coordinates |
el14jw | 3:02d9072a2507 | 410 | pvar.powerUp = powerUp; |
el14jw | 3:02d9072a2507 | 411 | pvar.powerUpHeight = 0; // This parameter keeps tabs on the number of pixels scrolled while a power up is active (after 100 picels the power up wears off) |
el14jw | 3:02d9072a2507 | 412 | pvar.powerUpRadius = 5; // Helpful parameter for detecting collisions |
el14jw | 3:02d9072a2507 | 413 | pvar.ballRadius = 2; // Also helpful parameter for detecting collisions and is changed in 2 power up cases |
el14jw | 3:02d9072a2507 | 414 | |
el14jw | 3:02d9072a2507 | 415 | // Initialising platforms |
el14jw | 3:02d9072a2507 | 416 | pvar.platforms[0].x = 42; |
el14jw | 3:02d9072a2507 | 417 | pvar.platforms[0].y = 46; |
el14jw | 3:02d9072a2507 | 418 | for (int i=1; i<20; i++) { |
el14jw | 3:02d9072a2507 | 419 | pvar.platforms[i].x = rand()%(84-pvar.platformWidth) + (pvar.platformWidth-1)/2; |
el14jw | 3:02d9072a2507 | 420 | pvar.platforms[i].y = pvar.platforms[i-1].y - (rand()%10 + 5); |
el14jw | 3:02d9072a2507 | 421 | } |
el14jw | 3:02d9072a2507 | 422 | |
el14jw | 3:02d9072a2507 | 423 | return pvar; |
el14jw | 3:02d9072a2507 | 424 | } |
el14jw | 3:02d9072a2507 | 425 | plinkvar plinkScroll(plinkvar pvar) |
el14jw | 3:02d9072a2507 | 426 | { |
el14jw | 3:02d9072a2507 | 427 | // Scrolling Block |
el14jw | 3:02d9072a2507 | 428 | while (pvar.pos.y < 14) { |
el14jw | 3:02d9072a2507 | 429 | pvar.pos.y++; |
el14jw | 3:02d9072a2507 | 430 | pvar.height++; |
el14jw | 3:02d9072a2507 | 431 | pvar.powerUpHeight++; |
el14jw | 3:02d9072a2507 | 432 | for (int i=0; i<20; i++) { |
el14jw | 3:02d9072a2507 | 433 | pvar.platforms[i].y++; |
el14jw | 3:02d9072a2507 | 434 | } |
el14jw | 3:02d9072a2507 | 435 | pvar.powerUp.y++; |
el14jw | 3:02d9072a2507 | 436 | } |
el14jw | 3:02d9072a2507 | 437 | return pvar; |
el14jw | 3:02d9072a2507 | 438 | } |
el14jw | 3:02d9072a2507 | 439 | plinkvar plinkPlatGen(plinkvar pvar) |
el14jw | 3:02d9072a2507 | 440 | { |
el14jw | 3:02d9072a2507 | 441 | // Platform generation |
el14jw | 3:02d9072a2507 | 442 | for (int i=0; i<20; i++) { |
el14jw | 3:02d9072a2507 | 443 | if (pvar.platforms[i].y > 47) { |
el14jw | 3:02d9072a2507 | 444 | // Stage 1 |
el14jw | 3:02d9072a2507 | 445 | if (pvar.height <= 500) { |
el14jw | 3:02d9072a2507 | 446 | if (i == 0) { |
el14jw | 3:02d9072a2507 | 447 | pvar.platforms[0].x = rand()%(84-pvar.platformWidth) + (pvar.platformWidth-1)/2; |
el14jw | 3:02d9072a2507 | 448 | pvar.platforms[0].y = pvar.platforms[19].y - (rand()%10 + 5); |
el14jw | 3:02d9072a2507 | 449 | } else { |
el14jw | 3:02d9072a2507 | 450 | pvar.platforms[i].x = rand()%(84-pvar.platformWidth) + (pvar.platformWidth-1)/2; |
el14jw | 3:02d9072a2507 | 451 | pvar.platforms[i].y = pvar.platforms[i-1].y - (rand()%10 + 5); |
el14jw | 3:02d9072a2507 | 452 | } |
el14jw | 3:02d9072a2507 | 453 | } |
el14jw | 3:02d9072a2507 | 454 | // Stage 2 |
el14jw | 3:02d9072a2507 | 455 | else if (500 < pvar.height <= 1000) { |
el14jw | 3:02d9072a2507 | 456 | if (i == 0) { |
el14jw | 3:02d9072a2507 | 457 | pvar.platforms[0].x = rand()%(84-pvar.platformWidth) + (pvar.platformWidth-1)/2; |
el14jw | 3:02d9072a2507 | 458 | pvar.platforms[0].y = pvar.platforms[19].y - (rand()%10 + 10); |
el14jw | 3:02d9072a2507 | 459 | } else { |
el14jw | 3:02d9072a2507 | 460 | pvar.platforms[i].x = rand()%(84-pvar.platformWidth) + (pvar.platformWidth-1)/2; |
el14jw | 3:02d9072a2507 | 461 | pvar.platforms[i].y = pvar.platforms[i-1].y - (rand()%10 + 10); |
el14jw | 3:02d9072a2507 | 462 | } |
el14jw | 3:02d9072a2507 | 463 | } |
el14jw | 3:02d9072a2507 | 464 | //Stage 3 |
el14jw | 3:02d9072a2507 | 465 | else if (pvar.height > 1000) { |
el14jw | 3:02d9072a2507 | 466 | if (i == 0) { |
el14jw | 3:02d9072a2507 | 467 | pvar.platforms[0].x = rand()%(84-pvar.platformWidth) + (pvar.platformWidth-1)/2; |
el14jw | 3:02d9072a2507 | 468 | pvar.platforms[0].y = pvar.platforms[19].y - (rand()%10 + 15); |
el14jw | 3:02d9072a2507 | 469 | } else { |
el14jw | 3:02d9072a2507 | 470 | pvar.platforms[i].x = rand()%(84-pvar.platformWidth) + (pvar.platformWidth-1)/2; |
el14jw | 3:02d9072a2507 | 471 | pvar.platforms[i].y = pvar.platforms[i-1].y - (rand()%10 + 15); |
el14jw | 3:02d9072a2507 | 472 | } |
el14jw | 3:02d9072a2507 | 473 | } |
el14jw | 3:02d9072a2507 | 474 | } |
el14jw | 3:02d9072a2507 | 475 | } |
el14jw | 3:02d9072a2507 | 476 | return pvar; |
el14jw | 3:02d9072a2507 | 477 | } |
el14jw | 3:02d9072a2507 | 478 | plinkvar plinkCollisions(plinkvar pvar) |
el14jw | 3:02d9072a2507 | 479 | { |
el14jw | 3:02d9072a2507 | 480 | // Collisions |
el14jw | 3:02d9072a2507 | 481 | // Platforms |
el14jw | 3:02d9072a2507 | 482 | for (int i=0; i<20; i++) { |
el14jw | 3:02d9072a2507 | 483 | if ( (int)pvar.pos.y == (pvar.platforms[i].y - 1) && (int)pvar.pos.x > pvar.platforms[i].x-pvar.platformWidth-2 && (int)pvar.pos.x < pvar.platforms[i].x+pvar.platformWidth+2 ) { |
el14jw | 3:02d9072a2507 | 484 | pvar.vel.y = -25; |
el14jw | 3:02d9072a2507 | 485 | // Play appropriate sound when bouncing |
el14jw | 3:02d9072a2507 | 486 | switch (pvar.ballRadius) { |
el14jw | 3:02d9072a2507 | 487 | case 1: |
el14jw | 3:02d9072a2507 | 488 | playSound(tune_plinkjump_small); |
el14jw | 3:02d9072a2507 | 489 | break; |
el14jw | 3:02d9072a2507 | 490 | case 2: |
el14jw | 3:02d9072a2507 | 491 | playSound(tune_plinkjump_normal); |
el14jw | 3:02d9072a2507 | 492 | break; |
el14jw | 3:02d9072a2507 | 493 | case 4: |
el14jw | 3:02d9072a2507 | 494 | playSound(tune_plinkjump_big); |
el14jw | 3:02d9072a2507 | 495 | break; |
el14jw | 3:02d9072a2507 | 496 | } |
el14jw | 3:02d9072a2507 | 497 | } |
el14jw | 3:02d9072a2507 | 498 | } |
el14jw | 3:02d9072a2507 | 499 | // Walls |
el14jw | 3:02d9072a2507 | 500 | if (pvar.pos.x <= pvar.ballRadius) { |
el14jw | 3:02d9072a2507 | 501 | pvar.vel.x = abs(pvar.vel.x); |
el14jw | 3:02d9072a2507 | 502 | } else if (pvar.pos.x >= 83 - pvar.ballRadius) { |
el14jw | 3:02d9072a2507 | 503 | pvar.vel.x = -abs(pvar.vel.x); |
el14jw | 3:02d9072a2507 | 504 | } |
el14jw | 3:02d9072a2507 | 505 | // Power Up |
el14jw | 3:02d9072a2507 | 506 | if ((int)pvar.pos.x+pvar.ballRadius >= (pvar.powerUp.x-pvar.powerUpRadius) |
el14jw | 3:02d9072a2507 | 507 | && (int)pvar.pos.x-pvar.ballRadius <= (pvar.powerUp.x+pvar.powerUpRadius) |
el14jw | 3:02d9072a2507 | 508 | && (int)pvar.pos.y+pvar.ballRadius >= (pvar.powerUp.y-pvar.powerUpRadius) |
el14jw | 3:02d9072a2507 | 509 | && (int)pvar.pos.y-pvar.ballRadius <= (pvar.powerUp.y+pvar.powerUpRadius)) { |
el14jw | 3:02d9072a2507 | 510 | // Create new powerUp box at the next 100 mark |
el14jw | 3:02d9072a2507 | 511 | pvar.powerUp.x = rand()%(84-1-(pvar.powerUpRadius*2)) + pvar.powerUpRadius; |
el14jw | 3:02d9072a2507 | 512 | pvar.powerUp.y = -100; |
el14jw | 3:02d9072a2507 | 513 | |
el14jw | 3:02d9072a2507 | 514 | //reset power up height |
el14jw | 3:02d9072a2507 | 515 | pvar.powerUpHeight = 0; |
el14jw | 3:02d9072a2507 | 516 | |
el14jw | 3:02d9072a2507 | 517 | // Choose new power up randomly |
el14jw | 3:02d9072a2507 | 518 | switch (rand()%4) { |
el14jw | 3:02d9072a2507 | 519 | case 0: |
el14jw | 3:02d9072a2507 | 520 | pvar.ballRadius = 4; |
el14jw | 3:02d9072a2507 | 521 | break; |
el14jw | 3:02d9072a2507 | 522 | case 1: |
el14jw | 3:02d9072a2507 | 523 | pvar.ballRadius = 1; |
el14jw | 3:02d9072a2507 | 524 | break; |
el14jw | 3:02d9072a2507 | 525 | case 2: |
el14jw | 3:02d9072a2507 | 526 | pvar.platformWidth = 11; |
el14jw | 3:02d9072a2507 | 527 | break; |
el14jw | 3:02d9072a2507 | 528 | case 3: |
el14jw | 3:02d9072a2507 | 529 | pvar.platformWidth = 5; |
el14jw | 3:02d9072a2507 | 530 | break; |
el14jw | 3:02d9072a2507 | 531 | default: |
el14jw | 3:02d9072a2507 | 532 | error(); |
el14jw | 3:02d9072a2507 | 533 | } |
el14jw | 5:ae641b1d04fa | 534 | } |
el14jw | 4:c2d920b17b14 | 535 | // If the powerup has been missed then generate new one |
el14jw | 4:c2d920b17b14 | 536 | else if (pvar.powerUp.y > 47+pvar.powerUpRadius) { |
el14jw | 3:02d9072a2507 | 537 | pvar.powerUp.x = rand()%(84-1-(pvar.powerUpRadius*2)) + pvar.powerUpRadius; |
el14jw | 3:02d9072a2507 | 538 | pvar.powerUp.y = -150; |
el14jw | 3:02d9072a2507 | 539 | } |
el14jw | 4:c2d920b17b14 | 540 | // After certain height achieved then cancel power up |
el14jw | 3:02d9072a2507 | 541 | if (pvar.powerUpHeight > 100) { |
el14jw | 3:02d9072a2507 | 542 | pvar.ballRadius = 2; |
el14jw | 3:02d9072a2507 | 543 | pvar.platformWidth = 7 - (pvar.difficulty * 2); |
el14jw | 3:02d9072a2507 | 544 | } |
el14jw | 3:02d9072a2507 | 545 | return pvar; |
el14jw | 3:02d9072a2507 | 546 | } |
el14jw | 3:02d9072a2507 | 547 | plinkvar plinkPhysicsEngine(plinkvar pvar) |
el14jw | 3:02d9072a2507 | 548 | { |
el14jw | 3:02d9072a2507 | 549 | // Physics engine |
el14jw | 3:02d9072a2507 | 550 | // Acceleration due to joystick |
el14jw | 3:02d9072a2507 | 551 | if (g_joystick_flag) { |
el14jw | 3:02d9072a2507 | 552 | if (joystick.direction == LEFT) { |
el14jw | 3:02d9072a2507 | 553 | pvar.acc.x = -15; |
el14jw | 3:02d9072a2507 | 554 | } else if (joystick.direction == RIGHT) { |
el14jw | 3:02d9072a2507 | 555 | pvar.acc.x = 15; |
el14jw | 3:02d9072a2507 | 556 | } else { |
el14jw | 3:02d9072a2507 | 557 | pvar.acc.x = 0; |
el14jw | 3:02d9072a2507 | 558 | } |
el14jw | 3:02d9072a2507 | 559 | } |
el14jw | 4:c2d920b17b14 | 560 | // physics iteration |
el14jw | 3:02d9072a2507 | 561 | pvar.vel.y = pvar.vel.y + (pvar.acc.y * pvar.tickerDelay * 4); |
el14jw | 3:02d9072a2507 | 562 | pvar.vel.x = 0.97F*(pvar.vel.x + (pvar.acc.x * pvar.tickerDelay)*4); // 0.97 adds slight damping factor to horizontal movement |
el14jw | 3:02d9072a2507 | 563 | pvar.pos.y = pvar.pos.y + (pvar.vel.y * pvar.tickerDelay * 4); |
el14jw | 3:02d9072a2507 | 564 | pvar.pos.x = pvar.pos.x + (pvar.vel.x * pvar.tickerDelay * 4); |
el14jw | 3:02d9072a2507 | 565 | // Boundaries of physics engine |
el14jw | 3:02d9072a2507 | 566 | if (pvar.pos.y > 48) { |
el14jw | 3:02d9072a2507 | 567 | pvar.gameOver = 1; |
el14jw | 3:02d9072a2507 | 568 | } |
el14jw | 4:c2d920b17b14 | 569 | // If ball is out of boundaries then place it back in boundaries |
el14jw | 3:02d9072a2507 | 570 | if (pvar.pos.x - pvar.ballRadius < 0) { |
el14jw | 3:02d9072a2507 | 571 | pvar.pos.x = pvar.ballRadius; |
el14jw | 3:02d9072a2507 | 572 | } else if (pvar.pos.x + pvar.ballRadius > 83) { |
el14jw | 3:02d9072a2507 | 573 | pvar.pos.x = 83-pvar.ballRadius; |
el14jw | 3:02d9072a2507 | 574 | } |
el14jw | 3:02d9072a2507 | 575 | return pvar; |
el14jw | 3:02d9072a2507 | 576 | } |
el14jw | 3:02d9072a2507 | 577 | plinkvar plinkDrawScreen(plinkvar pvar) |
el14jw | 3:02d9072a2507 | 578 | { |
el14jw | 5:ae641b1d04fa | 579 | if (g_screentick_flag) { |
el14jw | 5:ae641b1d04fa | 580 | g_screentick_flag = 0; |
el14jw | 5:ae641b1d04fa | 581 | // Drawing on lcd |
el14jw | 5:ae641b1d04fa | 582 | lcd.clear(); |
el14jw | 5:ae641b1d04fa | 583 | // Print Current Score |
el14jw | 5:ae641b1d04fa | 584 | char buffer[14]; |
el14jw | 5:ae641b1d04fa | 585 | sprintf(buffer,"Score: %d",pvar.height); |
el14jw | 5:ae641b1d04fa | 586 | lcd.printString(buffer,0,0); |
el14jw | 5:ae641b1d04fa | 587 | // Drawing ball/blob |
el14jw | 5:ae641b1d04fa | 588 | // If second blob stage |
el14jw | 5:ae641b1d04fa | 589 | int noPlatform = 1; |
el14jw | 5:ae641b1d04fa | 590 | if (pvar.ballRadius == 2) { |
el14jw | 5:ae641b1d04fa | 591 | for (int i=0; i<20; i++) { |
el14jw | 5:ae641b1d04fa | 592 | if ( (int)pvar.pos.y == (pvar.platforms[i].y - 2) && (int)pvar.pos.x > pvar.platforms[i].x-pvar.platformWidth-2 && (int)pvar.pos.x < pvar.platforms[i].x+pvar.platformWidth+2 ) { |
el14jw | 5:ae641b1d04fa | 593 | noPlatform = 0; |
el14jw | 5:ae641b1d04fa | 594 | lcd.drawRect(pvar.pos.x-2,pvar.pos.y-1,4,2,1); // X, Y, Width, Height, Fill |
el14jw | 5:ae641b1d04fa | 595 | lcd.setPixel(pvar.pos.x-1,pvar.pos.y-2); |
el14jw | 5:ae641b1d04fa | 596 | lcd.setPixel(pvar.pos.x,pvar.pos.y-2); |
el14jw | 5:ae641b1d04fa | 597 | lcd.setPixel(pvar.pos.x+1,pvar.pos.y-2); |
el14jw | 5:ae641b1d04fa | 598 | lcd.setPixel(pvar.pos.x-3,pvar.pos.y+1); |
el14jw | 5:ae641b1d04fa | 599 | lcd.setPixel(pvar.pos.x+3,pvar.pos.y+1); |
el14jw | 5:ae641b1d04fa | 600 | } |
el14jw | 5:ae641b1d04fa | 601 | // If third blob stage |
el14jw | 5:ae641b1d04fa | 602 | else if ( (int)pvar.pos.y == (pvar.platforms[i].y - 1) && (int)pvar.pos.x > pvar.platforms[i].x-pvar.platformWidth-2 && (int)pvar.pos.x < pvar.platforms[i].x+pvar.platformWidth+2 ) { |
el14jw | 5:ae641b1d04fa | 603 | noPlatform = 0; |
el14jw | 5:ae641b1d04fa | 604 | lcd.drawRect(pvar.pos.x-3,pvar.pos.y-1,6,1,1); // X, Y, Width, Height, Fill |
el14jw | 5:ae641b1d04fa | 605 | lcd.setPixel(pvar.pos.x-4,pvar.pos.y); |
el14jw | 5:ae641b1d04fa | 606 | lcd.setPixel(pvar.pos.x+4,pvar.pos.y); |
el14jw | 5:ae641b1d04fa | 607 | lcd.setPixel(pvar.pos.x-2,pvar.pos.y-2); |
el14jw | 5:ae641b1d04fa | 608 | lcd.setPixel(pvar.pos.x-1,pvar.pos.y-2); |
el14jw | 5:ae641b1d04fa | 609 | lcd.setPixel(pvar.pos.x,pvar.pos.y-2); |
el14jw | 5:ae641b1d04fa | 610 | lcd.setPixel(pvar.pos.x+1,pvar.pos.y-2); |
el14jw | 5:ae641b1d04fa | 611 | lcd.setPixel(pvar.pos.x+2,pvar.pos.y-2); |
el14jw | 5:ae641b1d04fa | 612 | } |
el14jw | 5:ae641b1d04fa | 613 | } |
el14jw | 5:ae641b1d04fa | 614 | } |
el14jw | 5:ae641b1d04fa | 615 | // Else default blob stage |
el14jw | 5:ae641b1d04fa | 616 | if (noPlatform == 1) { |
el14jw | 5:ae641b1d04fa | 617 | lcd.drawCircle((int)pvar.pos.x,(int)pvar.pos.y,pvar.ballRadius,1); // X, Y, Radius, Fill |
el14jw | 5:ae641b1d04fa | 618 | lcd.refresh(); |
el14jw | 5:ae641b1d04fa | 619 | } |
el14jw | 5:ae641b1d04fa | 620 | // Platforms and boundaries drawing |
el14jw | 3:02d9072a2507 | 621 | for (int i=0; i<20; i++) { |
el14jw | 5:ae641b1d04fa | 622 | if (pvar.platforms[i].y > 0) { |
el14jw | 5:ae641b1d04fa | 623 | lcd.drawRect( pvar.platforms[i].x-pvar.platformWidth ,pvar.platforms[i].y,pvar.platformWidth*2,1,1); // X, Y, Width, Height, Fill |
el14jw | 3:02d9072a2507 | 624 | } |
el14jw | 5:ae641b1d04fa | 625 | } |
el14jw | 5:ae641b1d04fa | 626 | lcd.drawLine(0,0,0,47,1); // x0,y0,x1,y1,type |
el14jw | 5:ae641b1d04fa | 627 | lcd.drawLine(83,0,83,47,1); |
el14jw | 5:ae641b1d04fa | 628 | // PowerUp drawing |
el14jw | 5:ae641b1d04fa | 629 | if (pvar.powerUp.y > 0-pvar.powerUpRadius && pvar.powerUp.y < 47+pvar.powerUpRadius) { |
el14jw | 5:ae641b1d04fa | 630 | lcd.drawRect(pvar.powerUp.x-pvar.powerUpRadius,pvar.powerUp.y-pvar.powerUpRadius,10,10,0); // X, Y, Width, Height, Fill |
el14jw | 5:ae641b1d04fa | 631 | lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y+3); |
el14jw | 5:ae641b1d04fa | 632 | lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y+1); |
el14jw | 5:ae641b1d04fa | 633 | lcd.setPixel(pvar.powerUp.x+1,pvar.powerUp.y); |
el14jw | 5:ae641b1d04fa | 634 | lcd.setPixel(pvar.powerUp.x+2,pvar.powerUp.y-1); |
el14jw | 5:ae641b1d04fa | 635 | lcd.setPixel(pvar.powerUp.x+2,pvar.powerUp.y-2); |
el14jw | 5:ae641b1d04fa | 636 | lcd.setPixel(pvar.powerUp.x+1,pvar.powerUp.y-3); |
el14jw | 5:ae641b1d04fa | 637 | lcd.setPixel(pvar.powerUp.x,pvar.powerUp.y-3); |
el14jw | 5:ae641b1d04fa | 638 | lcd.setPixel(pvar.powerUp.x-1,pvar.powerUp.y-3); |
el14jw | 5:ae641b1d04fa | 639 | lcd.setPixel(pvar.powerUp.x-2,pvar.powerUp.y-2); |
el14jw | 5:ae641b1d04fa | 640 | } |
el14jw | 5:ae641b1d04fa | 641 | |
el14jw | 5:ae641b1d04fa | 642 | lcd.refresh(); |
el14jw | 5:ae641b1d04fa | 643 | // Looks more pleasing when the ball pauses to bounce |
el14jw | 5:ae641b1d04fa | 644 | if (noPlatform == 0) { |
el14jw | 5:ae641b1d04fa | 645 | wait(0.03); |
el14jw | 3:02d9072a2507 | 646 | } |
el14jw | 3:02d9072a2507 | 647 | } |
el14jw | 3:02d9072a2507 | 648 | return pvar; |
el14jw | 3:02d9072a2507 | 649 | } |
el14jw | 5:ae641b1d04fa | 650 | plinkvar plinkGameOver(plinkvar pvar) |
el14jw | 5:ae641b1d04fa | 651 | { |
el14jw | 3:02d9072a2507 | 652 | // Handle saving high scores to SD card |
el14jw | 1:c4928de1f922 | 653 | // Read previous highscore if one exists |
el14jw | 1:c4928de1f922 | 654 | fp = fopen("/sd/plinkhighscore.txt", "r"); |
el14jw | 1:c4928de1f922 | 655 | int current_high_score = -1; // -1 to demonstrate it has changed after reading |
el14jw | 1:c4928de1f922 | 656 | |
el14jw | 1:c4928de1f922 | 657 | if (fp == NULL) { // if it can't open the file then print error message |
el14jw | 1:c4928de1f922 | 658 | lcd.printString("Failed Read",0,5); |
el14jw | 1:c4928de1f922 | 659 | } else { // opened file so can write |
el14jw | 1:c4928de1f922 | 660 | fscanf(fp,"%d",¤t_high_score); // ensure data type matches - note address operator (&) |
el14jw | 1:c4928de1f922 | 661 | fclose(fp); // ensure you close the file after reading |
el14jw | 1:c4928de1f922 | 662 | } |
el14jw | 1:c4928de1f922 | 663 | |
el14jw | 1:c4928de1f922 | 664 | // Writing score to sd card if new high score |
el14jw | 3:02d9072a2507 | 665 | if (current_high_score < pvar.height && current_high_score != -1) { |
el14jw | 1:c4928de1f922 | 666 | fp = fopen("/sd/plinkhighscore.txt", "w"); |
el14jw | 1:c4928de1f922 | 667 | if (fp == NULL) { // if it can't open the file then print error message |
el14jw | 1:c4928de1f922 | 668 | lcd.printString("No SD Card ",0,5); |
el14jw | 1:c4928de1f922 | 669 | } else { // opened file so can write |
el14jw | 3:02d9072a2507 | 670 | fprintf(fp,"%d",pvar.height); // ensure data type matches |
el14jw | 1:c4928de1f922 | 671 | fclose(fp); // ensure you close the file after writing |
el14jw | 1:c4928de1f922 | 672 | } |
el14jw | 1:c4928de1f922 | 673 | } |
el14jw | 1:c4928de1f922 | 674 | |
el14jw | 1:c4928de1f922 | 675 | // Appropriate strings printed to LCD |
el14jw | 1:c4928de1f922 | 676 | lcd.printString("Game Over",20,0); |
el14jw | 5:ae641b1d04fa | 677 | if (current_high_score == -2) { |
el14jw | 5:ae641b1d04fa | 678 | lcd.printString("New High Score:",0,1); |
el14jw | 5:ae641b1d04fa | 679 | } else if (current_high_score != -1 && current_high_score < pvar.height) { |
el14jw | 1:c4928de1f922 | 680 | lcd.printString("New High Score",0,1); |
el14jw | 1:c4928de1f922 | 681 | lcd.printString("Previously",0,3); |
el14jw | 5:ae641b1d04fa | 682 | } else if (current_high_score != -1 && current_high_score >= pvar.height) { |
el14jw | 5:ae641b1d04fa | 683 | lcd.printString("Score:",0,1); |
el14jw | 1:c4928de1f922 | 684 | lcd.printString("High Score",0,3); |
el14jw | 1:c4928de1f922 | 685 | } else { |
el14jw | 1:c4928de1f922 | 686 | lcd.printString("Score:",0,1); |
el14jw | 1:c4928de1f922 | 687 | lcd.printString("No Previous",0,3); |
el14jw | 1:c4928de1f922 | 688 | } |
el14jw | 1:c4928de1f922 | 689 | // Print score |
el14jw | 1:c4928de1f922 | 690 | char buffer[14]; |
el14jw | 3:02d9072a2507 | 691 | sprintf(buffer,"%d",pvar.height); |
el14jw | 1:c4928de1f922 | 692 | lcd.printString(buffer,20,2); |
el14jw | 1:c4928de1f922 | 693 | // Print previous high-score |
el14jw | 5:ae641b1d04fa | 694 | if (current_high_score != -1 && current_high_score != -2) { |
el14jw | 1:c4928de1f922 | 695 | char str[14]; |
el14jw | 1:c4928de1f922 | 696 | sprintf(str,"%d",current_high_score); |
el14jw | 1:c4928de1f922 | 697 | lcd.printString(str,20,4); |
el14jw | 1:c4928de1f922 | 698 | } |
el14jw | 2:80a91a737e17 | 699 | |
el14jw | 1:c4928de1f922 | 700 | playSound(tune_gameOver); |
el14jw | 0:23a749719479 | 701 | lcd.refresh(); |
el14jw | 1:c4928de1f922 | 702 | wait(3.0); |
el14jw | 4:c2d920b17b14 | 703 | // Reset all flags so no unexpected behaviour occurs |
el14jw | 1:c4928de1f922 | 704 | g_buttonA_flag = 0; |
el14jw | 1:c4928de1f922 | 705 | g_buttonB_flag = 0; |
el14jw | 1:c4928de1f922 | 706 | g_buttonjoy_flag = 0; |
el14jw | 3:02d9072a2507 | 707 | return pvar; |
el14jw | 0:23a749719479 | 708 | } |
el14jw | 0:23a749719479 | 709 | |
el14jw | 0:23a749719479 | 710 | |
el14jw | 0:23a749719479 | 711 | // ISR's |
el14jw | 1:c4928de1f922 | 712 | void buttonA_isr() |
el14jw | 1:c4928de1f922 | 713 | { |
el14jw | 1:c4928de1f922 | 714 | g_buttonA_flag = 1; |
el14jw | 1:c4928de1f922 | 715 | } |
el14jw | 1:c4928de1f922 | 716 | void buttonB_isr() |
el14jw | 1:c4928de1f922 | 717 | { |
el14jw | 1:c4928de1f922 | 718 | g_buttonB_flag = 1; |
el14jw | 1:c4928de1f922 | 719 | } |
el14jw | 1:c4928de1f922 | 720 | void buttonjoy_isr() |
el14jw | 1:c4928de1f922 | 721 | { |
el14jw | 1:c4928de1f922 | 722 | g_buttonjoy_flag = 1; |
el14jw | 1:c4928de1f922 | 723 | } |
el14jw | 1:c4928de1f922 | 724 | void gametick_isr() |
el14jw | 1:c4928de1f922 | 725 | { |
el14jw | 1:c4928de1f922 | 726 | g_gametick_flag = 1; |
el14jw | 1:c4928de1f922 | 727 | } |
el14jw | 5:ae641b1d04fa | 728 | void screentick_isr() |
el14jw | 5:ae641b1d04fa | 729 | { |
el14jw | 5:ae641b1d04fa | 730 | g_screentick_flag = 1; |
el14jw | 5:ae641b1d04fa | 731 | } |
el14jw | 0:23a749719479 | 732 | |
el14jw | 4:c2d920b17b14 | 733 | |
el14jw | 0:23a749719479 | 734 | // Initialises Inputs |
el14jw | 0:23a749719479 | 735 | void initInputs() |
el14jw | 0:23a749719479 | 736 | { |
el14jw | 0:23a749719479 | 737 | |
el14jw | 0:23a749719479 | 738 | errorLED = 1; |
el14jw | 0:23a749719479 | 739 | |
el14jw | 0:23a749719479 | 740 | /// Setting up Interrupt service routines for input buttons |
el14jw | 0:23a749719479 | 741 | /// PullDown mode is assumed |
el14jw | 0:23a749719479 | 742 | buttonA.rise(&buttonA_isr); |
el14jw | 0:23a749719479 | 743 | buttonB.rise(&buttonB_isr); |
el14jw | 0:23a749719479 | 744 | buttonjoy.rise(&buttonjoy_isr); |
el14jw | 0:23a749719479 | 745 | buttonA.mode(PullDown); |
el14jw | 0:23a749719479 | 746 | buttonB.mode(PullDown); |
el14jw | 0:23a749719479 | 747 | buttonjoy.mode(PullDown); |
el14jw | 0:23a749719479 | 748 | |
el14jw | 0:23a749719479 | 749 | /// Testing LCD display works (splash screen) |
el14jw | 0:23a749719479 | 750 | lcd.init(); |
el14jw | 2:80a91a737e17 | 751 | wait(0.5); |
el14jw | 5:ae641b1d04fa | 752 | lcd.setBrightness(0.5); // Brightness set to maximum duty cycle so it isn't affected by changing frequency of buzzer |
el14jw | 0:23a749719479 | 753 | lcd.printString("Calibrating",8,0); |
el14jw | 0:23a749719479 | 754 | lcd.printString("Do not move",8,1); |
el14jw | 0:23a749719479 | 755 | lcd.printString("Joystick",18,2); |
el14jw | 0:23a749719479 | 756 | lcd.refresh(); |
el14jw | 0:23a749719479 | 757 | |
el14jw | 0:23a749719479 | 758 | /// Calibrating the Joystick on startup |
el14jw | 0:23a749719479 | 759 | calibrateJoystick(); |
el14jw | 0:23a749719479 | 760 | /// read joystick 10 times per second |
el14jw | 0:23a749719479 | 761 | pollJoystick.attach(&updateJoystick,1.0/10.0); |
el14jw | 5:ae641b1d04fa | 762 | |
el14jw | 5:ae641b1d04fa | 763 | // Patch for sd card access not working first time |
el14jw | 5:ae641b1d04fa | 764 | fp = fopen("/sd/test.txt", "w"); |
el14jw | 3:02d9072a2507 | 765 | if (fp != NULL) { |
el14jw | 3:02d9072a2507 | 766 | fclose(fp); |
el14jw | 2:80a91a737e17 | 767 | } |
el14jw | 5:ae641b1d04fa | 768 | fp = fopen("/sd/test.txt", "w"); |
el14jw | 5:ae641b1d04fa | 769 | if (fp != NULL) { |
el14jw | 5:ae641b1d04fa | 770 | fclose(fp); // ensure you close the file after writing |
el14jw | 5:ae641b1d04fa | 771 | } |
el14jw | 5:ae641b1d04fa | 772 | |
el14jw | 5:ae641b1d04fa | 773 | // If file does not exist then create it |
el14jw | 5:ae641b1d04fa | 774 | fp = fopen("/sd/plinkhighscore.txt","r"); |
el14jw | 5:ae641b1d04fa | 775 | if (fp == NULL) { |
el14jw | 5:ae641b1d04fa | 776 | fp = fopen("/sd/plinkhighscore.txt","w"); |
el14jw | 5:ae641b1d04fa | 777 | if (fp != NULL) { |
el14jw | 5:ae641b1d04fa | 778 | fprintf(fp,"%d",-2); |
el14jw | 5:ae641b1d04fa | 779 | fclose(fp); |
el14jw | 5:ae641b1d04fa | 780 | } |
el14jw | 5:ae641b1d04fa | 781 | } else { |
el14jw | 5:ae641b1d04fa | 782 | fclose(fp); |
el14jw | 5:ae641b1d04fa | 783 | } |
el14jw | 5:ae641b1d04fa | 784 | |
el14jw | 5:ae641b1d04fa | 785 | fp = fopen("/sd/snakehighscore.txt","r"); |
el14jw | 5:ae641b1d04fa | 786 | if (fp == NULL) { |
el14jw | 5:ae641b1d04fa | 787 | fp = fopen("/sd/snakehighscore.txt","w"); |
el14jw | 5:ae641b1d04fa | 788 | if (fp != NULL) { |
el14jw | 5:ae641b1d04fa | 789 | fprintf(fp,"%d",-2); |
el14jw | 5:ae641b1d04fa | 790 | fclose(fp); |
el14jw | 5:ae641b1d04fa | 791 | } |
el14jw | 5:ae641b1d04fa | 792 | } else { |
el14jw | 5:ae641b1d04fa | 793 | fclose(fp); |
el14jw | 5:ae641b1d04fa | 794 | } |
el14jw | 5:ae641b1d04fa | 795 | |
el14jw | 0:23a749719479 | 796 | wait(1.0); |
el14jw | 0:23a749719479 | 797 | } |
el14jw | 5:ae641b1d04fa | 798 | |
el14jw | 0:23a749719479 | 799 | // Hangs on an error |
el14jw | 0:23a749719479 | 800 | void error() |
el14jw | 0:23a749719479 | 801 | { |
el14jw | 0:23a749719479 | 802 | while(1) { |
el14jw | 0:23a749719479 | 803 | errorLED = !errorLED; |
el14jw | 0:23a749719479 | 804 | wait(0.2); |
el14jw | 0:23a749719479 | 805 | } |
el14jw | 0:23a749719479 | 806 | } |
el14jw | 0:23a749719479 | 807 | |
el14jw | 0:23a749719479 | 808 | // Menu function for handling the printing and selecting of menu screens |
el14jw | 0:23a749719479 | 809 | int menu(const stringList* menuList,int lines) |
el14jw | 0:23a749719479 | 810 | { |
el14jw | 0:23a749719479 | 811 | int select = 0; |
el14jw | 1:c4928de1f922 | 812 | // While either joystick button or button A or button B are not on then continue selection process |
el14jw | 1:c4928de1f922 | 813 | // Once either button is on the the selected value is returned |
el14jw | 1:c4928de1f922 | 814 | while(g_buttonjoy_flag == 0 && g_buttonA_flag == 0 && g_buttonB_flag == 0) { |
el14jw | 0:23a749719479 | 815 | |
el14jw | 0:23a749719479 | 816 | // Changes the value of variable select determined by what the joystick value is |
el14jw | 0:23a749719479 | 817 | if (g_joystick_flag) { |
el14jw | 0:23a749719479 | 818 | if (joystick.direction == UP) { |
el14jw | 0:23a749719479 | 819 | if (select == 0) { |
el14jw | 0:23a749719479 | 820 | select = lines-2; |
el14jw | 0:23a749719479 | 821 | } else { |
el14jw | 0:23a749719479 | 822 | select--; |
el14jw | 0:23a749719479 | 823 | } |
el14jw | 0:23a749719479 | 824 | } else if(joystick.direction == DOWN) { |
el14jw | 0:23a749719479 | 825 | if (select == lines-2) { |
el14jw | 0:23a749719479 | 826 | select = 0; |
el14jw | 0:23a749719479 | 827 | } else { |
el14jw | 0:23a749719479 | 828 | select++; |
el14jw | 0:23a749719479 | 829 | } |
el14jw | 0:23a749719479 | 830 | } |
el14jw | 0:23a749719479 | 831 | } |
el14jw | 0:23a749719479 | 832 | |
el14jw | 0:23a749719479 | 833 | // Prints the correct strings |
el14jw | 0:23a749719479 | 834 | drawStrings(menuList,lines); |
el14jw | 1:c4928de1f922 | 835 | int line = select + 1; |
el14jw | 0:23a749719479 | 836 | char buffer[14]; |
el14jw | 1:c4928de1f922 | 837 | sprintf(buffer,">> %s",menuList[line].str); |
el14jw | 1:c4928de1f922 | 838 | lcd.printString(buffer,menuList[line].offset,line); |
el14jw | 1:c4928de1f922 | 839 | |
el14jw | 0:23a749719479 | 840 | if (g_joystick_flag) { |
el14jw | 0:23a749719479 | 841 | g_joystick_flag = 0; |
el14jw | 1:c4928de1f922 | 842 | // Adds acceptable scrolling delay |
el14jw | 0:23a749719479 | 843 | wait(0.2); |
el14jw | 0:23a749719479 | 844 | } |
el14jw | 0:23a749719479 | 845 | sleep(); |
el14jw | 0:23a749719479 | 846 | } |
el14jw | 0:23a749719479 | 847 | // Debouncing |
el14jw | 1:c4928de1f922 | 848 | wait(0.2); |
el14jw | 0:23a749719479 | 849 | g_buttonjoy_flag = 0; |
el14jw | 0:23a749719479 | 850 | g_buttonA_flag = 0; |
el14jw | 1:c4928de1f922 | 851 | // Returns -1 if B is pressed to automatically go back a menu |
el14jw | 1:c4928de1f922 | 852 | if (g_buttonB_flag) { |
el14jw | 1:c4928de1f922 | 853 | g_buttonB_flag = 0; |
el14jw | 1:c4928de1f922 | 854 | select = -1; |
el14jw | 1:c4928de1f922 | 855 | } |
el14jw | 0:23a749719479 | 856 | return select; |
el14jw | 0:23a749719479 | 857 | } |
el14jw | 1:c4928de1f922 | 858 | // Draw Strings function used for plotting an array of stringList to the LCD |
el14jw | 0:23a749719479 | 859 | void drawStrings(const stringList* list,int lines) |
el14jw | 0:23a749719479 | 860 | { |
el14jw | 0:23a749719479 | 861 | lcd.clear(); |
el14jw | 0:23a749719479 | 862 | for (int i=0; i<lines; i++) { |
el14jw | 0:23a749719479 | 863 | lcd.printString(list[i].str,list[i].offset,i); |
el14jw | 0:23a749719479 | 864 | } |
el14jw | 0:23a749719479 | 865 | } |
el14jw | 0:23a749719479 | 866 | |
el14jw | 0:23a749719479 | 867 | |
el14jw | 0:23a749719479 | 868 | /// Read default positions of the joystick to calibrate later readings |
el14jw | 0:23a749719479 | 869 | void calibrateJoystick() |
el14jw | 0:23a749719479 | 870 | { |
el14jw | 0:23a749719479 | 871 | // must not move during calibration |
el14jw | 0:23a749719479 | 872 | joystick.x0 = xPot; /// initial positions in the range 0.0 to 1.0 (0.5 if centred exactly) |
el14jw | 0:23a749719479 | 873 | joystick.y0 = yPot; |
el14jw | 0:23a749719479 | 874 | } |
el14jw | 0:23a749719479 | 875 | void updateJoystick() |
el14jw | 0:23a749719479 | 876 | { |
el14jw | 0:23a749719479 | 877 | /// read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred) |
el14jw | 0:23a749719479 | 878 | joystick.x = xPot - joystick.x0; |
el14jw | 0:23a749719479 | 879 | joystick.y = yPot - joystick.y0; |
el14jw | 0:23a749719479 | 880 | |
el14jw | 0:23a749719479 | 881 | // calculate direction depending on x,y values |
el14jw | 0:23a749719479 | 882 | // tolerance allows a little lee-way in case joystick not exactly in the stated direction |
el14jw | 0:23a749719479 | 883 | if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { |
el14jw | 0:23a749719479 | 884 | joystick.direction = CENTRE; |
el14jw | 2:80a91a737e17 | 885 | } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { |
el14jw | 0:23a749719479 | 886 | joystick.direction = UP; |
el14jw | 2:80a91a737e17 | 887 | } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) { |
el14jw | 0:23a749719479 | 888 | joystick.direction = DOWN; |
el14jw | 0:23a749719479 | 889 | } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { |
el14jw | 0:23a749719479 | 890 | joystick.direction = RIGHT; |
el14jw | 0:23a749719479 | 891 | } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) { |
el14jw | 0:23a749719479 | 892 | joystick.direction = LEFT; |
el14jw | 0:23a749719479 | 893 | } else { |
el14jw | 0:23a749719479 | 894 | joystick.direction = UNKNOWN; |
el14jw | 0:23a749719479 | 895 | } |
el14jw | 0:23a749719479 | 896 | |
el14jw | 0:23a749719479 | 897 | // set flag for printing |
el14jw | 0:23a749719479 | 898 | g_joystick_flag = 1; |
el14jw | 0:23a749719479 | 899 | } |