Kaif Kutchwala 201267448 ELEC2645 Project

Dependencies:   mbed

Committer:
KaifK
Date:
Tue May 26 14:45:02 2020 +0000
Revision:
28:215e8327d4e6
Parent:
26:04b2d7742a84
Child:
29:532e5c371be4
shot now misses if power is set too low and the ball now travels at speed proportional to power in shot animation

Who changed what in which revision?

UserRevisionLine numberNew contents of line
KaifK 4:08a0ff6668df 1 #include "Game.h"
KaifK 25:467d8fd0fec4 2
KaifK 21:d5b1160f349f 3 SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd");
KaifK 20:c697902b844f 4 Ticker ticker;
KaifK 25:467d8fd0fec4 5 FILE *fp;
KaifK 20:c697902b844f 6
KaifK 20:c697902b844f 7 volatile int sound_timer_flag = 0;
KaifK 20:c697902b844f 8 volatile int sound_sample = 0;
KaifK 21:d5b1160f349f 9 volatile int level_flag = 1; //initially set
KaifK 20:c697902b844f 10
KaifK 20:c697902b844f 11 void timer_isr();
KaifK 8:5ede90f99a27 12
KaifK 9:e6566d09f087 13 Game::Game(N5110 &lcd, Gamepad &pad, Ball &ball) {
KaifK 9:e6566d09f087 14 _lcd = &lcd;
KaifK 9:e6566d09f087 15 _pad = &pad;
KaifK 9:e6566d09f087 16 _ball = &ball;
KaifK 9:e6566d09f087 17 }
KaifK 4:08a0ff6668df 18 Game::~Game() {}
KaifK 4:08a0ff6668df 19
KaifK 4:08a0ff6668df 20 void Game::init() {
KaifK 24:c110f92fe266 21 level_flag = 1;
KaifK 4:08a0ff6668df 22 _is_goal = false;
KaifK 8:5ede90f99a27 23 _lives = 3;
KaifK 16:1f196a0e12be 24 _new_lives_threshold = 0;
KaifK 12:ca7329a41fc5 25 _level = 1;
KaifK 8:5ede90f99a27 26 _score = 0;
KaifK 9:e6566d09f087 27 _speed = 0.30f;
KaifK 16:1f196a0e12be 28 _new_speed_threshold = 0.00f;
KaifK 9:e6566d09f087 29 _x_val = 42.00f;
KaifK 9:e6566d09f087 30 _y_val = 0.00f;
KaifK 7:2a3b566aedd3 31 _shot_x = 0;
KaifK 7:2a3b566aedd3 32 _shot_y = 0;
KaifK 22:76bb0f52be8b 33 //Initialising Highscore
KaifK 22:76bb0f52be8b 34 fp = fopen("/sd/highscore.txt", "r"); //check for file
KaifK 25:467d8fd0fec4 35 if (fp == NULL) { // if it can't open the file (file does not exist)
KaifK 22:76bb0f52be8b 36 printf("No exisiting highscore!\n");
KaifK 22:76bb0f52be8b 37 set_highscore(0); // initialise highscore to zero
KaifK 25:467d8fd0fec4 38 } else { // if file exists, read highscore and initialise to that value
KaifK 25:467d8fd0fec4 39 fscanf(fp, "%d", & _highscore);
KaifK 25:467d8fd0fec4 40 printf("Initial Highscore found: %d\n", _highscore);
KaifK 22:76bb0f52be8b 41 set_highscore(_highscore);
KaifK 25:467d8fd0fec4 42 fclose(fp); // ensure you close the file after reading
KaifK 25:467d8fd0fec4 43 }
KaifK 4:08a0ff6668df 44 }
KaifK 9:e6566d09f087 45 void Game::play() {
KaifK 16:1f196a0e12be 46 // if all live are lost game ends
KaifK 25:467d8fd0fec4 47 while (_lives > 0) {
KaifK 17:2fbe40177b9c 48 updateSpeed();
KaifK 25:467d8fd0fec4 49 updateLives();
KaifK 17:2fbe40177b9c 50 updateLevel();
KaifK 17:2fbe40177b9c 51 readInput();
KaifK 25:467d8fd0fec4 52 if (_is_goal) { _score++; }
KaifK 25:467d8fd0fec4 53 else {
KaifK 28:215e8327d4e6 54 //ball should not go through obstacle hence y value limited to 21
KaifK 28:215e8327d4e6 55 //this is done after calculations to ensure accurate isGoal checking
KaifK 28:215e8327d4e6 56 if (_shot_y >= 9 && _shot_y <= 19) { _shot_y = 21; }
KaifK 25:467d8fd0fec4 57 if (_shot_y <= 5) { _shot_y = 3; }
KaifK 25:467d8fd0fec4 58 _lives--;
KaifK 15:5bf3f951d337 59 }
KaifK 25:467d8fd0fec4 60 _ball -> playShot(_shot_x, _shot_y);
KaifK 25:467d8fd0fec4 61 print_goal_message((int) _is_goal);
KaifK 12:ca7329a41fc5 62 }
KaifK 25:467d8fd0fec4 63 if (_score > _highscore) { set_highscore(_score); }
KaifK 25:467d8fd0fec4 64 _pad -> leds(0.0); //turn of all leds
KaifK 8:5ede90f99a27 65 }
KaifK 7:2a3b566aedd3 66
KaifK 9:e6566d09f087 67 void Game::readInput() {
KaifK 25:467d8fd0fec4 68 _pad -> reset_buttons(); //forced debounce/reset
KaifK 9:e6566d09f087 69 _x_val = 42; //reset x_val
KaifK 9:e6566d09f087 70 _y_val = 0; //reset y_val
KaifK 25:467d8fd0fec4 71 while (!_pad -> A_pressed()) {
KaifK 9:e6566d09f087 72 pointer_input();
KaifK 7:2a3b566aedd3 73 }
KaifK 25:467d8fd0fec4 74 _pad -> reset_buttons(); //forced debounce/reset
KaifK 25:467d8fd0fec4 75 while (!_pad -> B_pressed()) {
KaifK 9:e6566d09f087 76 power_meter_input();
KaifK 6:09a555c0d997 77 }
KaifK 8:5ede90f99a27 78 convert_to_shot_x();
KaifK 7:2a3b566aedd3 79 convert_to_shot_y();
KaifK 25:467d8fd0fec4 80 _is_goal = _ball -> isGoal(_level, _shot_x, _shot_y);
KaifK 20:c697902b844f 81 //printf("x val = %.2f \n",_x_val);
KaifK 20:c697902b844f 82 //printf("shot_x val = %d \n",_shot_x);
KaifK 20:c697902b844f 83 //printf("y val = %.2f \n",_y_val);
KaifK 20:c697902b844f 84 //printf("shot_y val = %d \n",_shot_y);
KaifK 6:09a555c0d997 85 }
KaifK 9:e6566d09f087 86 void Game::updateLives() {
KaifK 25:467d8fd0fec4 87 int val[6] = {0, 0, 0, 0, 0, 0};
KaifK 16:1f196a0e12be 88 // +1 life if score hits a multiple of 5 provided less than 3 lives left
KaifK 16:1f196a0e12be 89 //update threshold so lives don't increase if score stays same
KaifK 25:467d8fd0fec4 90 if (_score % 5 == 0 && _score != _new_lives_threshold && _lives != 3) {
KaifK 25:467d8fd0fec4 91 _lives++;
KaifK 16:1f196a0e12be 92 _new_lives_threshold = _score;
KaifK 22:76bb0f52be8b 93 playGoalSound(4);
KaifK 16:1f196a0e12be 94 }
KaifK 20:c697902b844f 95 //printf("Lives = %d \n", _lives);
KaifK 25:467d8fd0fec4 96 switch (_lives) {
KaifK 25:467d8fd0fec4 97 case 0:
KaifK 25:467d8fd0fec4 98 break;
KaifK 25:467d8fd0fec4 99 case 1: //red leds only
KaifK 25:467d8fd0fec4 100 val[0] = val[3] = 1;
KaifK 25:467d8fd0fec4 101 break;
KaifK 25:467d8fd0fec4 102 case 2: //red and yellow leds
KaifK 25:467d8fd0fec4 103 val[0] = val[1] = val[3] = val[4] = 1;
KaifK 25:467d8fd0fec4 104 break;
KaifK 25:467d8fd0fec4 105 case 3: //all leds on
KaifK 25:467d8fd0fec4 106 for (int i = 0; i < 6; i++) { val[i] = 1; }
KaifK 25:467d8fd0fec4 107 break;
KaifK 25:467d8fd0fec4 108 default:
KaifK 25:467d8fd0fec4 109 error("Invalid Number of Lives");
KaifK 25:467d8fd0fec4 110 break;
KaifK 5:ed71996c0534 111 }
KaifK 17:2fbe40177b9c 112 updateLeds(val);
KaifK 5:ed71996c0534 113 }
KaifK 9:e6566d09f087 114 void Game::updateScore() {
KaifK 5:ed71996c0534 115 char buffer[12];
KaifK 25:467d8fd0fec4 116 sprintf(buffer, "%d", _score);
KaifK 25:467d8fd0fec4 117 _lcd -> printString(buffer, 2, 5);
KaifK 9:e6566d09f087 118 }
KaifK 9:e6566d09f087 119 void Game::updateSpeed() {
KaifK 25:467d8fd0fec4 120 if (abs(_speed) <= 3) { // max speed = 3
KaifK 25:467d8fd0fec4 121 if (_score % 3 == 0 && _score != _new_speed_threshold) {
KaifK 26:04b2d7742a84 122 // add 0.2 everytime score hits a multiple of 3
KaifK 26:04b2d7742a84 123 _speed = abs(_speed) + 0.20f;
KaifK 16:1f196a0e12be 124 //update threshold so speed does not increase if score stays same
KaifK 25:467d8fd0fec4 125 _new_speed_threshold = _score;
KaifK 9:e6566d09f087 126 }
KaifK 9:e6566d09f087 127 }
KaifK 20:c697902b844f 128 //printf("speed = %.2f \n", _speed);
KaifK 20:c697902b844f 129 //printf("score = %d \n", _score);
KaifK 5:ed71996c0534 130 }
KaifK 17:2fbe40177b9c 131 void Game::updateLevel() {
KaifK 17:2fbe40177b9c 132 _level = random_level_gen(10); //generate random level
KaifK 25:467d8fd0fec4 133 if (level_flag == 1) { //first level is always level 1
KaifK 21:d5b1160f349f 134 level_flag = 0; //flag always stays 0 after first time
KaifK 25:467d8fd0fec4 135 _level = 1;
KaifK 25:467d8fd0fec4 136 }
KaifK 25:467d8fd0fec4 137 _ball -> set_level(_level); //set level
KaifK 20:c697902b844f 138 //printf("Level (in game) = %d \n", _level);
KaifK 17:2fbe40177b9c 139 }
KaifK 25:467d8fd0fec4 140 void Game::updateLeds(int val[6]) {
KaifK 25:467d8fd0fec4 141 _pad -> led(1, val[0]);
KaifK 25:467d8fd0fec4 142 _pad -> led(2, val[1]);
KaifK 25:467d8fd0fec4 143 _pad -> led(3, val[2]);
KaifK 25:467d8fd0fec4 144 _pad -> led(4, val[3]);
KaifK 25:467d8fd0fec4 145 _pad -> led(5, val[4]);
KaifK 25:467d8fd0fec4 146 _pad -> led(6, val[5]);
KaifK 17:2fbe40177b9c 147 }
KaifK 20:c697902b844f 148 void Game::playGoalSound(int sound) {
KaifK 20:c697902b844f 149 sound_sample = 0;
KaifK 20:c697902b844f 150 float val = 0.0f;
KaifK 20:c697902b844f 151 int NUM_ELEMENTS = 0;
KaifK 26:04b2d7742a84 152 ticker.attach( & timer_isr, 226e-7); //sample rate of sound effects
KaifK 26:04b2d7742a84 153 // set number of elements based on sound required
KaifK 25:467d8fd0fec4 154 if (sound == 1) { NUM_ELEMENTS = NUM_ELEMENTS_1; }
KaifK 25:467d8fd0fec4 155 else if (sound == 2) { NUM_ELEMENTS = NUM_ELEMENTS_3; }
KaifK 25:467d8fd0fec4 156 else if (sound == 3) { NUM_ELEMENTS = NUM_ELEMENTS_2; }
KaifK 25:467d8fd0fec4 157 else if (sound == 4) { NUM_ELEMENTS = NUM_ELEMENTS_4; }
KaifK 25:467d8fd0fec4 158 while (sound_sample <= NUM_ELEMENTS) {
KaifK 20:c697902b844f 159 if (sound_timer_flag == 1) {
KaifK 20:c697902b844f 160 sound_timer_flag = 0;
KaifK 26:04b2d7742a84 161 //play sound effect based on input value
KaifK 20:c697902b844f 162 // convert from 0 to 255 to 0.0 to 1.0
KaifK 25:467d8fd0fec4 163 if (sound == 1) { val = float(miss[sound_sample]) / 256.0f; }
KaifK 25:467d8fd0fec4 164 else if (sound == 2) { val = float(goall[sound_sample]) / 256.0f; }
KaifK 25:467d8fd0fec4 165 else if (sound == 3) { val = float(over[sound_sample]) / 256.0f; }
KaifK 25:467d8fd0fec4 166 else if (sound == 4) { val = float(life[sound_sample]) / 256.0f; }
KaifK 25:467d8fd0fec4 167 _pad -> write_dac(val); // write to DAC
KaifK 22:76bb0f52be8b 168 sound_sample++; // move onto next sample
KaifK 20:c697902b844f 169 }
KaifK 20:c697902b844f 170 }
KaifK 20:c697902b844f 171 }
KaifK 25:467d8fd0fec4 172 void Game::set_highscore(int score) {
KaifK 25:467d8fd0fec4 173 _highscore = score;
KaifK 21:d5b1160f349f 174 fp = fopen("/sd/highscore.txt", "w");
KaifK 25:467d8fd0fec4 175 if (fp == NULL) { // if it can't open the file then print error message
KaifK 21:d5b1160f349f 176 printf("Error! Unable to open file!\n");
KaifK 25:467d8fd0fec4 177 } else { // opened file so can write
KaifK 28:215e8327d4e6 178 printf("Writing to file highscore: %d \n", _highscore);
KaifK 25:467d8fd0fec4 179 fprintf(fp, "%d", _highscore); // ensure data type matches
KaifK 21:d5b1160f349f 180 printf("Done.\n");
KaifK 25:467d8fd0fec4 181 fclose(fp); // ensure you close the file after writing
KaifK 21:d5b1160f349f 182 }
KaifK 16:1f196a0e12be 183 }
KaifK 16:1f196a0e12be 184 int Game::get_highscore() {
KaifK 21:d5b1160f349f 185 fp = fopen("/sd/highscore.txt", "r");
KaifK 25:467d8fd0fec4 186 if (fp == NULL) { // if it can't open the file then print error message
KaifK 21:d5b1160f349f 187 printf("Error! Unable to open file!\n");
KaifK 25:467d8fd0fec4 188 } else { // opened file so can write
KaifK 25:467d8fd0fec4 189 fscanf(fp, "%d", & _highscore); // ensure data type matches - note address operator (&)
KaifK 21:d5b1160f349f 190 //printf("Read %d from file.\n",_highscore);
KaifK 25:467d8fd0fec4 191 fclose(fp); // ensure you close the file after reading
KaifK 21:d5b1160f349f 192 }
KaifK 16:1f196a0e12be 193 int val = _highscore;
KaifK 25:467d8fd0fec4 194 return val;
KaifK 16:1f196a0e12be 195 }
KaifK 9:e6566d09f087 196 void Game::pointer_input() {
KaifK 9:e6566d09f087 197 updateScore();
KaifK 25:467d8fd0fec4 198 _ball -> displayBackground();
KaifK 25:467d8fd0fec4 199 _ball -> drawBall(BALL_INIT_X, BALL_INIT_Y, 6);
KaifK 7:2a3b566aedd3 200 //draw aim pointer
KaifK 25:467d8fd0fec4 201 _lcd -> drawLine(WIDTH / 2 - 5, 41, _x_val, HEIGHT / 2 + 7, 1); //left side
KaifK 25:467d8fd0fec4 202 _lcd -> drawLine(WIDTH / 2 + 5, 41, _x_val, HEIGHT / 2 + 7, 1); //right side
KaifK 25:467d8fd0fec4 203 _lcd -> drawLine(WIDTH / 2 + 5, 41, WIDTH / 2 - 5, 41, 1); //base
KaifK 7:2a3b566aedd3 204 _x_val += _speed;
KaifK 9:e6566d09f087 205 //printf("dir = %d \n", _speed);
KaifK 25:467d8fd0fec4 206 if ((int) _x_val >= 70) {
KaifK 25:467d8fd0fec4 207 _speed = (-1 * _speed);
KaifK 25:467d8fd0fec4 208 }
KaifK 9:e6566d09f087 209 //pointer points out of screen i.e. 70=84 therefore, switch direction
KaifK 7:2a3b566aedd3 210 //value found through trial and error using print statement
KaifK 25:467d8fd0fec4 211 else if ((int) _x_val <= 12) {
KaifK 25:467d8fd0fec4 212 _speed = abs(_speed);
KaifK 25:467d8fd0fec4 213 }
KaifK 25:467d8fd0fec4 214 _lcd -> refresh();
KaifK 25:467d8fd0fec4 215 _lcd -> clear();
KaifK 7:2a3b566aedd3 216 wait(0.01);
KaifK 7:2a3b566aedd3 217 }
KaifK 9:e6566d09f087 218 void Game::power_meter_input() {
KaifK 9:e6566d09f087 219 updateScore();
KaifK 25:467d8fd0fec4 220 _ball -> displayBackground();
KaifK 25:467d8fd0fec4 221 _ball -> drawBall(BALL_INIT_X, BALL_INIT_Y, 6);
KaifK 7:2a3b566aedd3 222 //keep direction of pointer
KaifK 25:467d8fd0fec4 223 _lcd -> drawLine(WIDTH / 2 - 5, 41, _x_val, HEIGHT / 2 + 7, 1);
KaifK 25:467d8fd0fec4 224 _lcd -> drawLine(WIDTH / 2 + 5, 41, _x_val, HEIGHT / 2 + 7, 1);
KaifK 25:467d8fd0fec4 225 _lcd -> drawLine(WIDTH / 2 + 5, 41, WIDTH / 2 - 5, 41, 1);
KaifK 7:2a3b566aedd3 226 //fill and empty power meter
KaifK 25:467d8fd0fec4 227 _lcd -> drawRect(77, 27, 6, _y_val, FILL_BLACK);
KaifK 25:467d8fd0fec4 228 _y_val += _speed / 2;
KaifK 28:215e8327d4e6 229 if ((int) _y_val >= 20) { //power meter full
KaifK 25:467d8fd0fec4 230 _speed = (-1 * _speed);
KaifK 28:215e8327d4e6 231 }
KaifK 28:215e8327d4e6 232 else if ((int) _y_val <= 0) { // power meter empty
KaifK 25:467d8fd0fec4 233 _speed = abs(_speed);
KaifK 28:215e8327d4e6 234 }
KaifK 25:467d8fd0fec4 235 _lcd -> refresh();
KaifK 25:467d8fd0fec4 236 _lcd -> clear();
KaifK 7:2a3b566aedd3 237 wait(0.01);
KaifK 7:2a3b566aedd3 238 }
KaifK 7:2a3b566aedd3 239 void Game::convert_to_shot_x() {
KaifK 9:e6566d09f087 240 //convert from range 12-70 (range of pointer) to 0-84 (range of screen)
KaifK 25:467d8fd0fec4 241 _shot_x = ((((int) _x_val - 12) * (84)) / (70 - 12));
KaifK 8:5ede90f99a27 242 //ball misses goal completely
KaifK 25:467d8fd0fec4 243 if (_shot_x <= 7) {
KaifK 25:467d8fd0fec4 244 _shot_x = 0;
KaifK 25:467d8fd0fec4 245 } else if (_shot_x >= 77) {
KaifK 25:467d8fd0fec4 246 _shot_x = 84;
KaifK 25:467d8fd0fec4 247 }
KaifK 7:2a3b566aedd3 248 }
KaifK 7:2a3b566aedd3 249 void Game::convert_to_shot_y() {
KaifK 25:467d8fd0fec4 250 _shot_y = ((((int) _y_val) * (24)) / (20));
KaifK 28:215e8327d4e6 251 if( _shot_y >= 21) {
KaifK 28:215e8327d4e6 252 _shot_y = 28; // Very little power, so ball does not reach goal
KaifK 28:215e8327d4e6 253 }
KaifK 9:e6566d09f087 254 }
KaifK 9:e6566d09f087 255 int Game::random_level_gen(int limit) {
KaifK 25:467d8fd0fec4 256 int number = (rand() % limit) + 1; //random level between 1-limit
KaifK 15:5bf3f951d337 257 return number;
KaifK 15:5bf3f951d337 258 }
KaifK 15:5bf3f951d337 259 void Game::print_goal_message(int n) {
KaifK 25:467d8fd0fec4 260 _ball -> displayBackground();
KaifK 25:467d8fd0fec4 261 _lcd -> drawRect(0, 14, 84, 11, FILL_WHITE); //white background
KaifK 25:467d8fd0fec4 262 _lcd -> drawRect(0, 14, 84, 11, FILL_TRANSPARENT); //black outline
KaifK 25:467d8fd0fec4 263
KaifK 25:467d8fd0fec4 264 switch (n) {
KaifK 25:467d8fd0fec4 265 case 0:
KaifK 25:467d8fd0fec4 266 _lcd -> printString("MISS!", 30, 2);
KaifK 25:467d8fd0fec4 267 break;
KaifK 25:467d8fd0fec4 268 case 1:
KaifK 25:467d8fd0fec4 269 _lcd -> printString("GOAL!", 30, 2);
KaifK 25:467d8fd0fec4 270 break;
KaifK 25:467d8fd0fec4 271 }
KaifK 25:467d8fd0fec4 272 _lcd -> refresh();
KaifK 22:76bb0f52be8b 273 wait(0.5);
KaifK 26:04b2d7742a84 274 // adding 1 offsets the range of inputs from 0-1 to 1-2 (needed for function)
KaifK 25:467d8fd0fec4 275 playGoalSound((int) _is_goal + 1);
KaifK 25:467d8fd0fec4 276 wait(1);
KaifK 7:2a3b566aedd3 277 }
KaifK 20:c697902b844f 278 void timer_isr() {
KaifK 20:c697902b844f 279 sound_timer_flag = 1; // set flag in the isr
KaifK 25:467d8fd0fec4 280 }