Retro game that let's the player steer a ball through a hole filled maze. Has multiple levels of increasing difficulty.

Dependencies:   LCD_ST7735 MusicEngine RETRO_BallsAndThings mbed

Ball and Holes

In this game I attempted to create somewhat natural movement of the ball by implementing gravity and friction which combined over time determine the speed of the ball. Playing with the settings (aka. the magic numbers) that are spread out all over game.cpp, gives different effects, such as an icy, rough or liquid-like surface.

It took some time to figure out how to post my very first youtube video. Sorry for the shaky recording. Trying to record the video with my phone while playing the game in one hand was quite challenging, but here it is;

The left and right buttons are used to cheat: restart the current or go to the next level. Up and down control the game-tick. During game-play the robot-button shows the accelerator graph and the ship-button mutes the sound.

BTW. If your ball happens to get stuck, tilting the console in the opposite direction will set it free. For sake of argument: these magnetic wall-ends are in the words of Bob Ross "a happy accident". Since there is no specific code for it, others might call it a bug. As it results in more interesting game-play, I didn't attempt to fix it, but left a comment for those who dare to look at the mess I call code.

Committer:
maxint
Date:
Tue Feb 03 19:02:27 2015 +0000
Revision:
2:d4de5a5866fe
Parent:
1:c1ee4c699517
Child:
3:ca8b21da67dc
Added more balls

Who changed what in which revision?

