James Heavey
/
EL17JH
FINAL VERSION
Embed:
(wiki syntax)
Show/hide line numbers
BreakoutEngine.cpp
00001 #include "BreakoutEngine.h" 00002 00003 BreakoutEngine::BreakoutEngine() 00004 { 00005 00006 } 00007 00008 BreakoutEngine::~BreakoutEngine() 00009 { 00010 00011 } 00012 00013 void BreakoutEngine::init(int paddle_width,int paddle_height,int ball_size,int speed) 00014 { 00015 // initialise the game parameters 00016 _paddle_width = paddle_width; 00017 _paddle_height = paddle_height; 00018 _ball_size = ball_size; // size of the ball 00019 _speed = speed; // speed of the ball 00020 _number_left = 18; // number of bricks that remain on screen 00021 _index = 0; // index of which laser to move on screen at any time, starts at 0 00022 _cool_time = 0.0f; // time remaining before laser can be fired again, starts at 0 00023 _score = 0; // initialised as 0 00024 _prev_score = 0; // initialised as 0 for the first round 00025 _multiplier = 0; // initialised as 1 for the first round 00026 00027 // y position of the paddle on screen - HEIGHT is defined in N5110.h 00028 _paddley = HEIGHT - GAP - 1; 00029 00030 // initialises paddles and ball in middle 00031 _paddle.init(_paddley,_paddle_height,_paddle_width); 00032 _ball.init(_ball_size,_speed,_paddle.get_pos().x + (PADDLE_WIDTH/2)); 00033 00034 // initialises all the bricks in their set x/y positions 00035 _brick11.init(3,GAP_TOP+1,3); 00036 _brick12.init(16,GAP_TOP+1,3); 00037 _brick13.init(29,GAP_TOP+1,3); 00038 _brick14.init(42,GAP_TOP+1,3); 00039 _brick15.init(55,GAP_TOP+1,3); 00040 _brick16.init(68,GAP_TOP+1,3); 00041 00042 _brick21.init(3,GAP_TOP+BRICK_HEIGHT+2,2); 00043 _brick22.init(16,GAP_TOP+BRICK_HEIGHT+2,2); 00044 _brick23.init(29,GAP_TOP+BRICK_HEIGHT+2,2); 00045 _brick24.init(42,GAP_TOP+BRICK_HEIGHT+2,2); 00046 _brick25.init(55,GAP_TOP+BRICK_HEIGHT+2,2); 00047 _brick26.init(68,GAP_TOP+BRICK_HEIGHT+2,2); 00048 00049 _brick31.init(3,GAP_TOP+1+((BRICK_HEIGHT+1)*2),1); 00050 _brick32.init(16,GAP_TOP+1+((BRICK_HEIGHT+1)*2),1); 00051 _brick33.init(29,GAP_TOP+1+((BRICK_HEIGHT+1)*2),1); 00052 _brick34.init(42,GAP_TOP+1+((BRICK_HEIGHT+1)*2),1); 00053 _brick35.init(55,GAP_TOP+1+((BRICK_HEIGHT+1)*2),1); 00054 _brick36.init(68,GAP_TOP+1+((BRICK_HEIGHT+1)*2),1); 00055 00056 // appends all bricks to a list so that they are easier to check for collisions 00057 listofBricks.push_back(_brick11); 00058 listofBricks.push_back(_brick12); 00059 listofBricks.push_back(_brick13); 00060 listofBricks.push_back(_brick14); 00061 listofBricks.push_back(_brick15); 00062 listofBricks.push_back(_brick16); 00063 listofBricks.push_back(_brick21); 00064 listofBricks.push_back(_brick22); 00065 listofBricks.push_back(_brick23); 00066 listofBricks.push_back(_brick24); 00067 listofBricks.push_back(_brick25); 00068 listofBricks.push_back(_brick26); 00069 listofBricks.push_back(_brick31); 00070 listofBricks.push_back(_brick32); 00071 listofBricks.push_back(_brick33); 00072 listofBricks.push_back(_brick34); 00073 listofBricks.push_back(_brick35); 00074 listofBricks.push_back(_brick36); 00075 00076 // initialises lasers off screen 00077 _laser1.init(); 00078 _laser2.init(); 00079 _laser3.init(); 00080 00081 // appends lasers to a list so that they are easier to check for collisions 00082 listofLasers.push_back(_laser1); 00083 listofLasers.push_back(_laser2); 00084 listofLasers.push_back(_laser3); 00085 00086 _powerup.init(); 00087 } 00088 00089 00090 void BreakoutEngine::reset_game() // resets the game after victory screen 00091 { 00092 reset_num_left(); // resets _number_left to 18 00093 _paddle.recentre(); // recentres the paddle on screen 00094 //printf("Paddle lives = %d", _paddle.get_lives()); 00095 _ball.init(_ball_size,_speed + _multiplier/2, _paddle.get_pos().x + (PADDLE_WIDTH/2)); // resets the ball position to above the paddle, and increases its speed depending on the _multiplier 00096 _powerup.set_posx(-50); 00097 00098 int pointer = 0; // tracks the rows, if 6 bricks are placed, it moves to the next row 00099 for (it_R = listofBricks.begin(); it_R != listofBricks.end(); ++it_R) { 00100 if (pointer <= 5) { // 6 bricks in the first row 00101 it_R -> set_posx((pointer * 13) + 3); 00102 } else if (pointer <= 11) { 00103 it_R -> set_posx(((pointer-6) * 13) + 3); // pointer - 6 to offset it back to the first column of bricks 00104 } else if (pointer <= 17) { 00105 it_R -> set_posx(((pointer-12) * 13) + 3); // pointer - 12 to offset it back to the first column of bricks 00106 } 00107 00108 it_R -> reset_lives(_multiplier); // increases the bricks number of lives by the multiplier + their _base_lives 00109 pointer ++; // increment the pointer 00110 //printf("pointer = %d",pointer); 00111 } 00112 for (it_L = listofLasers.begin(); it_L != listofLasers.end(); ++it_L) { 00113 it_L -> set_posx(-10); // moves all the lasers off screen 00114 } 00115 } 00116 00117 00118 void BreakoutEngine::read_input(Gamepad &pad) 00119 { 00120 _d = pad.get_direction(); 00121 _mag = pad.get_mag(); 00122 00123 if (pad.check_event(Gamepad::B_PRESSED) && _cool_time <= 0) { // if B is pressed and it is not cooling down then fire a laser 00124 00125 Vector2D p_pos = _paddle.get_pos(); 00126 it_L = listofLasers.begin(); 00127 switch(_index) { // switch between the lasers each time the button is pressed so that it doesnt just re position the same laser each time 00128 case 0: 00129 advance(it_L, 0); 00130 it_L -> set_posx(p_pos.x+7); // move laser 1 to middle of paddle 00131 it_L -> set_posy(p_pos.y); 00132 inc_index(); 00133 //printf("index = %d",_index); 00134 break; 00135 case 1: 00136 advance(it_L, 1); 00137 it_L -> set_posx(p_pos.x+7); // move laser 2 to middle of paddle 00138 it_L -> set_posy(p_pos.y); 00139 inc_index(); 00140 //printf("index = %d",_index); 00141 break; 00142 case 2: 00143 advance(it_L, 2); 00144 it_L -> set_posx(p_pos.x+7); // move laser 3 to middle of paddle 00145 it_L -> set_posy(p_pos.y); 00146 //printf("index = %d",_index); 00147 reset_index(); 00148 //printf("index = %d",_index); 00149 break; 00150 } 00151 00152 it_L = listofLasers.end(); 00153 00154 _cool_time = 0.75f; // reset cool time to 0.75 seconds 00155 } else { 00156 _cool_time -= 0.125; // reduce cool down time by 1/8 of a second as fps is 8 00157 } 00158 00159 } 00160 00161 00162 void BreakoutEngine::draw(N5110 &lcd) 00163 { 00164 lcd.drawRect(0,GAP_TOP - 2,WIDTH,HEIGHT - GAP_TOP + 2,FILL_TRANSPARENT); // draw the game screen dimensions 00165 print_scores(lcd); // print the score above the screen 00166 _paddle.draw(lcd); // draw the paddle 00167 _ball.draw(lcd); // draw the ball 00168 00169 for (it_R = listofBricks.begin(); it_R != listofBricks.end(); ++it_R) { // draw all teh bricks 00170 it_R->draw(lcd); 00171 } 00172 for (it_L = listofLasers.begin(); it_L != listofLasers.end(); ++it_L) { // draw all the lasers 00173 it_L->draw(lcd); 00174 } 00175 00176 check_life_powerup(); // check if power up can be drawn, if so move on screen when random condition is met 00177 00178 _powerup.draw(lcd); // draw the powerup 00179 } 00180 00181 00182 void BreakoutEngine::update(Gamepad &pad) 00183 { 00184 check_loss(pad); // check if the ball has gone above max y 00185 00186 _paddle.update(_d,_mag); // update paddle position 00187 _ball.update(); // update ball position 00188 _powerup.update(); // update powerup position 00189 00190 for (it_L = listofLasers.begin(); it_L != listofLasers.end(); ++it_L) { // update all the lasers' positions 00191 it_L->update(); 00192 } 00193 00194 lives_leds(pad); // update the LEDs with the remaining lives 00195 00196 check_wall_collisions(pad); // check ball and laser collisions with walls and ceiling 00197 check_paddle_collisions(pad); // check ball collision with paddle 00198 check_brick_collisions(pad); // check ball collision with bricks 00199 check_laser_collisions(pad); // check all laser collisions with all bricks 00200 check_powerup_collisions(pad); // check powerup collision with paddle 00201 } 00202 00203 00204 void BreakoutEngine::lives_leds(Gamepad &pad) // converst the number of lives left into LEDs 00205 { 00206 if (_paddle.get_lives() == 0) { 00207 pad.leds_off(); // all LEDs off 00208 } 00209 00210 else if (_paddle.get_lives() == 1) { 00211 pad.leds_off(); 00212 pad.led(1,1); // 1 LED on 00213 } 00214 00215 else if (_paddle.get_lives() == 2) { 00216 pad.leds_off(); 00217 pad.led(1,1); 00218 pad.led(2,1); // 2 LEDs on 00219 } 00220 00221 else if (_paddle.get_lives() == 3) { 00222 pad.leds_off(); 00223 pad.led(1,1); 00224 pad.led(2,1); 00225 pad.led(3,1); // 3 LEDs on 00226 } 00227 00228 else if (_paddle.get_lives() == 4) { 00229 pad.leds_on(); 00230 pad.led(5,0); 00231 pad.led(6,0); // 4 LEDs on 00232 } 00233 00234 else if (_paddle.get_lives() == 5) { 00235 pad.leds_on(); 00236 pad.led(6,0); // 5 LEDs on 00237 } 00238 00239 else if (_paddle.get_lives() == 6) { 00240 pad.leds_on(); // all LEDs on 00241 //printf("all LEDs on \n"); 00242 } 00243 } 00244 00245 00246 void BreakoutEngine::check_wall_collisions(Gamepad &pad) // checks ball and laser collisions with the walls and ceiling 00247 { 00248 // read current ball attributes 00249 Vector2D ball_pos = _ball.get_pos(); 00250 Vector2D ball_velocity = _ball.get_velocity(); 00251 00252 // bounce off the ceiling 00253 if (ball_pos.y <= GAP_TOP - 1) { // 1 due to 1 pixel boundary 00254 ball_pos.y = GAP_TOP - 1; 00255 ball_velocity.y = -ball_velocity.y; 00256 pad.tone(750.0,0.1); 00257 } 00258 00259 // bounce off the left 00260 else if (ball_pos.x <= 1) { // 1 due to 1 pixel boundary 00261 ball_pos.x = 1; // bounce off walls 00262 ball_velocity.x = -ball_velocity.x; 00263 pad.tone(750.0,0.1); 00264 } 00265 00266 // bounce off the right 00267 else if (ball_pos.x + _ball_size >= (WIDTH-1) ) { // bottom pixel is 47 00268 // hit bottom 00269 ball_pos.x = (WIDTH-1) - _ball_size; // stops ball going off screen 00270 ball_velocity.x = -ball_velocity.x; 00271 // audio feedback 00272 pad.tone(750.0,0.1); 00273 } 00274 00275 // update ball parameters 00276 _ball.set_velocity(ball_velocity); 00277 _ball.set_pos(ball_pos); 00278 00279 for (it_L = listofLasers.begin(); it_L != listofLasers.end(); ++it_L) { // checks every laser 00280 if ( 00281 (it_L -> get_y() <= GAP_TOP - 2) // if it hits the ceiling 00282 ) { 00283 it_L -> set_posx(-10); // set its x coordinate off screen 00284 } 00285 } 00286 00287 } 00288 00289 00290 void BreakoutEngine::check_paddle_collisions(Gamepad &pad) 00291 { 00292 // read current ball attributes 00293 Vector2D ball_pos = _ball.get_pos(); 00294 Vector2D ball_velocity = _ball.get_velocity(); 00295 00296 // read the paddle position 00297 Vector2D paddle_pos = _paddle.get_pos(); 00298 00299 // check if ball overlaps with the paddle 00300 if ( 00301 (ball_pos.x >= paddle_pos.x) && //left 00302 (ball_pos.x <= paddle_pos.x + _paddle_width) && //right 00303 (ball_pos.y >= _paddley) && //bottom 00304 (ball_pos.y <= _paddley + _paddle_height) //top 00305 ) { 00306 pad.tone(1000.0,0.1); 00307 ball_pos.y = _paddley + _paddle_height - 1; 00308 ball_velocity.y = -ball_velocity.y; 00309 00310 // below is a method to control the ball reflect angle based on where it hits the paddle 00311 // however cannot be used as it does not work with collisions due to varying angles and speeds 00312 // would work with greater pixel density in the screen 00313 00314 // if (ball_pos.x == paddle_pos.x + PADDLE_WIDTH/2) { // check ballxpos in relation to paddle xpos. translate the distance from the centre to an angle between 30 and 60 degrees in that direction 00315 // ball_pos.y = _paddley + _paddle_height - 1; 00316 // ball_velocity.y = -ball_velocity.y; 00317 // } 00318 // else if (ball_pos.x <= paddle_pos.x + PADDLE_WIDTH/2) { 00319 // float ang = 40*(((paddle_pos.x + PADDLE_WIDTH/2)-ball_pos.x)/(PADDLE_WIDTH/2 - paddle_pos.x)) + 30; //converts the distance from the centre to an angle between 30 and 60 00320 // if (ball_velocity.x > 0) { 00321 // ball_velocity.x = -ball_velocity.x; 00322 // } 00323 // ball_pos.y = _paddley + _paddle_heigh - 1; 00324 // ball_velocity.y = -tan(ang); 00325 // } 00326 // else if (ball_pos.x >= paddle_pos.x + PADDLE_WIDTH/2) { 00327 // float ang = 40*(((paddle_pos.x + PADDLE_WIDTH/2)-ball_pos.x)/(PADDLE_WIDTH/2 - paddle_pos.x)) + 30; //converts the distance from the centre to an angle between 30 and 60 00328 // if (ball_velocity.x < 0) { 00329 // ball_velocity.x = -ball_velocity.x; 00330 // } 00331 // ball_pos.y = _paddley + _paddle_height - 1; 00332 // ball_velocity.y = -tan(ang); 00333 // } 00334 } 00335 00336 // write new attributes 00337 _ball.set_velocity(ball_velocity); 00338 _ball.set_pos(ball_pos); 00339 } 00340 00341 void BreakoutEngine::check_brick_collisions(Gamepad &pad) 00342 { 00343 // read current ball attributes 00344 Vector2D ball_pos = _ball.get_pos(); 00345 Vector2D ball_velocity = _ball.get_velocity(); 00346 00347 for (it_R = listofBricks.begin(); it_R != listofBricks.end(); ++it_R) { 00348 if ( 00349 (ball_pos.x >= it_R -> get_x()) && //left 00350 (ball_pos.x <= it_R -> get_x() + BRICK_WIDTH) && //right 00351 (ball_pos.y >= it_R -> get_y()) && //bottom 00352 (ball_pos.y <= it_R -> get_y() + BRICK_HEIGHT) //top 00353 ) { 00354 if (ball_velocity.y < 0) { // if velocity is negative, it has hit the bottom, therefore correct its pos to the bottom face 00355 ball_pos.y = it_R -> get_y() + BRICK_HEIGHT; 00356 } else { // else it has hit the top, correct its position to the top face 00357 ball_pos.y = it_R -> get_y(); 00358 } 00359 ball_velocity.y = -ball_velocity.y; // invert the balls y velocity 00360 // audio feedback 00361 pad.tone(1000.0,0.1); 00362 it_R -> hit(); 00363 if(it_R-> hit() == true) { // hit the brick, remove 2 lives from it and check if destroyed 00364 it_R -> set_posx(-100); // if destroyed, move off screen 00365 dec_num_left(); // decrement the number of bricks left on screen 00366 } 00367 } 00368 } 00369 // write new attributes 00370 _ball.set_velocity(ball_velocity); 00371 _ball.set_pos(ball_pos); 00372 } 00373 00374 00375 void BreakoutEngine::check_laser_collisions(Gamepad &pad) 00376 { 00377 for (it_L = listofLasers.begin(); it_L != listofLasers.end(); ++it_L) { 00378 for (it_R = listofBricks.begin(); it_R != listofBricks.end(); ++it_R) { // check every laser against every brick 00379 if ( 00380 (it_L -> get_x() >= it_R -> get_x()) && //left 00381 (it_L -> get_x() <= it_R -> get_x() + BRICK_WIDTH) && //right 00382 (it_L -> get_y() >= it_R -> get_y()) && //bottom 00383 (it_L -> get_y() <= it_R -> get_y() + BRICK_HEIGHT) //top 00384 ) { 00385 it_L -> set_posx(-10); // if they overlap/collide, move the laser off screen 00386 // audio feedback 00387 pad.tone(1000.0,0.1); 00388 if(it_R-> hit() == true) { // remove a life from the brick, if its destroyed, move it off screen 00389 it_R -> set_posx(-100); 00390 dec_num_left(); // decrement the number of bricks remaining on screen 00391 } 00392 } 00393 } 00394 } 00395 } 00396 00397 00398 void BreakoutEngine::check_powerup_collisions(Gamepad &pad) // checks powerup collisions with the paddle and the bottom of the screen 00399 { 00400 // read the current position of the paddle 00401 Vector2D paddle_pos = _paddle.get_pos(); 00402 00403 if ( 00404 (_powerup.get_x() >= paddle_pos.x) && //left 00405 (_powerup.get_x() + 8 <= paddle_pos.x + _paddle_width) && //right 00406 (_powerup.get_y() + 8 >= paddle_pos.y) // top 00407 ) { 00408 pad.tone(2500.0,0.1); 00409 _powerup.set_posx(-50); // if the paddle and power up overlap, move the powerup off screen 00410 _paddle.inc_life(); // increment the numebr of lives left on the paddle 00411 } 00412 00413 else if ( 00414 (_powerup.get_y() +9 >= HEIGHT) // bottom of screen 00415 ) { 00416 _powerup.set_posx(-50); // if the powerup reaches the bottom of the screen, move it off screen 00417 } 00418 } 00419 00420 00421 bool BreakoutEngine::check_loss(Gamepad &pad) // check if the ball has hit the bottom of the screen 00422 { 00423 // read the current ball position 00424 Vector2D ball_pos = _ball.get_pos(); 00425 00426 if (ball_pos.y > HEIGHT) { // if it has gone off screen 00427 _paddle.lose_life(); // decrement the number of lives left 00428 00429 _ball.init(_ball_size,_speed+_multiplier/2,_paddle.get_pos().x + (PADDLE_WIDTH/2)); // re initialise the ball above the paddle 00430 pad.tone(1500.0,0.5); 00431 return true; // return true, to be used to flash the screen in the main 00432 } else { 00433 return false; 00434 } 00435 } 00436 00437 00438 void BreakoutEngine::set_paddle_motion(bool tilt, float sens) // sets the motion options for the paddle 00439 { 00440 if (tilt == true) { 00441 _paddle.set_tilt(); // sets tilt 00442 } else { 00443 _paddle.set_joy(); // sets joystick 00444 } 00445 _paddle.set_sens(sens); // sets sensitivity 00446 } 00447 00448 00449 void BreakoutEngine::print_scores(N5110 &lcd) 00450 { 00451 int score = _prev_score + (18 - get_num_left())*100 * (_multiplier + 1); // current score depends on number left, the multiplier and the previous score 00452 _score = score; // set the member variable _score 00453 00454 char buffer[14]; 00455 sprintf(buffer,"%2d",score); // put score in buffer 00456 lcd.printString("SCORE: ",2,0); 00457 lcd.printString(buffer,WIDTH/2 -2,0); // print buffer on LCD 00458 } 00459 00460 00461 void BreakoutEngine::check_life_powerup() 00462 { 00463 srand(time(0)); // Initialize random number generator. 00464 int r1 = (rand() % 25) + 1; 00465 int r2 = (rand() % 25) + 1; // 2 random number between 1 and 26 00466 int rx = (rand() % 60) + 11; // generate a random x coordinate for the powerup to be place 00467 //printf("r1 = %d",r1); 00468 //printf("r2 = %d",r2); 00469 //printf("rx = %d",rx); 00470 if ((get_paddle_lives() < 6) & (r1 == r2)) { // if lives are not max, and the random condition is met 00471 _powerup.set_posx(rx); // set the powerup x 00472 _powerup.set_posy(HEIGHT/2); // set the y at the middle of the screen 00473 } 00474 } 00475 00476 00477 int BreakoutEngine::get_prev_score() 00478 { 00479 return _prev_score; // return the previous score 00480 } 00481 00482 00483 void BreakoutEngine::set_prev_score(int prev_score) 00484 { 00485 _prev_score = prev_score; // set the member variable _prev_score 00486 } 00487 00488 00489 int BreakoutEngine::get_num_left() 00490 { 00491 return _number_left; // return the number of bricks left on screen 00492 } 00493 00494 00495 void BreakoutEngine::dec_num_left() 00496 { 00497 _number_left -= 1; // decrement the member variable _number_left when a brick is destroyed 00498 } 00499 00500 00501 void BreakoutEngine::reset_num_left() 00502 { 00503 _number_left = 18; // reset the number left to 18 when the game is reset 00504 } 00505 00506 00507 int BreakoutEngine::get_score() 00508 { 00509 return _score; // return the member variable _score 00510 } 00511 00512 00513 void BreakoutEngine::inc_mult() 00514 { 00515 _multiplier ++; // increment the _multiplier when continue is selected upon victory 00516 } 00517 00518 00519 int BreakoutEngine::get_mult() 00520 { 00521 return _multiplier; // retrieve the multiplier value 00522 } 00523 00524 00525 void BreakoutEngine::reset_mult() 00526 { 00527 _multiplier = 0; // reset the multiplier to 0 00528 } 00529 00530 00531 void BreakoutEngine::inc_index() 00532 { 00533 _index ++; // increment the laser index 00534 } 00535 00536 00537 void BreakoutEngine::reset_index() 00538 { 00539 _index = 0; // reset the laser index 00540 } 00541 00542 00543 void BreakoutEngine::reset_paddle_lives() 00544 { 00545 _paddle.reset_lives(); // resets paddle lives 00546 } 00547 00548 00549 int BreakoutEngine::get_paddle_lives() 00550 { 00551 return _paddle.get_lives(); // return the number of lives left 00552 }
Generated on Thu Jul 14 2022 01:22:29 by 1.7.2