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:
Wed Jan 28 17:32:54 2015 +0000
Revision:
0:87ab172a74b4
Child:
1:c1ee4c699517
Separated elements as objects, added gravity and bouncespeed.

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 0:87ab172a74b4 5 const char* Game::SPLASH_1 = "Press ship to start.";
maxint 0:87ab172a74b4 6 const char* Game::SPLASH_2 = "Press robot to switch.";
maxint 0:87ab172a74b4 7 const char* Game::SPLASH_3 = "mod:Tilt 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 0:87ab172a74b4 24 pwm(P0_18), 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), vGravity(0, 0.1)
maxint 0:87ab172a74b4 25 {
maxint 0:87ab172a74b4 26 srand(this->ain.read_u16());
maxint 0:87ab172a74b4 27
maxint 0:87ab172a74b4 28 this->lastUp = false;
maxint 0:87ab172a74b4 29 this->lastDown = false;
maxint 0:87ab172a74b4 30 this->mode = true;
maxint 0:87ab172a74b4 31
maxint 0:87ab172a74b4 32 this->colors[0] = Color565::Red;
maxint 0:87ab172a74b4 33 this->colors[1] = Color565::Green;
maxint 0:87ab172a74b4 34 this->colors[2] = Color565::Blue;
maxint 0:87ab172a74b4 35
maxint 0:87ab172a74b4 36 this->initialize();
maxint 0:87ab172a74b4 37 }
maxint 0:87ab172a74b4 38
maxint 0:87ab172a74b4 39 /*
maxint 0:87ab172a74b4 40 void Game::getXYZ(double& x, double& y, double& z) {
maxint 0:87ab172a74b4 41 this->accel.getXYZ(x, y, z);
maxint 0:87ab172a74b4 42 }
maxint 0:87ab172a74b4 43 */
maxint 0:87ab172a74b4 44
maxint 0:87ab172a74b4 45 void Game::printDouble(double value, int x, int y) {
maxint 0:87ab172a74b4 46 char buffer[10];
maxint 0:87ab172a74b4 47 int len = sprintf(buffer, "%.1f ", value);
maxint 0:87ab172a74b4 48
maxint 0:87ab172a74b4 49 this->disp.drawString(font_ibm, x, y, buffer);
maxint 0:87ab172a74b4 50 }
maxint 0:87ab172a74b4 51
maxint 0:87ab172a74b4 52 void Game::drawAxes() {
maxint 0:87ab172a74b4 53 for (int i = 0; i < 3; i++) {
maxint 0:87ab172a74b4 54 this->disp.drawLine(0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING), 0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT, WHITE);
maxint 0:87ab172a74b4 55 this->disp.drawLine(0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT / 2, WIDTH, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT / 2, WHITE);
maxint 0:87ab172a74b4 56 }
maxint 0:87ab172a74b4 57 }
maxint 0:87ab172a74b4 58
maxint 0:87ab172a74b4 59 void Game::drawPoint(int axis, double value) {
maxint 0:87ab172a74b4 60 if (value < -1.0)
maxint 0:87ab172a74b4 61 value = -1.0;
maxint 0:87ab172a74b4 62
maxint 0:87ab172a74b4 63 if (value > 1.0)
maxint 0:87ab172a74b4 64 value = 1.0;
maxint 0:87ab172a74b4 65
maxint 0:87ab172a74b4 66 value += 1.0;
maxint 0:87ab172a74b4 67 value /= 2.0;
maxint 0:87ab172a74b4 68 value = 1.0 - value;
maxint 0:87ab172a74b4 69 value *= Game::GRAPH_HEIGHT;
maxint 0:87ab172a74b4 70
maxint 0:87ab172a74b4 71 this->disp.setPixel(this->graphX, axis * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + (int)value, this->colors[axis]);
maxint 0:87ab172a74b4 72 }
maxint 0:87ab172a74b4 73
maxint 0:87ab172a74b4 74 void Game::checkGraphReset() {
maxint 0:87ab172a74b4 75 if (this->graphX > WIDTH) {
maxint 0:87ab172a74b4 76 this->graphX = 0;
maxint 0:87ab172a74b4 77 this->disp.clearScreen();
maxint 0:87ab172a74b4 78 this->drawAxes();
maxint 0:87ab172a74b4 79 }
maxint 0:87ab172a74b4 80 }
maxint 0:87ab172a74b4 81
maxint 0:87ab172a74b4 82 void Game::initialize() {
maxint 0:87ab172a74b4 83 //this->disp.clear();
maxint 0:87ab172a74b4 84 this->disp.setOrientation(LCD_ST7735::Rotate270, false);
maxint 0:87ab172a74b4 85 this->disp.setForegroundColor(WHITE);
maxint 0:87ab172a74b4 86 this->disp.setBackgroundColor(BLACK);
maxint 0:87ab172a74b4 87 this->disp.clearScreen();
maxint 0:87ab172a74b4 88
maxint 0:87ab172a74b4 89 this->initializeBall();
maxint 0:87ab172a74b4 90 this->initializePaddle();
maxint 0:87ab172a74b4 91
maxint 0:87ab172a74b4 92 this->paddleX = WIDTH / 2 - Game::PADDLE_WIDTH / 2;
maxint 0:87ab172a74b4 93 this->pwmTicksLeft = 0;
maxint 0:87ab172a74b4 94 this->lives = 4;
maxint 0:87ab172a74b4 95
maxint 0:87ab172a74b4 96 this->pwm.period_ms(1);
maxint 0:87ab172a74b4 97 this->pwm.write(0.00);
maxint 0:87ab172a74b4 98
maxint 0:87ab172a74b4 99 this->tWait.start(); // start the timer
maxint 0:87ab172a74b4 100
maxint 0:87ab172a74b4 101 }
maxint 0:87ab172a74b4 102
maxint 0:87ab172a74b4 103 void Game::initializeBall()
maxint 0:87ab172a74b4 104 {
maxint 0:87ab172a74b4 105 this->ball.initialize(&(this->disp),WIDTH / 2 - Game::BALL_RADIUS, HEIGHT / 4 - Game::BALL_RADIUS, Game::BALL_RADIUS);
maxint 0:87ab172a74b4 106 this->ball.setSpeed(rand() % 2 ? 1 : -1, rand() % 2 ? 1 : -1);
maxint 0:87ab172a74b4 107 }
maxint 0:87ab172a74b4 108
maxint 0:87ab172a74b4 109 void Game::initializePaddle()
maxint 0:87ab172a74b4 110 {
maxint 0:87ab172a74b4 111 this->paddle.initialize(&(this->disp), WIDTH / 2 - Game::PADDLE_WIDTH/2, HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT);
maxint 0:87ab172a74b4 112 }
maxint 0:87ab172a74b4 113
maxint 0:87ab172a74b4 114 void Game::tick() {
maxint 0:87ab172a74b4 115 this->checkButtons();
maxint 0:87ab172a74b4 116
maxint 0:87ab172a74b4 117 if (this->mode) {
maxint 0:87ab172a74b4 118 //this->clearPaddle();
maxint 0:87ab172a74b4 119 //this->paddle.clear();
maxint 0:87ab172a74b4 120 /*
maxint 0:87ab172a74b4 121 if(this->tWait.read_ms()>100)
maxint 0:87ab172a74b4 122 {
maxint 0:87ab172a74b4 123 this->updatePaddle();
maxint 0:87ab172a74b4 124 this->tWait.reset();
maxint 0:87ab172a74b4 125 }
maxint 0:87ab172a74b4 126 */
maxint 0:87ab172a74b4 127 this->updatePaddle();
maxint 0:87ab172a74b4 128 this->ball.vSpeed.add(Vector(0, 0.1)); // add some gravity
maxint 0:87ab172a74b4 129 this->ball.update(); // update the ball position
maxint 0:87ab172a74b4 130
maxint 0:87ab172a74b4 131 this->checkCollision();
maxint 0:87ab172a74b4 132 //this->drawPaddle();
maxint 0:87ab172a74b4 133 //this->paddle.draw();
maxint 0:87ab172a74b4 134 this->paddle.redraw();
maxint 0:87ab172a74b4 135
maxint 0:87ab172a74b4 136 this->ball.redraw();
maxint 0:87ab172a74b4 137
maxint 0:87ab172a74b4 138 this->checkPwm();
maxint 0:87ab172a74b4 139 this->checkLives();
maxint 0:87ab172a74b4 140
maxint 0:87ab172a74b4 141 wait_ms(25);
maxint 0:87ab172a74b4 142 }
maxint 0:87ab172a74b4 143 else {
maxint 0:87ab172a74b4 144 double x, y, z;
maxint 0:87ab172a74b4 145 this->accel.getXYZ(x, y, z);
maxint 0:87ab172a74b4 146
maxint 0:87ab172a74b4 147 this->checkGraphReset();
maxint 0:87ab172a74b4 148 this->drawPoint(0, x);
maxint 0:87ab172a74b4 149 this->drawPoint(1, y);
maxint 0:87ab172a74b4 150 this->drawPoint(2, z);
maxint 0:87ab172a74b4 151 this->graphX++;
maxint 0:87ab172a74b4 152
maxint 0:87ab172a74b4 153 wait_ms(100);
maxint 0:87ab172a74b4 154 }
maxint 0:87ab172a74b4 155 }
maxint 0:87ab172a74b4 156
maxint 0:87ab172a74b4 157 int Game::checkTilt()
maxint 0:87ab172a74b4 158 { // move the paddle by tilting the board left or righr
maxint 0:87ab172a74b4 159 double x, y, z;
maxint 0:87ab172a74b4 160 //int nStart=this->tWait.read_ms();
maxint 0:87ab172a74b4 161 this->accel.getXYZ(x, y, z);
maxint 0:87ab172a74b4 162
maxint 0:87ab172a74b4 163 //printDouble((double)this->tWait.read_ms()-nStart, 10, 10);
maxint 0:87ab172a74b4 164 /*
maxint 0:87ab172a74b4 165 printDouble(x, 0, 0);
maxint 0:87ab172a74b4 166 char buf[256];
maxint 0:87ab172a74b4 167 sprintf(buf,"tilt:%0.1f", x);
maxint 0:87ab172a74b4 168 this->drawString(buf, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT / 2 + 4*DisplayN18::CHAR_HEIGHT );
maxint 0:87ab172a74b4 169 */
maxint 0:87ab172a74b4 170
maxint 0:87ab172a74b4 171 if(x<-0.1) return(-1);
maxint 0:87ab172a74b4 172 else if(x>0.1) return(1);
maxint 0:87ab172a74b4 173 else return(0);
maxint 0:87ab172a74b4 174 }
maxint 0:87ab172a74b4 175
maxint 0:87ab172a74b4 176 void Game::checkButtons()
maxint 0:87ab172a74b4 177 {
maxint 0:87ab172a74b4 178 if (!this->square.read())
maxint 0:87ab172a74b4 179 {
maxint 0:87ab172a74b4 180 this->mode = !this->mode;
maxint 0:87ab172a74b4 181
maxint 0:87ab172a74b4 182 //this->disp.clear();
maxint 0:87ab172a74b4 183 this->disp.clearScreen();
maxint 0:87ab172a74b4 184
maxint 0:87ab172a74b4 185 if (!this->mode)
maxint 0:87ab172a74b4 186 {
maxint 0:87ab172a74b4 187 this->graphX = 0;
maxint 0:87ab172a74b4 188
maxint 0:87ab172a74b4 189 this->drawAxes();
maxint 0:87ab172a74b4 190 }
maxint 0:87ab172a74b4 191
maxint 0:87ab172a74b4 192 this->led1.write(this->mode);
maxint 0:87ab172a74b4 193 this->led2.write(!this->mode);
maxint 0:87ab172a74b4 194 }
maxint 0:87ab172a74b4 195 else
maxint 0:87ab172a74b4 196 {
maxint 0:87ab172a74b4 197 bool isUp = !this->up.read();
maxint 0:87ab172a74b4 198 bool isDown = !this->down.read();
maxint 0:87ab172a74b4 199
maxint 0:87ab172a74b4 200 if (isUp && isDown) goto end;
maxint 0:87ab172a74b4 201 if (!isUp && !isDown) goto end;
maxint 0:87ab172a74b4 202
maxint 0:87ab172a74b4 203 if (isUp && this->lastUp) goto end;
maxint 0:87ab172a74b4 204 if (isDown && this->lastDown) goto end;
maxint 0:87ab172a74b4 205
maxint 0:87ab172a74b4 206 if (isUp)
maxint 0:87ab172a74b4 207 {
maxint 0:87ab172a74b4 208 this->ball.changeSpeed(true);
maxint 0:87ab172a74b4 209 }
maxint 0:87ab172a74b4 210 else if (isDown)
maxint 0:87ab172a74b4 211 {
maxint 0:87ab172a74b4 212 this->ball.changeSpeed(false);
maxint 0:87ab172a74b4 213 }
maxint 0:87ab172a74b4 214
maxint 0:87ab172a74b4 215 end:
maxint 0:87ab172a74b4 216 this->lastUp = isUp;
maxint 0:87ab172a74b4 217 this->lastDown = isDown;
maxint 0:87ab172a74b4 218 }
maxint 0:87ab172a74b4 219 }
maxint 0:87ab172a74b4 220
maxint 0:87ab172a74b4 221 void Game::drawString(const char* str, int y) {
maxint 0:87ab172a74b4 222 this->disp.drawString(font_ibm, WIDTH / 2 - CHAR_WIDTH * strlen(str) / 2, y, str);
maxint 0:87ab172a74b4 223 }
maxint 0:87ab172a74b4 224
maxint 0:87ab172a74b4 225 void Game::showSplashScreen() {
maxint 0:87ab172a74b4 226 this->drawString(Game::SPLASH_1, HEIGHT / 2 - CHAR_HEIGHT / 2);
maxint 0:87ab172a74b4 227 this->drawString(Game::SPLASH_2, HEIGHT / 2 + CHAR_HEIGHT / 2);
maxint 0:87ab172a74b4 228 this->drawString(Game::SPLASH_3, HEIGHT / 2 + CHAR_HEIGHT / 2 + 2*(8));
maxint 0:87ab172a74b4 229
maxint 0:87ab172a74b4 230 while (this->circle.read())
maxint 0:87ab172a74b4 231 {
maxint 0:87ab172a74b4 232 int i=this->checkTilt();
maxint 0:87ab172a74b4 233 char buf[256];
maxint 0:87ab172a74b4 234 sprintf(buf,"tilt:%d ", i);
maxint 0:87ab172a74b4 235 this->drawString(buf, HEIGHT / 2 - CHAR_HEIGHT / 2 + (4*CHAR_HEIGHT) );
maxint 0:87ab172a74b4 236
maxint 0:87ab172a74b4 237 wait_ms(1);
maxint 0:87ab172a74b4 238 }
maxint 0:87ab172a74b4 239
maxint 0:87ab172a74b4 240 this->disp.clearScreen();
maxint 0:87ab172a74b4 241 }
maxint 0:87ab172a74b4 242
maxint 0:87ab172a74b4 243
maxint 0:87ab172a74b4 244 void Game::updatePaddle() {
maxint 0:87ab172a74b4 245 if (!this->left.read()) // note: read is LOW (0) when button pressed
maxint 0:87ab172a74b4 246 {
maxint 0:87ab172a74b4 247 this->paddleX -= Game::PADDLE_SPEED;
maxint 0:87ab172a74b4 248 this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
maxint 0:87ab172a74b4 249 }
maxint 0:87ab172a74b4 250 else if (!this->right.read())
maxint 0:87ab172a74b4 251 {
maxint 0:87ab172a74b4 252 this->paddleX += Game::PADDLE_SPEED;
maxint 0:87ab172a74b4 253 this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
maxint 0:87ab172a74b4 254 }
maxint 0:87ab172a74b4 255 else
maxint 0:87ab172a74b4 256 {
maxint 0:87ab172a74b4 257 int i=this->checkTilt(); // don't call too often as this I2C is slow and will delay the game
maxint 0:87ab172a74b4 258 if(i>0)
maxint 0:87ab172a74b4 259 {
maxint 0:87ab172a74b4 260 this->paddleX += Game::PADDLE_SPEED;
maxint 0:87ab172a74b4 261 this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
maxint 0:87ab172a74b4 262 }
maxint 0:87ab172a74b4 263 else if(i<0)
maxint 0:87ab172a74b4 264 {
maxint 0:87ab172a74b4 265 this->paddleX -= Game::PADDLE_SPEED;
maxint 0:87ab172a74b4 266 this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
maxint 0:87ab172a74b4 267 }
maxint 0:87ab172a74b4 268 }
maxint 0:87ab172a74b4 269 }
maxint 0:87ab172a74b4 270
maxint 0:87ab172a74b4 271 void Game::checkCollision()
maxint 0:87ab172a74b4 272 {
maxint 0:87ab172a74b4 273 Rectangle rTop=Rectangle(0, -10, WIDTH, 0); // Rectangle(0, 0, WIDTH, 1); // top wall
maxint 0:87ab172a74b4 274 Rectangle rBottom=Rectangle(0, HEIGHT, WIDTH, HEIGHT+10); // Rectangle(0, HEIGHT, WIDTH, HEIGHT); // bottom gap
maxint 0:87ab172a74b4 275 Rectangle rLeft=Rectangle(-10, 0, 0, HEIGHT); // Rectangle(0, 0, 0, HEIGHT); // left wall
maxint 0:87ab172a74b4 276 Rectangle rRight=Rectangle(WIDTH, 0, WIDTH+10, HEIGHT); // Rectangle(WIDTH, 0, WIDTH, HEIGHT); // right wall
maxint 0:87ab172a74b4 277 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 278 Rectangle rPaddleLeft=Rectangle(paddle.pos.getX(), paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH/3, HEIGHT+10); // paddle left part
maxint 0:87ab172a74b4 279 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:87ab172a74b4 280
maxint 0:87ab172a74b4 281
maxint 0:87ab172a74b4 282 if (this->paddle.pos.getX() < 0)
maxint 0:87ab172a74b4 283 this->paddle.pos.setX(0);
maxint 0:87ab172a74b4 284 if (this->paddle.pos.getX() + Game::PADDLE_WIDTH > WIDTH)
maxint 0:87ab172a74b4 285 this->paddle.pos.setX(WIDTH - Game::PADDLE_WIDTH);
maxint 0:87ab172a74b4 286
maxint 0:87ab172a74b4 287
maxint 0:87ab172a74b4 288
maxint 0:87ab172a74b4 289 if(ball.collides(rTop) && this->ball.vSpeed.isUp()) // top wall
maxint 0:87ab172a74b4 290 {
maxint 0:87ab172a74b4 291 this->ball.Bounce(Vector(1,-1)); // bounce vertical
maxint 0:87ab172a74b4 292 this->pwmTicksLeft = Game::BOUNCE1_SOUND_TICKS;
maxint 0:87ab172a74b4 293 }
maxint 0:87ab172a74b4 294 if(ball.collides(rRight) && this->ball.vSpeed.isRight()) // right wall
maxint 0:87ab172a74b4 295 {
maxint 0:87ab172a74b4 296 this->ball.Bounce(Vector(-1,1)); // bounce horizontal
maxint 0:87ab172a74b4 297 this->pwmTicksLeft = Game::BOUNCE1_SOUND_TICKS;
maxint 0:87ab172a74b4 298 }
maxint 0:87ab172a74b4 299 if(ball.collides(rLeft) && this->ball.vSpeed.isLeft()) // left wall
maxint 0:87ab172a74b4 300 {
maxint 0:87ab172a74b4 301 this->ball.Bounce(Vector(-1,1)); // bounce horizontal
maxint 0:87ab172a74b4 302 this->pwmTicksLeft = Game::BOUNCE1_SOUND_TICKS;
maxint 0:87ab172a74b4 303 }
maxint 0:87ab172a74b4 304 if(ball.collides(rPaddle) && this->ball.vSpeed.isDown()) // paddle
maxint 0:87ab172a74b4 305 {
maxint 0:87ab172a74b4 306 //this->ball.Bounce(Vector(1,-1)); // bounce vertical at same speed
maxint 0:87ab172a74b4 307 this->ball.Bounce(Vector(1,-1.1)); // bounce from paddle at higher speed
maxint 0:87ab172a74b4 308 if(ball.collides(rPaddleLeft)) ball.vSpeed.add(Vector(-1,0));
maxint 0:87ab172a74b4 309 if(ball.collides(rPaddleRight)) ball.vSpeed.add(Vector(1,0));
maxint 0:87ab172a74b4 310
maxint 0:87ab172a74b4 311 this->pwmTicksLeft = Game::BOUNCE2_SOUND_TICKS;
maxint 0:87ab172a74b4 312 }
maxint 0:87ab172a74b4 313 if(ball.collides(rBottom) && this->ball.vSpeed.isDown()) // bottom gap
maxint 0:87ab172a74b4 314 {
maxint 0:87ab172a74b4 315 ball.clearPrev();
maxint 0:87ab172a74b4 316 this->initializeBall();
maxint 0:87ab172a74b4 317 this->lives--;
maxint 0:87ab172a74b4 318 }
maxint 0:87ab172a74b4 319
maxint 0:87ab172a74b4 320 }
maxint 0:87ab172a74b4 321
maxint 0:87ab172a74b4 322 void Game::checkPwm() {
maxint 0:87ab172a74b4 323 if (this->pwmTicksLeft == 0) {
maxint 0:87ab172a74b4 324 this->pwm.write(0.0);
maxint 0:87ab172a74b4 325 }
maxint 0:87ab172a74b4 326 else {
maxint 0:87ab172a74b4 327 this->pwmTicksLeft--;
maxint 0:87ab172a74b4 328 this->pwm.write(0.5);
maxint 0:87ab172a74b4 329 }
maxint 0:87ab172a74b4 330 }
maxint 0:87ab172a74b4 331
maxint 0:87ab172a74b4 332 void Game::Printf(int x, int y, const char *szFormat, ...)
maxint 0:87ab172a74b4 333 {
maxint 0:87ab172a74b4 334 char szBuffer[256];
maxint 0:87ab172a74b4 335 va_list args;
maxint 0:87ab172a74b4 336
maxint 0:87ab172a74b4 337 va_start(args, szFormat);
maxint 0:87ab172a74b4 338 vsprintf(szBuffer, szFormat, args);
maxint 0:87ab172a74b4 339 va_end(args);
maxint 0:87ab172a74b4 340 this->disp.drawString(font_ibm, x, y, szBuffer);
maxint 0:87ab172a74b4 341 }
maxint 0:87ab172a74b4 342
maxint 0:87ab172a74b4 343
maxint 0:87ab172a74b4 344 void Game::checkLives() {
maxint 0:87ab172a74b4 345 if (this->lives == 0) {
maxint 0:87ab172a74b4 346 this->disp.clearScreen();
maxint 0:87ab172a74b4 347
maxint 0:87ab172a74b4 348 this->drawString(Game::LOSE_1, HEIGHT / 2 - CHAR_HEIGHT);
maxint 0:87ab172a74b4 349 this->drawString(Game::LOSE_2, HEIGHT / 2);
maxint 0:87ab172a74b4 350
maxint 0:87ab172a74b4 351 while (this->circle.read())
maxint 0:87ab172a74b4 352 wait_ms(1);
maxint 0:87ab172a74b4 353
maxint 0:87ab172a74b4 354 this->initialize();
maxint 0:87ab172a74b4 355 }
maxint 0:87ab172a74b4 356 else {
maxint 0:87ab172a74b4 357 this->Printf(0, 0, "%d", this->lives);
maxint 0:87ab172a74b4 358 }
maxint 0:87ab172a74b4 359 }