UserRevisionLine numberNew contents of line
maxint 0:87ab172a74b4 1 #include "Game.h"
maxint 0:87ab172a74b4 2
maxint 0:87ab172a74b4 3 const char* Game::LOSE_1 = "You lose.";
maxint 0:87ab172a74b4 4 const char* Game::LOSE_2 = "Press ship to restart.";
maxint 2:d4de5a5866fe 5 const char* Game::SPLASH_1 = "-*- Balls and paddle -*-";
maxint 2:d4de5a5866fe 6 const char* Game::SPLASH_2 = "Press ship to start.";
maxint 2:d4de5a5866fe 7 const char* Game::SPLASH_3 = "Made by Maxint";
maxint 0:87ab172a74b4 8
maxint 0:87ab172a74b4 9
maxint 0:87ab172a74b4 10 #define WHITE Color565::White
maxint 0:87ab172a74b4 11 #define BLACK Color565::Black
maxint 0:87ab172a74b4 12 #define BLUE Color565::Blue
maxint 0:87ab172a74b4 13 #define RED Color565::Red
maxint 0:87ab172a74b4 14 #define YELLOW Color565::Yellow
maxint 0:87ab172a74b4 15
maxint 0:87ab172a74b4 16 #define CHAR_WIDTH 8
maxint 0:87ab172a74b4 17 #define CHAR_HEIGHT 8
maxint 0:87ab172a74b4 18 #define HEIGHT this->disp.getHeight()
maxint 0:87ab172a74b4 19 #define WIDTH this->disp.getWidth()
maxint 0:87ab172a74b4 20
maxint 0:87ab172a74b4 21
maxint 0:87ab172a74b4 22
maxint 0:87ab172a74b4 23 Game::Game() : left(P0_14, PullUp), right(P0_11, PullUp), down(P0_12, PullUp), up(P0_13, PullUp), square(P0_16, PullUp), circle(P0_1, PullUp), led1(P0_9), led2(P0_8),
maxint 2:d4de5a5866fe 24 ain(P0_15), i2c(P0_5, P0_4), disp(P0_19, P0_20, P0_7, P0_21, P0_22, P1_15, P0_2, LCD_ST7735::RGB), accel(this->I2C_ADDR, &disp), vGravity(0, 0.1), ball(&disp), paddle(&disp)
maxint 0:87ab172a74b4 25 {
maxint 1:c1ee4c699517 26 this->disp.setOrientation(LCD_ST7735::Rotate270, false);
maxint 1:c1ee4c699517 27 this->disp.setForegroundColor(WHITE);
maxint 1:c1ee4c699517 28 this->disp.setBackgroundColor(BLACK);
maxint 1:c1ee4c699517 29 this->disp.clearScreen();
maxint 1:c1ee4c699517 30
maxint 0:87ab172a74b4 31 srand(this->ain.read_u16());
maxint 0:87ab172a74b4 32
maxint 0:87ab172a74b4 33 this->lastUp = false;
maxint 0:87ab172a74b4 34 this->lastDown = false;
maxint 0:87ab172a74b4 35 this->mode = true;
maxint 0:87ab172a74b4 36
maxint 2:d4de5a5866fe 37
maxint 2:d4de5a5866fe 38 //this->aBalls[2]={ Ball(&disp), Ball(&disp) };
maxint 2:d4de5a5866fe 39 for(int i=0; i<NUM_BALLS; i++)
maxint 2:d4de5a5866fe 40 this->aBalls[i]=Ball(&(this->disp));
maxint 2:d4de5a5866fe 41
maxint 2:d4de5a5866fe 42 //this->initialize();
maxint 0:87ab172a74b4 43 }
maxint 0:87ab172a74b4 44
maxint 2:d4de5a5866fe 45 void Game::printDouble(double value, int x, int y)
maxint 2:d4de5a5866fe 46 {
maxint 0:87ab172a74b4 47 char buffer[10];
maxint 0:87ab172a74b4 48 int len = sprintf(buffer, "%.1f ", value);
maxint 0:87ab172a74b4 49
maxint 1:c1ee4c699517 50 this->disp.drawString(font_oem, x, y, buffer);
maxint 0:87ab172a74b4 51 }
maxint 0:87ab172a74b4 52
maxint 1:c1ee4c699517 53 void Game::initialize()
maxint 1:c1ee4c699517 54 {
maxint 0:87ab172a74b4 55 this->disp.clearScreen();
maxint 0:87ab172a74b4 56
maxint 2:d4de5a5866fe 57 // this->initializeBall(); // start first ball
maxint 2:d4de5a5866fe 58 // this->initializeBalls(); // start first ball
maxint 2:d4de5a5866fe 59
maxint 2:d4de5a5866fe 60 this->setNoBalls(); // reset all balls
maxint 2:d4de5a5866fe 61 this->newBall(); // start first ball
maxint 0:87ab172a74b4 62 this->initializePaddle();
maxint 2:d4de5a5866fe 63 //this->paddle.draw();
maxint 2:d4de5a5866fe 64
maxint 0:87ab172a74b4 65
maxint 1:c1ee4c699517 66 // this->paddleX = WIDTH / 2 - Game::PADDLE_WIDTH / 2;
maxint 2:d4de5a5866fe 67 this->snd.reset();
maxint 1:c1ee4c699517 68 this->nLives = 4;
maxint 1:c1ee4c699517 69 this->nScore = 0;
maxint 0:87ab172a74b4 70
maxint 0:87ab172a74b4 71 this->tWait.start(); // start the timer
maxint 0:87ab172a74b4 72
maxint 0:87ab172a74b4 73 }
maxint 2:d4de5a5866fe 74
maxint 2:d4de5a5866fe 75
maxint 2:d4de5a5866fe 76 void Game::initializePaddle()
maxint 2:d4de5a5866fe 77 {
maxint 2:d4de5a5866fe 78 this->paddle.initialize(WIDTH / 2 - Game::PADDLE_WIDTH/2, HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT);
maxint 2:d4de5a5866fe 79 this->paddle.draw();
maxint 2:d4de5a5866fe 80 }
maxint 2:d4de5a5866fe 81
maxint 2:d4de5a5866fe 82
maxint 2:d4de5a5866fe 83 void Game::updatePaddle()
maxint 2:d4de5a5866fe 84 {
maxint 2:d4de5a5866fe 85 if (!this->left.read()) // note: read is LOW (0) when button pressed
maxint 2:d4de5a5866fe 86 this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
maxint 2:d4de5a5866fe 87 else if (!this->right.read())
maxint 2:d4de5a5866fe 88 this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
maxint 2:d4de5a5866fe 89 else
maxint 2:d4de5a5866fe 90 {
maxint 2:d4de5a5866fe 91 int i=this->checkTilt();
maxint 2:d4de5a5866fe 92 if(i>0)
maxint 2:d4de5a5866fe 93 this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
maxint 2:d4de5a5866fe 94 else if(i<0)
maxint 2:d4de5a5866fe 95 this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
maxint 2:d4de5a5866fe 96 else if(this->paddle.hasChanged())
maxint 2:d4de5a5866fe 97 paddle.move(Vector(0, 0)); // move to same place to restrict redraws
maxint 2:d4de5a5866fe 98 }
maxint 2:d4de5a5866fe 99 }
maxint 2:d4de5a5866fe 100
maxint 2:d4de5a5866fe 101
maxint 2:d4de5a5866fe 102
maxint 2:d4de5a5866fe 103
maxint 2:d4de5a5866fe 104 /*
maxint 0:87ab172a74b4 105 void Game::initializeBall()
maxint 0:87ab172a74b4 106 {
maxint 1:c1ee4c699517 107 this->ball.initialize(WIDTH / 2 - Game::BALL_RADIUS, HEIGHT / 4 - Game::BALL_RADIUS, Game::BALL_RADIUS, Color565::fromRGB(0xFF, 0x33, 0x33));
maxint 0:87ab172a74b4 108 this->ball.setSpeed(rand() % 2 ? 1 : -1, rand() % 2 ? 1 : -1);
maxint 0:87ab172a74b4 109 }
maxint 2:d4de5a5866fe 110 */
maxint 0:87ab172a74b4 111
maxint 2:d4de5a5866fe 112 /*
maxint 2:d4de5a5866fe 113 void Game::initializeBalls()
maxint 2:d4de5a5866fe 114 {
maxint 2:d4de5a5866fe 115 for(int i=0; i<NUM_BALLS; i++)
maxint 2:d4de5a5866fe 116 {
maxint 2:d4de5a5866fe 117 this->aBalls[i].initialize(WIDTH / 2 - Game::BALL_RADIUS, HEIGHT / 4 - Game::BALL_RADIUS, Game::BALL_RADIUS, Color565::fromRGB(i==0?0xFF:0x33, i==1?0xFF:0x33, i==2?0xFF:0x33));
maxint 2:d4de5a5866fe 118 //float ftRandX=rand() % 2 ? 1 : -1;
maxint 2:d4de5a5866fe 119 float ftRandX=((rand() % 20) - 10)/10 ;
maxint 2:d4de5a5866fe 120 float ftRandY=rand() % 2 ? 1 : -1;
maxint 2:d4de5a5866fe 121 this->aBalls[i].setSpeed(ftRandX, ftRandY);
maxint 2:d4de5a5866fe 122 }
maxint 2:d4de5a5866fe 123 }
maxint 2:d4de5a5866fe 124 */
maxint 2:d4de5a5866fe 125
maxint 2:d4de5a5866fe 126 void Game::setNoBalls()
maxint 0:87ab172a74b4 127 {
maxint 2:d4de5a5866fe 128 for(int i=0; i<NUM_BALLS; i++)
maxint 2:d4de5a5866fe 129 this->aBalls[i].fActive=false;
maxint 2:d4de5a5866fe 130 }
maxint 2:d4de5a5866fe 131
maxint 2:d4de5a5866fe 132 void Game::newBall()
maxint 2:d4de5a5866fe 133 {
maxint 2:d4de5a5866fe 134 for(int i=0; i<NUM_BALLS; i++)
maxint 2:d4de5a5866fe 135 {
maxint 2:d4de5a5866fe 136 if(this->aBalls[i].fActive)
maxint 2:d4de5a5866fe 137 continue;
maxint 2:d4de5a5866fe 138 else
maxint 2:d4de5a5866fe 139 {
maxint 2:d4de5a5866fe 140 this->aBalls[i].initialize(WIDTH / 2 - Game::BALL_RADIUS, HEIGHT / 4 - Game::BALL_RADIUS, Game::BALL_RADIUS, Color565::fromRGB(i==0?0xFF:0x33, i==1?0xFF:0x33, i==2?0xFF:0x33));
maxint 2:d4de5a5866fe 141 //float ftRandX=rand() % 2 ? 1 : -1;
maxint 2:d4de5a5866fe 142 //float ftRandY=rand() % 2 ? 1 : -1;
maxint 2:d4de5a5866fe 143 float ftRandX=((rand() % 20) - 10)/5.0;
maxint 2:d4de5a5866fe 144 float ftRandY=((rand() % 10) - 10)/5.0;
maxint 2:d4de5a5866fe 145 //this->aBalls[i].setSpeed(ftRandX, ftRandY);
maxint 2:d4de5a5866fe 146 this->aBalls[i].vSpeed.set(ftRandX, ftRandY);
maxint 2:d4de5a5866fe 147 this->aBalls[i].fActive=true;
maxint 2:d4de5a5866fe 148 break;
maxint 2:d4de5a5866fe 149 }
maxint 2:d4de5a5866fe 150 }
maxint 0:87ab172a74b4 151 }
maxint 0:87ab172a74b4 152
maxint 2:d4de5a5866fe 153 void Game::updateBalls()
maxint 2:d4de5a5866fe 154 {
maxint 2:d4de5a5866fe 155 for(int i=0; i<NUM_BALLS; i++)
maxint 2:d4de5a5866fe 156 {
maxint 2:d4de5a5866fe 157 if(!this->aBalls[i].fActive)
maxint 2:d4de5a5866fe 158 continue;
maxint 2:d4de5a5866fe 159
maxint 2:d4de5a5866fe 160 this->aBalls[i].update(); // update the ball position
maxint 2:d4de5a5866fe 161
maxint 2:d4de5a5866fe 162 // add downward gravity
maxint 2:d4de5a5866fe 163 if(this->aBalls[i].vSpeed.getSize() != 0 && this->aBalls[i].vSpeed.getSize()<10.0) // TODO: added if statement to allow zero speed pause of ball
maxint 2:d4de5a5866fe 164 this->aBalls[i].vSpeed.add(this->vGravity); // add some gravity
maxint 2:d4de5a5866fe 165
maxint 2:d4de5a5866fe 166 }
maxint 2:d4de5a5866fe 167 }
maxint 2:d4de5a5866fe 168
maxint 2:d4de5a5866fe 169 void Game::redrawBalls()
maxint 2:d4de5a5866fe 170 {
maxint 2:d4de5a5866fe 171 for(int i=0; i<NUM_BALLS; i++)
maxint 2:d4de5a5866fe 172 {
maxint 2:d4de5a5866fe 173 if(!this->aBalls[i].fActive)
maxint 2:d4de5a5866fe 174 continue;
maxint 2:d4de5a5866fe 175 this->aBalls[i].redraw(); // update the ball position
maxint 2:d4de5a5866fe 176 }
maxint 2:d4de5a5866fe 177 }
maxint 2:d4de5a5866fe 178
maxint 2:d4de5a5866fe 179 int Game::countBalls()
maxint 2:d4de5a5866fe 180 {
maxint 2:d4de5a5866fe 181 int nResult=0;
maxint 2:d4de5a5866fe 182 for(int i=0; i<NUM_BALLS; i++)
maxint 2:d4de5a5866fe 183 {
maxint 2:d4de5a5866fe 184 if(this->aBalls[i].fActive)
maxint 2:d4de5a5866fe 185 nResult++;
maxint 2:d4de5a5866fe 186 }
maxint 2:d4de5a5866fe 187 return(nResult);
maxint 2:d4de5a5866fe 188 }
maxint 2:d4de5a5866fe 189
maxint 2:d4de5a5866fe 190
maxint 2:d4de5a5866fe 191
maxint 2:d4de5a5866fe 192
maxint 2:d4de5a5866fe 193
maxint 2:d4de5a5866fe 194 void Game::tick()
maxint 2:d4de5a5866fe 195 {
maxint 0:87ab172a74b4 196 this->checkButtons();
maxint 0:87ab172a74b4 197
maxint 0:87ab172a74b4 198 if (this->mode) {
maxint 0:87ab172a74b4 199 /*
maxint 0:87ab172a74b4 200 if(this->tWait.read_ms()>100)
maxint 0:87ab172a74b4 201 {
maxint 0:87ab172a74b4 202 this->updatePaddle();
maxint 0:87ab172a74b4 203 this->tWait.reset();
maxint 0:87ab172a74b4 204 }
maxint 0:87ab172a74b4 205 */
maxint 2:d4de5a5866fe 206
maxint 2:d4de5a5866fe 207 /*
maxint 2:d4de5a5866fe 208 if(this->ball.vSpeed.getSize() != 0) // TODO: added if statement to allow zero speed pause of ball
maxint 2:d4de5a5866fe 209 this->ball.vSpeed.add(this->vGravity); // add some gravity
maxint 2:d4de5a5866fe 210 //this->ball.vSpeed.add(Vector(0, 0.1)); // add some gravity
maxint 2:d4de5a5866fe 211 this->ball.update(); // update the ball position
maxint 2:d4de5a5866fe 212 */
maxint 2:d4de5a5866fe 213
maxint 2:d4de5a5866fe 214 this->updateBalls(); // update the ball positions
maxint 2:d4de5a5866fe 215
maxint 0:87ab172a74b4 216 this->updatePaddle();
maxint 0:87ab172a74b4 217
maxint 2:d4de5a5866fe 218 // this->checkCollision();
maxint 2:d4de5a5866fe 219 this->checkPaddle();
maxint 2:d4de5a5866fe 220 this->checkBallsCollision();
maxint 2:d4de5a5866fe 221 // this->ball.redraw();
maxint 2:d4de5a5866fe 222 this->redrawBalls();
maxint 0:87ab172a74b4 223 this->paddle.redraw();
maxint 0:87ab172a74b4 224
maxint 2:d4de5a5866fe 225 this->snd.checkPwm();
maxint 1:c1ee4c699517 226 //this->checkScore();
maxint 0:87ab172a74b4 227 this->checkLives();
maxint 0:87ab172a74b4 228
maxint 0:87ab172a74b4 229 wait_ms(25);
maxint 0:87ab172a74b4 230 }
maxint 1:c1ee4c699517 231 else {
maxint 1:c1ee4c699517 232 this->accel.updateGraph();
maxint 0:87ab172a74b4 233 wait_ms(100);
maxint 0:87ab172a74b4 234 }
maxint 0:87ab172a74b4 235 }
maxint 0:87ab172a74b4 236
maxint 0:87ab172a74b4 237 int Game::checkTilt()
maxint 0:87ab172a74b4 238 { // move the paddle by tilting the board left or righr
maxint 0:87ab172a74b4 239 double x, y, z;
maxint 0:87ab172a74b4 240 //int nStart=this->tWait.read_ms();
maxint 0:87ab172a74b4 241 this->accel.getXYZ(x, y, z);
maxint 0:87ab172a74b4 242
maxint 0:87ab172a74b4 243 //printDouble((double)this->tWait.read_ms()-nStart, 10, 10);
maxint 0:87ab172a74b4 244 /*
maxint 0:87ab172a74b4 245 printDouble(x, 0, 0);
maxint 0:87ab172a74b4 246 char buf[256];
maxint 0:87ab172a74b4 247 sprintf(buf,"tilt:%0.1f", x);
maxint 0:87ab172a74b4 248 this->drawString(buf, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT / 2 + 4*DisplayN18::CHAR_HEIGHT );
maxint 0:87ab172a74b4 249 */
maxint 0:87ab172a74b4 250
maxint 0:87ab172a74b4 251 if(x<-0.1) return(-1);
maxint 0:87ab172a74b4 252 else if(x>0.1) return(1);
maxint 0:87ab172a74b4 253 else return(0);
maxint 0:87ab172a74b4 254 }
maxint 0:87ab172a74b4 255
maxint 0:87ab172a74b4 256 void Game::checkButtons()
maxint 0:87ab172a74b4 257 {
maxint 0:87ab172a74b4 258 if (!this->square.read())
maxint 0:87ab172a74b4 259 {
maxint 0:87ab172a74b4 260 this->mode = !this->mode;
maxint 0:87ab172a74b4 261
maxint 0:87ab172a74b4 262 //this->disp.clear();
maxint 0:87ab172a74b4 263 this->disp.clearScreen();
maxint 0:87ab172a74b4 264
maxint 0:87ab172a74b4 265 if (!this->mode)
maxint 0:87ab172a74b4 266 {
maxint 1:c1ee4c699517 267 this->accel.resetGraph();
maxint 0:87ab172a74b4 268 }
maxint 0:87ab172a74b4 269
maxint 0:87ab172a74b4 270 this->led1.write(this->mode);
maxint 0:87ab172a74b4 271 this->led2.write(!this->mode);
maxint 0:87ab172a74b4 272 }
maxint 0:87ab172a74b4 273 else
maxint 0:87ab172a74b4 274 {
maxint 0:87ab172a74b4 275 bool isUp = !this->up.read();
maxint 0:87ab172a74b4 276 bool isDown = !this->down.read();
maxint 0:87ab172a74b4 277
maxint 0:87ab172a74b4 278 if (isUp && isDown) goto end;
maxint 0:87ab172a74b4 279 if (!isUp && !isDown) goto end;
maxint 0:87ab172a74b4 280
maxint 0:87ab172a74b4 281 if (isUp && this->lastUp) goto end;
maxint 0:87ab172a74b4 282 if (isDown && this->lastDown) goto end;
maxint 0:87ab172a74b4 283
maxint 0:87ab172a74b4 284 if (isUp)
maxint 0:87ab172a74b4 285 {
maxint 0:87ab172a74b4 286 this->ball.changeSpeed(true);
maxint 0:87ab172a74b4 287 }
maxint 0:87ab172a74b4 288 else if (isDown)
maxint 0:87ab172a74b4 289 {
maxint 0:87ab172a74b4 290 this->ball.changeSpeed(false);
maxint 0:87ab172a74b4 291 }
maxint 0:87ab172a74b4 292
maxint 0:87ab172a74b4 293 end:
maxint 0:87ab172a74b4 294 this->lastUp = isUp;
maxint 0:87ab172a74b4 295 this->lastDown = isDown;
maxint 0:87ab172a74b4 296 }
maxint 0:87ab172a74b4 297 }
maxint 0:87ab172a74b4 298
maxint 1:c1ee4c699517 299 void Game::drawString(const char* str, int y)
maxint 1:c1ee4c699517 300 {
maxint 1:c1ee4c699517 301 uint8_t width;
maxint 1:c1ee4c699517 302 uint8_t height;
maxint 1:c1ee4c699517 303
maxint 1:c1ee4c699517 304 this->disp.measureString(font_oem, str, width, height);
maxint 1:c1ee4c699517 305 this->disp.drawString(font_oem, WIDTH / 2 - width / 2, y, str);
maxint 1:c1ee4c699517 306
maxint 0:87ab172a74b4 307 }
maxint 0:87ab172a74b4 308
maxint 0:87ab172a74b4 309 void Game::showSplashScreen() {
maxint 0:87ab172a74b4 310 this->drawString(Game::SPLASH_1, HEIGHT / 2 - CHAR_HEIGHT / 2);
maxint 0:87ab172a74b4 311 this->drawString(Game::SPLASH_2, HEIGHT / 2 + CHAR_HEIGHT / 2);
maxint 0:87ab172a74b4 312 this->drawString(Game::SPLASH_3, HEIGHT / 2 + CHAR_HEIGHT / 2 + 2*(8));
maxint 0:87ab172a74b4 313
maxint 0:87ab172a74b4 314 while (this->circle.read())
maxint 0:87ab172a74b4 315 {
maxint 0:87ab172a74b4 316 int i=this->checkTilt();
maxint 0:87ab172a74b4 317 char buf[256];
maxint 1:c1ee4c699517 318 sprintf(buf," tilt:%d ", i);
maxint 0:87ab172a74b4 319 this->drawString(buf, HEIGHT / 2 - CHAR_HEIGHT / 2 + (4*CHAR_HEIGHT) );
maxint 0:87ab172a74b4 320
maxint 0:87ab172a74b4 321 wait_ms(1);
maxint 0:87ab172a74b4 322 }
maxint 0:87ab172a74b4 323
maxint 2:d4de5a5866fe 324 //this->disp.clearScreen();
maxint 2:d4de5a5866fe 325 this->initialize(); // start a new game
maxint 0:87ab172a74b4 326 }
maxint 0:87ab172a74b4 327
maxint 0:87ab172a74b4 328
maxint 2:d4de5a5866fe 329
maxint 2:d4de5a5866fe 330 void Game::checkBallsCollision()
maxint 2:d4de5a5866fe 331 {
maxint 2:d4de5a5866fe 332 Rectangle rTop=Rectangle(0, -10, WIDTH, 0); // Rectangle(0, 0, WIDTH, 1); // top wall
maxint 2:d4de5a5866fe 333 Rectangle rBottom=Rectangle(0, HEIGHT, WIDTH, HEIGHT+10); // Rectangle(0, HEIGHT, WIDTH, HEIGHT); // bottom gap
maxint 2:d4de5a5866fe 334 Rectangle rLeft=Rectangle(-10, 0, 0, HEIGHT); // Rectangle(0, 0, 0, HEIGHT); // left wall
maxint 2:d4de5a5866fe 335 Rectangle rRight=Rectangle(WIDTH, 0, WIDTH+10, HEIGHT); // Rectangle(WIDTH, 0, WIDTH, HEIGHT); // right wall
maxint 2:d4de5a5866fe 336 Rectangle rPaddle=Rectangle(paddle.pos.getX(), paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH, HEIGHT+10); // Rectangle(this->paddleX, HEIGHT - Game::PADDLE_HEIGHT, this->paddleX + Game::PADDLE_WIDTH, HEIGHT); // paddle
maxint 2:d4de5a5866fe 337 Rectangle rPaddleLeft=Rectangle(paddle.pos.getX(), paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH/3, HEIGHT+10); // paddle left part
maxint 2:d4de5a5866fe 338 Rectangle rPaddleRight=Rectangle(paddle.pos.getX()+ Game::PADDLE_WIDTH/3 + Game::PADDLE_WIDTH/3, paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH, HEIGHT+10); // paddle right part
maxint 2:d4de5a5866fe 339 //Rectangle rScreen=Rectangle(0,0, WIDTH, HEIGHT); // screen boundary
maxint 2:d4de5a5866fe 340
maxint 2:d4de5a5866fe 341 Ball* pBall;
maxint 2:d4de5a5866fe 342 for(int i=0; i<NUM_BALLS; i++)
maxint 0:87ab172a74b4 343 {
maxint 2:d4de5a5866fe 344 if(!this->aBalls[i].fActive)
maxint 2:d4de5a5866fe 345 continue;
maxint 2:d4de5a5866fe 346
maxint 2:d4de5a5866fe 347 pBall=&(this->aBalls[i]);
maxint 2:d4de5a5866fe 348
maxint 2:d4de5a5866fe 349 if(pBall->collides(rTop) && pBall->vSpeed.isUp()) // top wall
maxint 2:d4de5a5866fe 350 {
maxint 2:d4de5a5866fe 351 pBall->Bounce(Vector(1,-1)); // bounce vertical
maxint 2:d4de5a5866fe 352 this->snd.beepShort();
maxint 2:d4de5a5866fe 353 }
maxint 2:d4de5a5866fe 354 if(pBall->collides(rRight) && pBall->vSpeed.isRight()) // right wall
maxint 2:d4de5a5866fe 355 {
maxint 2:d4de5a5866fe 356 pBall->Bounce(Vector(-1,1)); // bounce horizontal
maxint 2:d4de5a5866fe 357 this->snd.beepShort();
maxint 2:d4de5a5866fe 358 }
maxint 2:d4de5a5866fe 359 if(pBall->collides(rLeft) && pBall->vSpeed.isLeft()) // left wall
maxint 2:d4de5a5866fe 360 {
maxint 2:d4de5a5866fe 361 pBall->Bounce(Vector(-1,1)); // bounce horizontal
maxint 2:d4de5a5866fe 362 this->snd.beepShort();
maxint 2:d4de5a5866fe 363 }
maxint 2:d4de5a5866fe 364 if(pBall->collides(rPaddle) && pBall->vSpeed.isDown()) // paddle
maxint 2:d4de5a5866fe 365 {
maxint 2:d4de5a5866fe 366 if(pBall->collides(rPaddleLeft)) pBall->vSpeed.add(Vector(-1,0)); // left side of paddle has bias to the left
maxint 2:d4de5a5866fe 367 if(pBall->collides(rPaddleRight)) pBall->vSpeed.add(Vector(1,0)); // right side of paddle has bias to the right
maxint 2:d4de5a5866fe 368
maxint 2:d4de5a5866fe 369
maxint 2:d4de5a5866fe 370 // increase the speed of the ball when hitting the paddle to increase difficulty
maxint 2:d4de5a5866fe 371 //pBall->Bounce(Vector(1,-1)); // bounce vertical at same speed
maxint 2:d4de5a5866fe 372 float ftSpeedMax=3.0;
maxint 2:d4de5a5866fe 373 if(this->nScore>50)
maxint 2:d4de5a5866fe 374 ftSpeedMax=5.0;
maxint 2:d4de5a5866fe 375 if(this->nScore>100)
maxint 2:d4de5a5866fe 376 ftSpeedMax=10.0;
maxint 2:d4de5a5866fe 377 if(this->nScore>150)
maxint 2:d4de5a5866fe 378 ftSpeedMax=999.0;
maxint 2:d4de5a5866fe 379 if(pBall->vSpeed.getSize()<ftSpeedMax) // TODO: added if statement to allow zero speed pause of ball
maxint 2:d4de5a5866fe 380 pBall->Bounce(Vector(1,-1.02)); // bounce from paddle at higher speed
maxint 2:d4de5a5866fe 381 else
maxint 2:d4de5a5866fe 382 pBall->Bounce(Vector(1,-1)); // bounce vertical at same speed
maxint 2:d4de5a5866fe 383
maxint 2:d4de5a5866fe 384 this->snd.beepLong();
maxint 2:d4de5a5866fe 385 this->nScore++;
maxint 2:d4de5a5866fe 386 this->printf(100, 0, "Score: %d ", this->nScore);
maxint 2:d4de5a5866fe 387
maxint 2:d4de5a5866fe 388 if(this->nScore>0 && this->nScore%10==0)
maxint 2:d4de5a5866fe 389 {
maxint 2:d4de5a5866fe 390 this->newBall();
maxint 2:d4de5a5866fe 391 this->nLives++;
maxint 2:d4de5a5866fe 392 }
maxint 2:d4de5a5866fe 393 }
maxint 2:d4de5a5866fe 394 if(pBall->collides(rBottom) && pBall->vSpeed.isDown()) // bottom gap
maxint 2:d4de5a5866fe 395 {
maxint 2:d4de5a5866fe 396 pBall->clearPrev(); // clear the ball from its previous position
maxint 2:d4de5a5866fe 397 pBall->clear(); // clear the ball from its current position
maxint 2:d4de5a5866fe 398 pBall->vSpeed.set(0,0);
maxint 2:d4de5a5866fe 399 pBall->fActive=false;
maxint 2:d4de5a5866fe 400 this->nLives--;
maxint 2:d4de5a5866fe 401 //this->initializeBall(); // start a new ball
maxint 2:d4de5a5866fe 402 if(countBalls()==0)
maxint 2:d4de5a5866fe 403 {
maxint 2:d4de5a5866fe 404 this->newBall(); // start a new ball
maxint 2:d4de5a5866fe 405 this->snd.beepLow();
maxint 2:d4de5a5866fe 406 }
maxint 2:d4de5a5866fe 407 }
maxint 0:87ab172a74b4 408 }
maxint 0:87ab172a74b4 409 }
maxint 0:87ab172a74b4 410
maxint 2:d4de5a5866fe 411 void Game::checkPaddle()
maxint 2:d4de5a5866fe 412 {
maxint 2:d4de5a5866fe 413 Rectangle rScreen=Rectangle(0,0, WIDTH, HEIGHT); // screen boundary
maxint 2:d4de5a5866fe 414
maxint 2:d4de5a5866fe 415 this->paddle.checkBoundary(rScreen);
maxint 2:d4de5a5866fe 416 }
maxint 2:d4de5a5866fe 417
maxint 2:d4de5a5866fe 418 /*
maxint 0:87ab172a74b4 419 void Game::checkCollision()
maxint 0:87ab172a74b4 420 {
maxint 0:87ab172a74b4 421 Rectangle rTop=Rectangle(0, -10, WIDTH, 0); // Rectangle(0, 0, WIDTH, 1); // top wall
maxint 0:87ab172a74b4 422 Rectangle rBottom=Rectangle(0, HEIGHT, WIDTH, HEIGHT+10); // Rectangle(0, HEIGHT, WIDTH, HEIGHT); // bottom gap
maxint 0:87ab172a74b4 423 Rectangle rLeft=Rectangle(-10, 0, 0, HEIGHT); // Rectangle(0, 0, 0, HEIGHT); // left wall
maxint 0:87ab172a74b4 424 Rectangle rRight=Rectangle(WIDTH, 0, WIDTH+10, HEIGHT); // Rectangle(WIDTH, 0, WIDTH, HEIGHT); // right wall
maxint 0:87ab172a74b4 425 Rectangle rPaddle=Rectangle(paddle.pos.getX(), paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH, HEIGHT+10); // Rectangle(this->paddleX, HEIGHT - Game::PADDLE_HEIGHT, this->paddleX + Game::PADDLE_WIDTH, HEIGHT); // paddle
maxint 0:87ab172a74b4 426 Rectangle rPaddleLeft=Rectangle(paddle.pos.getX(), paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH/3, HEIGHT+10); // paddle left part
maxint 0:87ab172a74b4 427 Rectangle rPaddleRight=Rectangle(paddle.pos.getX()+ Game::PADDLE_WIDTH/3 + Game::PADDLE_WIDTH/3, paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH, HEIGHT+10); // paddle right part
maxint 1:c1ee4c699517 428 Rectangle rScreen=Rectangle(0,0, WIDTH, HEIGHT); // screen boundary
maxint 0:87ab172a74b4 429
maxint 1:c1ee4c699517 430 this->paddle.checkBoundary(rScreen);
maxint 1:c1ee4c699517 431
maxint 0:87ab172a74b4 432 if(ball.collides(rTop) && this->ball.vSpeed.isUp()) // top wall
maxint 0:87ab172a74b4 433 {
maxint 0:87ab172a74b4 434 this->ball.Bounce(Vector(1,-1)); // bounce vertical
maxint 2:d4de5a5866fe 435 this->snd.beepShort();
maxint 0:87ab172a74b4 436 }
maxint 0:87ab172a74b4 437 if(ball.collides(rRight) && this->ball.vSpeed.isRight()) // right wall
maxint 0:87ab172a74b4 438 {
maxint 0:87ab172a74b4 439 this->ball.Bounce(Vector(-1,1)); // bounce horizontal
maxint 2:d4de5a5866fe 440 this->snd.beepShort();
maxint 0:87ab172a74b4 441 }
maxint 0:87ab172a74b4 442 if(ball.collides(rLeft) && this->ball.vSpeed.isLeft()) // left wall
maxint 0:87ab172a74b4 443 {
maxint 0:87ab172a74b4 444 this->ball.Bounce(Vector(-1,1)); // bounce horizontal
maxint 2:d4de5a5866fe 445 this->snd.beepShort();
maxint 0:87ab172a74b4 446 }
maxint 0:87ab172a74b4 447 if(ball.collides(rPaddle) && this->ball.vSpeed.isDown()) // paddle
maxint 0:87ab172a74b4 448 {
maxint 1:c1ee4c699517 449 if(ball.collides(rPaddleLeft)) ball.vSpeed.add(Vector(-1,0)); // left side of paddle has bias to the left
maxint 1:c1ee4c699517 450 if(ball.collides(rPaddleRight)) ball.vSpeed.add(Vector(1,0)); // right side of paddle has bias to the right
maxint 1:c1ee4c699517 451
maxint 2:d4de5a5866fe 452 ball.Bounce(Vector(1,-1)); // bounce vertical at same speed
maxint 2:d4de5a5866fe 453 //ball.Bounce(Vector(1,-1.05)); // bounce from paddle at higher speed
maxint 0:87ab172a74b4 454
maxint 2:d4de5a5866fe 455 this->snd.beepLong();
maxint 1:c1ee4c699517 456 this->nScore++;
maxint 1:c1ee4c699517 457 this->printf(100, 0, "Score: %d ", this->nScore);
maxint 0:87ab172a74b4 458 }
maxint 0:87ab172a74b4 459 if(ball.collides(rBottom) && this->ball.vSpeed.isDown()) // bottom gap
maxint 0:87ab172a74b4 460 {
maxint 1:c1ee4c699517 461 ball.clearPrev(); // clear the ball from its previous position
maxint 1:c1ee4c699517 462 this->nLives--;
maxint 1:c1ee4c699517 463 this->initializeBall(); // start a new ball
maxint 0:87ab172a74b4 464 }
maxint 0:87ab172a74b4 465 }
maxint 2:d4de5a5866fe 466 */
maxint 0:87ab172a74b4 467
maxint 1:c1ee4c699517 468 void Game::printf(int x, int y, const char *szFormat, ...)
maxint 0:87ab172a74b4 469 {
maxint 0:87ab172a74b4 470 char szBuffer[256];
maxint 0:87ab172a74b4 471 va_list args;
maxint 0:87ab172a74b4 472
maxint 0:87ab172a74b4 473 va_start(args, szFormat);
maxint 0:87ab172a74b4 474 vsprintf(szBuffer, szFormat, args);
maxint 0:87ab172a74b4 475 va_end(args);
maxint 1:c1ee4c699517 476 this->disp.drawString(font_oem, x, y, szBuffer);
maxint 0:87ab172a74b4 477 }
maxint 0:87ab172a74b4 478
maxint 0:87ab172a74b4 479
maxint 0:87ab172a74b4 480 void Game::checkLives() {
maxint 1:c1ee4c699517 481 if (this->nLives == 0) {
maxint 0:87ab172a74b4 482 this->disp.clearScreen();
maxint 0:87ab172a74b4 483
maxint 0:87ab172a74b4 484 this->drawString(Game::LOSE_1, HEIGHT / 2 - CHAR_HEIGHT);
maxint 0:87ab172a74b4 485 this->drawString(Game::LOSE_2, HEIGHT / 2);
maxint 0:87ab172a74b4 486
maxint 2:d4de5a5866fe 487 this->snd.playTune();
maxint 0:87ab172a74b4 488 while (this->circle.read())
maxint 0:87ab172a74b4 489 wait_ms(1);
maxint 0:87ab172a74b4 490
maxint 0:87ab172a74b4 491 this->initialize();
maxint 0:87ab172a74b4 492 }
maxint 0:87ab172a74b4 493 else {
maxint 1:c1ee4c699517 494 this->printf(0, 0, "%d", this->nLives);
maxint 0:87ab172a74b4 495 }
maxint 0:87ab172a74b4 496 }