Kaif Kutchwala 201267448 ELEC2645 Project

Dependencies:   mbed

Committer:
KaifK
Date:
Tue May 26 15:50:46 2020 +0000
Revision:
31:e1f80d181779
Parent:
29:532e5c371be4
Final Submission. I have read and agreed with Statement of Academic Integrity.

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