Balls & Paddle game for RETRO Pong inspired game featuring multi-directional tilt-sensitive paddle, multiple balls, shrinking ceiling and a bit of gravity.

Dependencies:   LCD_ST7735 MusicEngine RETRO_BallsAndThings mbed

Balls and Paddle

After doing some work on the Pong mod I decided to put my efforts into making my version object oriented and try to make a generic object-library that could be use for other ball-and-things games. To add some challenges to the gameplay, the following features were added:

  • extra-free additional balls to please the juglers
  • gravity for pulling the ball down to create some dynamic movement
  • directional power-paddle that counters the ball with a bit more speed
  • lowering ceiling to make endless gameplay impossible
Committer:
maxint
Date:
Fri Feb 06 10:18:41 2015 +0000
Revision:
0:7e989d0083ff
Child:
1:bf46edcd6b4f
First game ready for competition

Who changed what in which revision?

UserRevisionLine numberNew contents of line
maxint 0:7e989d0083ff 1 #include "Game.h"
maxint 0:7e989d0083ff 2
maxint 0:7e989d0083ff 3 const char* Game::LOSE_1 = "Game over.";
maxint 0:7e989d0083ff 4 const char* Game::LOSE_2 = "Press ship to restart.";
maxint 0:7e989d0083ff 5 const char* Game::SPLASH_1 = "-*- Balls and paddle -*-";
maxint 0:7e989d0083ff 6 const char* Game::SPLASH_2 = "Press ship to start.";
maxint 0:7e989d0083ff 7 const char* Game::SPLASH_3 = "Made by Maxint";
maxint 0:7e989d0083ff 8
maxint 0:7e989d0083ff 9
maxint 0:7e989d0083ff 10 #define WHITE Color565::White
maxint 0:7e989d0083ff 11 #define BLACK Color565::Black
maxint 0:7e989d0083ff 12 #define BLUE Color565::Blue
maxint 0:7e989d0083ff 13 #define RED Color565::Red
maxint 0:7e989d0083ff 14 #define YELLOW Color565::Yellow
maxint 0:7e989d0083ff 15
maxint 0:7e989d0083ff 16 #define CHAR_WIDTH 8
maxint 0:7e989d0083ff 17 #define CHAR_HEIGHT 8
maxint 0:7e989d0083ff 18 #define HEIGHT this->disp.getHeight()
maxint 0:7e989d0083ff 19 #define WIDTH this->disp.getWidth()
maxint 0:7e989d0083ff 20
maxint 0:7e989d0083ff 21
maxint 0:7e989d0083ff 22
maxint 0:7e989d0083ff 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 0:7e989d0083ff 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:7e989d0083ff 25 {
maxint 0:7e989d0083ff 26 this->disp.setOrientation(LCD_ST7735::Rotate270, false);
maxint 0:7e989d0083ff 27 this->disp.setForegroundColor(WHITE);
maxint 0:7e989d0083ff 28 this->disp.setBackgroundColor(BLACK);
maxint 0:7e989d0083ff 29 this->disp.clearScreen();
maxint 0:7e989d0083ff 30
maxint 0:7e989d0083ff 31 srand(this->ain.read_u16());
maxint 0:7e989d0083ff 32
maxint 0:7e989d0083ff 33 this->lastUp = false;
maxint 0:7e989d0083ff 34 this->lastDown = false;
maxint 0:7e989d0083ff 35 this->mode = true; // mode: true=game, false=graph
maxint 0:7e989d0083ff 36
maxint 0:7e989d0083ff 37 this->nGameTickDelay=25; // game tickdelay can be adjusted using up/down
maxint 0:7e989d0083ff 38
maxint 0:7e989d0083ff 39 for(int i=0; i<NUM_BALLS; i++)
maxint 0:7e989d0083ff 40 this->aBalls[i]=Ball(&(this->disp));
maxint 0:7e989d0083ff 41
maxint 0:7e989d0083ff 42 this->snd.reset();
maxint 0:7e989d0083ff 43 }
maxint 0:7e989d0083ff 44
maxint 0:7e989d0083ff 45 void Game::printDouble(double value, int x, int y)
maxint 0:7e989d0083ff 46 {
maxint 0:7e989d0083ff 47 char buffer[10];
maxint 0:7e989d0083ff 48 int len = sprintf(buffer, "%.1f ", value);
maxint 0:7e989d0083ff 49
maxint 0:7e989d0083ff 50 this->disp.drawString(font_oem, x, y, buffer);
maxint 0:7e989d0083ff 51 }
maxint 0:7e989d0083ff 52
maxint 0:7e989d0083ff 53 void Game::initialize()
maxint 0:7e989d0083ff 54 {
maxint 0:7e989d0083ff 55 this->disp.clearScreen();
maxint 0:7e989d0083ff 56
maxint 0:7e989d0083ff 57 this->snd.reset();
maxint 0:7e989d0083ff 58 this->nBalls = 4;
maxint 0:7e989d0083ff 59 this->nScore = 0;
maxint 0:7e989d0083ff 60 this->nTopWall = 8;
maxint 0:7e989d0083ff 61 this->fDrawTopWall=true;
maxint 0:7e989d0083ff 62
maxint 0:7e989d0083ff 63 this->initializePaddle();
maxint 0:7e989d0083ff 64 this->setNoBalls(); // reset all balls
maxint 0:7e989d0083ff 65 this->newBall(); // start first ball
maxint 0:7e989d0083ff 66 this->snd.play("T240 L16 O5 D E F");
maxint 0:7e989d0083ff 67 }
maxint 0:7e989d0083ff 68
maxint 0:7e989d0083ff 69
maxint 0:7e989d0083ff 70 void Game::initializePaddle()
maxint 0:7e989d0083ff 71 {
maxint 0:7e989d0083ff 72 this->paddle.initialize(WIDTH / 2 - Game::PADDLE_WIDTH/2, HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT);
maxint 0:7e989d0083ff 73 this->fDrawPaddle=true;
maxint 0:7e989d0083ff 74 }
maxint 0:7e989d0083ff 75
maxint 0:7e989d0083ff 76
maxint 0:7e989d0083ff 77 void Game::updatePaddle()
maxint 0:7e989d0083ff 78 {
maxint 0:7e989d0083ff 79 if (!this->left.read()) // note: read is LOW (0) when button pressed
maxint 0:7e989d0083ff 80 this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
maxint 0:7e989d0083ff 81 else if (!this->right.read())
maxint 0:7e989d0083ff 82 this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
maxint 0:7e989d0083ff 83 else
maxint 0:7e989d0083ff 84 {
maxint 0:7e989d0083ff 85 int i=this->checkTilt();
maxint 0:7e989d0083ff 86 if(i>0)
maxint 0:7e989d0083ff 87 this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
maxint 0:7e989d0083ff 88 else if(i<0)
maxint 0:7e989d0083ff 89 this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
maxint 0:7e989d0083ff 90 else if(this->paddle.hasChanged())
maxint 0:7e989d0083ff 91 paddle.move(Vector(0, 0)); // move to same place to restrict redraws
maxint 0:7e989d0083ff 92 }
maxint 0:7e989d0083ff 93 }
maxint 0:7e989d0083ff 94
maxint 0:7e989d0083ff 95 void Game::redrawPaddle()
maxint 0:7e989d0083ff 96 { // redraw the paddle when moved, or when forced by this->fDrawPaddle (set at bounce)
maxint 0:7e989d0083ff 97 this->paddle.redraw(this->fDrawPaddle);
maxint 0:7e989d0083ff 98 this->fDrawPaddle=false;
maxint 0:7e989d0083ff 99 }
maxint 0:7e989d0083ff 100
maxint 0:7e989d0083ff 101 void Game::setNoBalls()
maxint 0:7e989d0083ff 102 { // make sure no balls are active
maxint 0:7e989d0083ff 103 for(int i=0; i<NUM_BALLS; i++)
maxint 0:7e989d0083ff 104 this->aBalls[i].fActive=false;
maxint 0:7e989d0083ff 105 }
maxint 0:7e989d0083ff 106
maxint 0:7e989d0083ff 107 void Game::newBall()
maxint 0:7e989d0083ff 108 { // add a new ball to the game
maxint 0:7e989d0083ff 109 for(int i=0; i<NUM_BALLS; i++)
maxint 0:7e989d0083ff 110 {
maxint 0:7e989d0083ff 111 if(this->aBalls[i].fActive)
maxint 0:7e989d0083ff 112 continue;
maxint 0:7e989d0083ff 113 else
maxint 0:7e989d0083ff 114 {
maxint 0:7e989d0083ff 115 this->aBalls[i].initialize(WIDTH / 2 - Game::BALL_RADIUS, this->nTopWall + (HEIGHT-this->nTopWall) / 4 - Game::BALL_RADIUS, Game::BALL_RADIUS, Color565::fromRGB(i==0?0xFF:0x33, i==1?0xFF:0x33, i==2?0xFF:0x33));
maxint 0:7e989d0083ff 116 //float ftRandX=rand() % 2 ? 1 : -1;
maxint 0:7e989d0083ff 117 //float ftRandY=rand() % 2 ? 1 : -1;
maxint 0:7e989d0083ff 118 //this->aBalls[i].setSpeed(ftRandX, ftRandY);
maxint 0:7e989d0083ff 119 float ftRandX=((rand() % 20) - 10)/5.0; // left/right at random speed
maxint 0:7e989d0083ff 120 float ftRandY=((rand() % 10) - 10)/5.0; // up at random speed
maxint 0:7e989d0083ff 121 this->aBalls[i].vSpeed.set(ftRandX, ftRandY);
maxint 0:7e989d0083ff 122 this->aBalls[i].fActive=true;
maxint 0:7e989d0083ff 123 break;
maxint 0:7e989d0083ff 124 }
maxint 0:7e989d0083ff 125 }
maxint 0:7e989d0083ff 126 }
maxint 0:7e989d0083ff 127
maxint 0:7e989d0083ff 128 void Game::updateBalls()
maxint 0:7e989d0083ff 129 {
maxint 0:7e989d0083ff 130 for(int i=0; i<NUM_BALLS; i++)
maxint 0:7e989d0083ff 131 {
maxint 0:7e989d0083ff 132 if(!this->aBalls[i].fActive)
maxint 0:7e989d0083ff 133 continue;
maxint 0:7e989d0083ff 134
maxint 0:7e989d0083ff 135 this->aBalls[i].update(); // update the ball position
maxint 0:7e989d0083ff 136
maxint 0:7e989d0083ff 137 // add downward gravity
maxint 0:7e989d0083ff 138 if(this->aBalls[i].vSpeed.getSize()<10.0)
maxint 0:7e989d0083ff 139 this->aBalls[i].vSpeed.add(this->vGravity); // add some gravity
maxint 0:7e989d0083ff 140
maxint 0:7e989d0083ff 141 }
maxint 0:7e989d0083ff 142 }
maxint 0:7e989d0083ff 143
maxint 0:7e989d0083ff 144 void Game::redrawBalls()
maxint 0:7e989d0083ff 145 {
maxint 0:7e989d0083ff 146 for(int i=0; i<NUM_BALLS; i++)
maxint 0:7e989d0083ff 147 {
maxint 0:7e989d0083ff 148 if(!this->aBalls[i].fActive)
maxint 0:7e989d0083ff 149 continue;
maxint 0:7e989d0083ff 150 this->aBalls[i].redraw(); // update the ball position
maxint 0:7e989d0083ff 151 }
maxint 0:7e989d0083ff 152 }
maxint 0:7e989d0083ff 153
maxint 0:7e989d0083ff 154 int Game::countBalls()
maxint 0:7e989d0083ff 155 {
maxint 0:7e989d0083ff 156 int nResult=0;
maxint 0:7e989d0083ff 157 for(int i=0; i<NUM_BALLS; i++)
maxint 0:7e989d0083ff 158 {
maxint 0:7e989d0083ff 159 if(this->aBalls[i].fActive)
maxint 0:7e989d0083ff 160 nResult++;
maxint 0:7e989d0083ff 161 }
maxint 0:7e989d0083ff 162 return(nResult);
maxint 0:7e989d0083ff 163 }
maxint 0:7e989d0083ff 164
maxint 0:7e989d0083ff 165
maxint 0:7e989d0083ff 166
maxint 0:7e989d0083ff 167
maxint 0:7e989d0083ff 168
maxint 0:7e989d0083ff 169 void Game::tick()
maxint 0:7e989d0083ff 170 {
maxint 0:7e989d0083ff 171 this->checkButtons();
maxint 0:7e989d0083ff 172
maxint 0:7e989d0083ff 173 if (this->mode) {
maxint 0:7e989d0083ff 174
maxint 0:7e989d0083ff 175 this->updateBalls(); // update the ball positions
maxint 0:7e989d0083ff 176 this->updatePaddle();
maxint 0:7e989d0083ff 177
maxint 0:7e989d0083ff 178 this->checkPaddle();
maxint 0:7e989d0083ff 179 this->checkBallsCollision();
maxint 0:7e989d0083ff 180
maxint 0:7e989d0083ff 181 this->redrawBalls();
maxint 0:7e989d0083ff 182 this->redrawPaddle();
maxint 0:7e989d0083ff 183 this->redrawTopWall();
maxint 0:7e989d0083ff 184
maxint 0:7e989d0083ff 185 //this->checkScore();
maxint 0:7e989d0083ff 186 this->checkBalls();
maxint 0:7e989d0083ff 187
maxint 0:7e989d0083ff 188 wait_ms(this->nGameTickDelay); // can be adjusted using up/down
maxint 0:7e989d0083ff 189 }
maxint 0:7e989d0083ff 190 else {
maxint 0:7e989d0083ff 191 this->accel.updateGraph();
maxint 0:7e989d0083ff 192 wait_ms(100);
maxint 0:7e989d0083ff 193 }
maxint 0:7e989d0083ff 194 }
maxint 0:7e989d0083ff 195
maxint 0:7e989d0083ff 196 int Game::checkTilt()
maxint 0:7e989d0083ff 197 { // move the paddle by tilting the board left or righr
maxint 0:7e989d0083ff 198 double x, y, z;
maxint 0:7e989d0083ff 199 this->accel.getXYZ(x, y, z);
maxint 0:7e989d0083ff 200 if(x<-0.1) return(-1);
maxint 0:7e989d0083ff 201 else if(x>0.1) return(1);
maxint 0:7e989d0083ff 202 else return(0);
maxint 0:7e989d0083ff 203 }
maxint 0:7e989d0083ff 204
maxint 0:7e989d0083ff 205 void Game::checkButtons()
maxint 0:7e989d0083ff 206 {
maxint 0:7e989d0083ff 207 if(!this->square.read()) // note: button.read() is false (LOW/0) when pressed
maxint 0:7e989d0083ff 208 {
maxint 0:7e989d0083ff 209 wait_ms(250); // el-cheapo deboounce
maxint 0:7e989d0083ff 210 this->mode = !this->mode;
maxint 0:7e989d0083ff 211
maxint 0:7e989d0083ff 212 this->disp.clearScreen();
maxint 0:7e989d0083ff 213
maxint 0:7e989d0083ff 214 if (!this->mode)
maxint 0:7e989d0083ff 215 {
maxint 0:7e989d0083ff 216 this->accel.resetGraph();
maxint 0:7e989d0083ff 217 }
maxint 0:7e989d0083ff 218
maxint 0:7e989d0083ff 219 this->led1.write(this->mode);
maxint 0:7e989d0083ff 220 this->led2.write(!this->mode);
maxint 0:7e989d0083ff 221 }
maxint 0:7e989d0083ff 222 else if(!this->circle.read() && this->mode) // note: button.read() is false (LOW/0) when pressed
maxint 0:7e989d0083ff 223 {
maxint 0:7e989d0083ff 224 bool fMute=this->snd.getMute();
maxint 0:7e989d0083ff 225 fMute=!fMute;
maxint 0:7e989d0083ff 226 this->snd.setMute(fMute);
maxint 0:7e989d0083ff 227 this->led2.write(fMute);
maxint 0:7e989d0083ff 228 wait_ms(250); // el-cheapo deboounce
maxint 0:7e989d0083ff 229 }
maxint 0:7e989d0083ff 230 else
maxint 0:7e989d0083ff 231 {
maxint 0:7e989d0083ff 232 bool isUp = !this->up.read();
maxint 0:7e989d0083ff 233 bool isDown = !this->down.read();
maxint 0:7e989d0083ff 234
maxint 0:7e989d0083ff 235 if (isUp && isDown) goto end;
maxint 0:7e989d0083ff 236 if (!isUp && !isDown) goto end;
maxint 0:7e989d0083ff 237
maxint 0:7e989d0083ff 238 if (isUp && this->lastUp) goto end;
maxint 0:7e989d0083ff 239 if (isDown && this->lastDown) goto end;
maxint 0:7e989d0083ff 240
maxint 0:7e989d0083ff 241 if (isUp)
maxint 0:7e989d0083ff 242 {
maxint 0:7e989d0083ff 243 if(this->nGameTickDelay<1000) this->nGameTickDelay=(float)this->nGameTickDelay*1.20;
maxint 0:7e989d0083ff 244 this->printf(100, 0, "Speed: %d ", this->nGameTickDelay);
maxint 0:7e989d0083ff 245 }
maxint 0:7e989d0083ff 246 else if (isDown)
maxint 0:7e989d0083ff 247 {
maxint 0:7e989d0083ff 248 if(this->nGameTickDelay>5) this->nGameTickDelay=(float)this->nGameTickDelay/1.20;
maxint 0:7e989d0083ff 249 this->printf(100, 0, "Speed: %d ", this->nGameTickDelay);
maxint 0:7e989d0083ff 250 }
maxint 0:7e989d0083ff 251
maxint 0:7e989d0083ff 252 end:
maxint 0:7e989d0083ff 253 this->lastUp = isUp;
maxint 0:7e989d0083ff 254 this->lastDown = isDown;
maxint 0:7e989d0083ff 255 }
maxint 0:7e989d0083ff 256 }
maxint 0:7e989d0083ff 257
maxint 0:7e989d0083ff 258 void Game::drawString(const char* str, int y)
maxint 0:7e989d0083ff 259 {
maxint 0:7e989d0083ff 260 uint8_t width;
maxint 0:7e989d0083ff 261 uint8_t height;
maxint 0:7e989d0083ff 262
maxint 0:7e989d0083ff 263 this->disp.measureString(font_oem, str, width, height);
maxint 0:7e989d0083ff 264 this->disp.drawString(font_oem, WIDTH / 2 - width / 2, y, str);
maxint 0:7e989d0083ff 265
maxint 0:7e989d0083ff 266 }
maxint 0:7e989d0083ff 267
maxint 0:7e989d0083ff 268 void Game::showSplashScreen()
maxint 0:7e989d0083ff 269 {
maxint 0:7e989d0083ff 270 this->drawString(Game::SPLASH_1, HEIGHT / 2 - CHAR_HEIGHT / 2);
maxint 0:7e989d0083ff 271 this->drawString(Game::SPLASH_2, HEIGHT / 2 + CHAR_HEIGHT / 2);
maxint 0:7e989d0083ff 272 this->drawString(Game::SPLASH_3, HEIGHT / 2 + CHAR_HEIGHT / 2 + 2*CHAR_HEIGHT);
maxint 0:7e989d0083ff 273
maxint 0:7e989d0083ff 274 while (this->circle.read())
maxint 0:7e989d0083ff 275 wait_ms(1);
maxint 0:7e989d0083ff 276 wait_ms(250); // el-cheapo deboounce
maxint 0:7e989d0083ff 277
maxint 0:7e989d0083ff 278 this->initialize(); // start a new game
maxint 0:7e989d0083ff 279 }
maxint 0:7e989d0083ff 280
maxint 0:7e989d0083ff 281
maxint 0:7e989d0083ff 282
maxint 0:7e989d0083ff 283 void Game::checkBallsCollision()
maxint 0:7e989d0083ff 284 {
maxint 0:7e989d0083ff 285 Rectangle rTop=Rectangle(0, -10, WIDTH, this->nTopWall); // top wall
maxint 0:7e989d0083ff 286 Rectangle rBottom=Rectangle(0, HEIGHT, WIDTH, HEIGHT+10); // bottom gap
maxint 0:7e989d0083ff 287 Rectangle rLeft=Rectangle(-10, 0, 0, HEIGHT); // left wall
maxint 0:7e989d0083ff 288 Rectangle rRight=Rectangle(WIDTH, 0, WIDTH+10, HEIGHT); // right wall
maxint 0:7e989d0083ff 289 Rectangle rPaddle=Rectangle(paddle.pos.getX(), paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH, HEIGHT+10); // paddle
maxint 0:7e989d0083ff 290 Rectangle rPaddleLeft=Rectangle(paddle.pos.getX(), paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH/3, HEIGHT+10); // paddle left part
maxint 0:7e989d0083ff 291 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 0:7e989d0083ff 292
maxint 0:7e989d0083ff 293 Ball* pBall;
maxint 0:7e989d0083ff 294 for(int i=0; i<NUM_BALLS; i++)
maxint 0:7e989d0083ff 295 {
maxint 0:7e989d0083ff 296 if(!this->aBalls[i].fActive)
maxint 0:7e989d0083ff 297 continue;
maxint 0:7e989d0083ff 298
maxint 0:7e989d0083ff 299 pBall=&(this->aBalls[i]);
maxint 0:7e989d0083ff 300
maxint 0:7e989d0083ff 301 if(pBall->collides(rTop) && pBall->vSpeed.isUp()) // top wall
maxint 0:7e989d0083ff 302 {
maxint 0:7e989d0083ff 303 pBall->Bounce(Vector(1,-1)); // bounce vertical
maxint 0:7e989d0083ff 304 this->snd.beepShort();
maxint 0:7e989d0083ff 305 this->fDrawTopWall=true;
maxint 0:7e989d0083ff 306 }
maxint 0:7e989d0083ff 307 if(pBall->collides(rRight) && pBall->vSpeed.isRight()) // right wall
maxint 0:7e989d0083ff 308 {
maxint 0:7e989d0083ff 309 pBall->Bounce(Vector(-1,1)); // bounce horizontal
maxint 0:7e989d0083ff 310 this->snd.beepShort();
maxint 0:7e989d0083ff 311 }
maxint 0:7e989d0083ff 312 if(pBall->collides(rLeft) && pBall->vSpeed.isLeft()) // left wall
maxint 0:7e989d0083ff 313 {
maxint 0:7e989d0083ff 314 pBall->Bounce(Vector(-1,1)); // bounce horizontal
maxint 0:7e989d0083ff 315 this->snd.beepShort();
maxint 0:7e989d0083ff 316 }
maxint 0:7e989d0083ff 317 if(pBall->collides(rPaddle) && pBall->vSpeed.isDown()) // paddle
maxint 0:7e989d0083ff 318 {
maxint 0:7e989d0083ff 319 if(pBall->collides(rPaddleLeft)) pBall->vSpeed.add(Vector(-1.3,0)); // left side of paddle has bias to the left
maxint 0:7e989d0083ff 320 if(pBall->collides(rPaddleRight)) pBall->vSpeed.add(Vector(1.3,0)); // right side of paddle has bias to the right
maxint 0:7e989d0083ff 321
maxint 0:7e989d0083ff 322 // bounce the ball
maxint 0:7e989d0083ff 323 // increase the speed of the ball when hitting the paddle to increase difficulty
maxint 0:7e989d0083ff 324 float ftSpeedMax=3.0;
maxint 0:7e989d0083ff 325 if(this->nScore>50)
maxint 0:7e989d0083ff 326 ftSpeedMax=5.0;
maxint 0:7e989d0083ff 327 if(this->nScore>100)
maxint 0:7e989d0083ff 328 ftSpeedMax=10.0;
maxint 0:7e989d0083ff 329 if(this->nScore>150)
maxint 0:7e989d0083ff 330 ftSpeedMax=999.0;
maxint 0:7e989d0083ff 331 if(pBall->vSpeed.getSize()<ftSpeedMax)
maxint 0:7e989d0083ff 332 pBall->Bounce(Vector(1,-1.02)); // bounce from paddle at higher speed
maxint 0:7e989d0083ff 333 else
maxint 0:7e989d0083ff 334 pBall->Bounce(Vector(1,-1)); // bounce vertical at same speed
maxint 0:7e989d0083ff 335
maxint 0:7e989d0083ff 336 // force drawing the paddle after redrawing the bounced ball
maxint 0:7e989d0083ff 337 this->fDrawPaddle=true;
maxint 0:7e989d0083ff 338
maxint 0:7e989d0083ff 339 // make sound and update the score
maxint 0:7e989d0083ff 340 this->snd.beepLong();
maxint 0:7e989d0083ff 341 this->nScore++;
maxint 0:7e989d0083ff 342 this->printf(100, 0, "Score: %d ", this->nScore);
maxint 0:7e989d0083ff 343
maxint 0:7e989d0083ff 344 // add a new ball every 10 points
maxint 0:7e989d0083ff 345 if(this->nScore>0 && this->nScore%10==0)
maxint 0:7e989d0083ff 346 {
maxint 0:7e989d0083ff 347 this->newBall();
maxint 0:7e989d0083ff 348 this->nBalls++;
maxint 0:7e989d0083ff 349 this->snd.play("T240 L16 O5 D E F");
maxint 0:7e989d0083ff 350 }
maxint 0:7e989d0083ff 351
maxint 0:7e989d0083ff 352 // lower the ceiling every 25 points
maxint 0:7e989d0083ff 353 if(this->nScore>0 && this->nScore%25==0)
maxint 0:7e989d0083ff 354 {
maxint 0:7e989d0083ff 355 this->nTopWall+=3;
maxint 0:7e989d0083ff 356 this->fDrawTopWall=true;
maxint 0:7e989d0083ff 357 this->snd.play("T240 L16 O5 CDEFG");
maxint 0:7e989d0083ff 358 }
maxint 0:7e989d0083ff 359
maxint 0:7e989d0083ff 360 }
maxint 0:7e989d0083ff 361 if(pBall->collides(rBottom) && pBall->vSpeed.isDown()) // bottom gap
maxint 0:7e989d0083ff 362 {
maxint 0:7e989d0083ff 363 pBall->clearPrev(); // clear the ball from its previous position
maxint 0:7e989d0083ff 364 pBall->clear(); // clear the ball from its current position
maxint 0:7e989d0083ff 365 pBall->vSpeed.set(0,0);
maxint 0:7e989d0083ff 366 pBall->fActive=false;
maxint 0:7e989d0083ff 367 this->nBalls--;
maxint 0:7e989d0083ff 368 if(countBalls()==0)
maxint 0:7e989d0083ff 369 {
maxint 0:7e989d0083ff 370 this->newBall(); // start a new ball
maxint 0:7e989d0083ff 371 this->snd.beepLow();
maxint 0:7e989d0083ff 372 }
maxint 0:7e989d0083ff 373 }
maxint 0:7e989d0083ff 374 }
maxint 0:7e989d0083ff 375 }
maxint 0:7e989d0083ff 376
maxint 0:7e989d0083ff 377 void Game::redrawTopWall()
maxint 0:7e989d0083ff 378 {
maxint 0:7e989d0083ff 379 if(this->fDrawTopWall)
maxint 0:7e989d0083ff 380 {
maxint 0:7e989d0083ff 381 int nTop=max(this->nTopWall-2, 8);
maxint 0:7e989d0083ff 382 this->disp.fillRect(0, 8, WIDTH, nTop, Color565::Black);
maxint 0:7e989d0083ff 383 this->disp.fillRect(0, nTop, WIDTH, this->nTopWall, Color565::Purple);
maxint 0:7e989d0083ff 384 this->fDrawTopWall=false;
maxint 0:7e989d0083ff 385 }
maxint 0:7e989d0083ff 386 }
maxint 0:7e989d0083ff 387
maxint 0:7e989d0083ff 388 void Game::checkPaddle()
maxint 0:7e989d0083ff 389 {
maxint 0:7e989d0083ff 390 Rectangle rScreen=Rectangle(0,0, WIDTH, HEIGHT); // screen boundary
maxint 0:7e989d0083ff 391
maxint 0:7e989d0083ff 392 this->paddle.checkBoundary(rScreen);
maxint 0:7e989d0083ff 393 }
maxint 0:7e989d0083ff 394
maxint 0:7e989d0083ff 395
maxint 0:7e989d0083ff 396 void Game::printf(int x, int y, const char *szFormat, ...)
maxint 0:7e989d0083ff 397 {
maxint 0:7e989d0083ff 398 char szBuffer[256];
maxint 0:7e989d0083ff 399 va_list args;
maxint 0:7e989d0083ff 400
maxint 0:7e989d0083ff 401 va_start(args, szFormat);
maxint 0:7e989d0083ff 402 vsprintf(szBuffer, szFormat, args);
maxint 0:7e989d0083ff 403 va_end(args);
maxint 0:7e989d0083ff 404 this->disp.drawString(font_oem, x, y, szBuffer);
maxint 0:7e989d0083ff 405 }
maxint 0:7e989d0083ff 406
maxint 0:7e989d0083ff 407
maxint 0:7e989d0083ff 408 void Game::checkBalls()
maxint 0:7e989d0083ff 409 {
maxint 0:7e989d0083ff 410 if (this->nBalls == 0)
maxint 0:7e989d0083ff 411 { // game over
maxint 0:7e989d0083ff 412 char buf[256];
maxint 0:7e989d0083ff 413 this->disp.clearScreen();
maxint 0:7e989d0083ff 414
maxint 0:7e989d0083ff 415 this->drawString(Game::LOSE_1, HEIGHT / 2 - CHAR_HEIGHT);
maxint 0:7e989d0083ff 416 this->drawString(Game::LOSE_2, HEIGHT / 2);
maxint 0:7e989d0083ff 417 sprintf(buf,"Your score: %d ", this->nScore);
maxint 0:7e989d0083ff 418 this->drawString(buf, HEIGHT / 2 + CHAR_HEIGHT / 2 + CHAR_HEIGHT );
maxint 0:7e989d0083ff 419
maxint 0:7e989d0083ff 420 this->snd.play("T120 O3 L4 R4 F C F2 C");
maxint 0:7e989d0083ff 421 while (this->circle.read())
maxint 0:7e989d0083ff 422 wait_ms(1);
maxint 0:7e989d0083ff 423 wait_ms(250); // el-cheapo deboounce
maxint 0:7e989d0083ff 424 this->initialize();
maxint 0:7e989d0083ff 425 }
maxint 0:7e989d0083ff 426 else
maxint 0:7e989d0083ff 427 {
maxint 0:7e989d0083ff 428 this->printf(0, 0, "Balls: %d ", this->nBalls);
maxint 0:7e989d0083ff 429 }
maxint 0:7e989d0083ff 430 }