Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: LCD_ST7735 MusicEngine RETRO_BallsAndThings mbed
Diff: Game.cpp
- Revision:
- 2:d4de5a5866fe
- Parent:
- 1:c1ee4c699517
- Child:
- 3:ca8b21da67dc
diff -r c1ee4c699517 -r d4de5a5866fe Game.cpp
--- a/Game.cpp Sun Feb 01 16:21:24 2015 +0000
+++ b/Game.cpp Tue Feb 03 19:02:27 2015 +0000
@@ -2,9 +2,9 @@
const char* Game::LOSE_1 = "You lose.";
const char* Game::LOSE_2 = "Press ship to restart.";
-const char* Game::SPLASH_1 = "Press ship to start.";
-const char* Game::SPLASH_2 = "Press robot to switch.";
-const char* Game::SPLASH_3 = "mod:Tilt by Maxint.";
+const char* Game::SPLASH_1 = "-*- Balls and paddle -*-";
+const char* Game::SPLASH_2 = "Press ship to start.";
+const char* Game::SPLASH_3 = "Made by Maxint";
#define WHITE Color565::White
@@ -21,7 +21,7 @@
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),
- 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, &disp), vGravity(0, 0.1), ball(&disp), paddle(&disp)
+ 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)
{
this->disp.setOrientation(LCD_ST7735::Rotate270, false);
this->disp.setForegroundColor(WHITE);
@@ -34,10 +34,16 @@
this->lastDown = false;
this->mode = true;
- this->initialize();
+
+ //this->aBalls[2]={ Ball(&disp), Ball(&disp) };
+ for(int i=0; i<NUM_BALLS; i++)
+ this->aBalls[i]=Ball(&(this->disp));
+
+ //this->initialize();
}
-void Game::printDouble(double value, int x, int y) {
+void Game::printDouble(double value, int x, int y)
+{
char buffer[10];
int len = sprintf(buffer, "%.1f ", value);
@@ -48,33 +54,145 @@
{
this->disp.clearScreen();
- this->initializeBall(); // start first ball
+// this->initializeBall(); // start first ball
+// this->initializeBalls(); // start first ball
+
+ this->setNoBalls(); // reset all balls
+ this->newBall(); // start first ball
this->initializePaddle();
+ //this->paddle.draw();
+
// this->paddleX = WIDTH / 2 - Game::PADDLE_WIDTH / 2;
- this->pwmTicksLeft = 0;
+ this->snd.reset();
this->nLives = 4;
this->nScore = 0;
- this->pwm.period_ms(1);
- this->pwm.write(0.00);
-
this->tWait.start(); // start the timer
}
-
+
+
+void Game::initializePaddle()
+{
+ this->paddle.initialize(WIDTH / 2 - Game::PADDLE_WIDTH/2, HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT);
+ this->paddle.draw();
+}
+
+
+void Game::updatePaddle()
+{
+ if (!this->left.read()) // note: read is LOW (0) when button pressed
+ this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
+ else if (!this->right.read())
+ this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
+ else
+ {
+ int i=this->checkTilt();
+ if(i>0)
+ this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
+ else if(i<0)
+ this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
+ else if(this->paddle.hasChanged())
+ paddle.move(Vector(0, 0)); // move to same place to restrict redraws
+ }
+}
+
+
+
+
+/*
void Game::initializeBall()
{
this->ball.initialize(WIDTH / 2 - Game::BALL_RADIUS, HEIGHT / 4 - Game::BALL_RADIUS, Game::BALL_RADIUS, Color565::fromRGB(0xFF, 0x33, 0x33));
this->ball.setSpeed(rand() % 2 ? 1 : -1, rand() % 2 ? 1 : -1);
}
+*/
-void Game::initializePaddle()
+/*
+void Game::initializeBalls()
+{
+ for(int i=0; i<NUM_BALLS; i++)
+ {
+ 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));
+ //float ftRandX=rand() % 2 ? 1 : -1;
+ float ftRandX=((rand() % 20) - 10)/10 ;
+ float ftRandY=rand() % 2 ? 1 : -1;
+ this->aBalls[i].setSpeed(ftRandX, ftRandY);
+ }
+}
+*/
+
+void Game::setNoBalls()
{
- this->paddle.initialize(WIDTH / 2 - Game::PADDLE_WIDTH/2, HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT);
+ for(int i=0; i<NUM_BALLS; i++)
+ this->aBalls[i].fActive=false;
+}
+
+void Game::newBall()
+{
+ for(int i=0; i<NUM_BALLS; i++)
+ {
+ if(this->aBalls[i].fActive)
+ continue;
+ else
+ {
+ 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));
+ //float ftRandX=rand() % 2 ? 1 : -1;
+ //float ftRandY=rand() % 2 ? 1 : -1;
+ float ftRandX=((rand() % 20) - 10)/5.0;
+ float ftRandY=((rand() % 10) - 10)/5.0;
+ //this->aBalls[i].setSpeed(ftRandX, ftRandY);
+ this->aBalls[i].vSpeed.set(ftRandX, ftRandY);
+ this->aBalls[i].fActive=true;
+ break;
+ }
+ }
}
-void Game::tick() {
+void Game::updateBalls()
+{
+ for(int i=0; i<NUM_BALLS; i++)
+ {
+ if(!this->aBalls[i].fActive)
+ continue;
+
+ this->aBalls[i].update(); // update the ball position
+
+ // add downward gravity
+ 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
+ this->aBalls[i].vSpeed.add(this->vGravity); // add some gravity
+
+ }
+}
+
+void Game::redrawBalls()
+{
+ for(int i=0; i<NUM_BALLS; i++)
+ {
+ if(!this->aBalls[i].fActive)
+ continue;
+ this->aBalls[i].redraw(); // update the ball position
+ }
+}
+
+int Game::countBalls()
+{
+ int nResult=0;
+ for(int i=0; i<NUM_BALLS; i++)
+ {
+ if(this->aBalls[i].fActive)
+ nResult++;
+ }
+ return(nResult);
+}
+
+
+
+
+
+void Game::tick()
+{
this->checkButtons();
if (this->mode) {
@@ -85,15 +203,26 @@
this->tWait.reset();
}
*/
+
+/*
+ if(this->ball.vSpeed.getSize() != 0) // TODO: added if statement to allow zero speed pause of ball
+ this->ball.vSpeed.add(this->vGravity); // add some gravity
+ //this->ball.vSpeed.add(Vector(0, 0.1)); // add some gravity
+ this->ball.update(); // update the ball position
+*/
+
+ this->updateBalls(); // update the ball positions
+
this->updatePaddle();
- this->ball.vSpeed.add(Vector(0, 0.1)); // add some gravity
- this->ball.update(); // update the ball position
- this->checkCollision();
+// this->checkCollision();
+ this->checkPaddle();
+ this->checkBallsCollision();
+// this->ball.redraw();
+ this->redrawBalls();
this->paddle.redraw();
- this->ball.redraw();
- this->checkPwm();
+ this->snd.checkPwm();
//this->checkScore();
this->checkLives();
@@ -192,25 +321,101 @@
wait_ms(1);
}
- this->disp.clearScreen();
+ //this->disp.clearScreen();
+ this->initialize(); // start a new game
}
-void Game::updatePaddle() {
- if (!this->left.read()) // note: read is LOW (0) when button pressed
- this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
- else if (!this->right.read())
- this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
- else
+
+void Game::checkBallsCollision()
+{
+ Rectangle rTop=Rectangle(0, -10, WIDTH, 0); // Rectangle(0, 0, WIDTH, 1); // top wall
+ Rectangle rBottom=Rectangle(0, HEIGHT, WIDTH, HEIGHT+10); // Rectangle(0, HEIGHT, WIDTH, HEIGHT); // bottom gap
+ Rectangle rLeft=Rectangle(-10, 0, 0, HEIGHT); // Rectangle(0, 0, 0, HEIGHT); // left wall
+ Rectangle rRight=Rectangle(WIDTH, 0, WIDTH+10, HEIGHT); // Rectangle(WIDTH, 0, WIDTH, HEIGHT); // right wall
+ 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
+ Rectangle rPaddleLeft=Rectangle(paddle.pos.getX(), paddle.pos.getY(), paddle.pos.getX() + Game::PADDLE_WIDTH/3, HEIGHT+10); // paddle left part
+ 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
+ //Rectangle rScreen=Rectangle(0,0, WIDTH, HEIGHT); // screen boundary
+
+ Ball* pBall;
+ for(int i=0; i<NUM_BALLS; i++)
{
- int i=this->checkTilt(); // don't call too often as this I2C is slow and will delay the game
- if(i>0)
- this->paddle.move(Vector(Game::PADDLE_SPEED, 0));
- else if(i<0)
- this->paddle.move(Vector(-1 * Game::PADDLE_SPEED, 0));
+ if(!this->aBalls[i].fActive)
+ continue;
+
+ pBall=&(this->aBalls[i]);
+
+ if(pBall->collides(rTop) && pBall->vSpeed.isUp()) // top wall
+ {
+ pBall->Bounce(Vector(1,-1)); // bounce vertical
+ this->snd.beepShort();
+ }
+ if(pBall->collides(rRight) && pBall->vSpeed.isRight()) // right wall
+ {
+ pBall->Bounce(Vector(-1,1)); // bounce horizontal
+ this->snd.beepShort();
+ }
+ if(pBall->collides(rLeft) && pBall->vSpeed.isLeft()) // left wall
+ {
+ pBall->Bounce(Vector(-1,1)); // bounce horizontal
+ this->snd.beepShort();
+ }
+ if(pBall->collides(rPaddle) && pBall->vSpeed.isDown()) // paddle
+ {
+ if(pBall->collides(rPaddleLeft)) pBall->vSpeed.add(Vector(-1,0)); // left side of paddle has bias to the left
+ if(pBall->collides(rPaddleRight)) pBall->vSpeed.add(Vector(1,0)); // right side of paddle has bias to the right
+
+
+ // increase the speed of the ball when hitting the paddle to increase difficulty
+ //pBall->Bounce(Vector(1,-1)); // bounce vertical at same speed
+ float ftSpeedMax=3.0;
+ if(this->nScore>50)
+ ftSpeedMax=5.0;
+ if(this->nScore>100)
+ ftSpeedMax=10.0;
+ if(this->nScore>150)
+ ftSpeedMax=999.0;
+ if(pBall->vSpeed.getSize()<ftSpeedMax) // TODO: added if statement to allow zero speed pause of ball
+ pBall->Bounce(Vector(1,-1.02)); // bounce from paddle at higher speed
+ else
+ pBall->Bounce(Vector(1,-1)); // bounce vertical at same speed
+
+ this->snd.beepLong();
+ this->nScore++;
+ this->printf(100, 0, "Score: %d ", this->nScore);
+
+ if(this->nScore>0 && this->nScore%10==0)
+ {
+ this->newBall();
+ this->nLives++;
+ }
+ }
+ if(pBall->collides(rBottom) && pBall->vSpeed.isDown()) // bottom gap
+ {
+ pBall->clearPrev(); // clear the ball from its previous position
+ pBall->clear(); // clear the ball from its current position
+ pBall->vSpeed.set(0,0);
+ pBall->fActive=false;
+ this->nLives--;
+ //this->initializeBall(); // start a new ball
+ if(countBalls()==0)
+ {
+ this->newBall(); // start a new ball
+ this->snd.beepLow();
+ }
+ }
}
}
+void Game::checkPaddle()
+{
+ Rectangle rScreen=Rectangle(0,0, WIDTH, HEIGHT); // screen boundary
+
+ this->paddle.checkBoundary(rScreen);
+}
+
+/*
void Game::checkCollision()
{
Rectangle rTop=Rectangle(0, -10, WIDTH, 0); // Rectangle(0, 0, WIDTH, 1); // top wall
@@ -222,38 +427,32 @@
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
Rectangle rScreen=Rectangle(0,0, WIDTH, HEIGHT); // screen boundary
-/*
- if (this->paddle.pos.getX() < 0)
- this->paddle.pos.setX(0);
- if (this->paddle.pos.getX() + Game::PADDLE_WIDTH > WIDTH)
- this->paddle.pos.setX(WIDTH - Game::PADDLE_WIDTH);
-*/
this->paddle.checkBoundary(rScreen);
if(ball.collides(rTop) && this->ball.vSpeed.isUp()) // top wall
{
this->ball.Bounce(Vector(1,-1)); // bounce vertical
- this->pwmTicksLeft = Game::BOUNCE1_SOUND_TICKS;
+ this->snd.beepShort();
}
if(ball.collides(rRight) && this->ball.vSpeed.isRight()) // right wall
{
this->ball.Bounce(Vector(-1,1)); // bounce horizontal
- this->pwmTicksLeft = Game::BOUNCE1_SOUND_TICKS;
+ this->snd.beepShort();
}
if(ball.collides(rLeft) && this->ball.vSpeed.isLeft()) // left wall
{
this->ball.Bounce(Vector(-1,1)); // bounce horizontal
- this->pwmTicksLeft = Game::BOUNCE1_SOUND_TICKS;
+ this->snd.beepShort();
}
if(ball.collides(rPaddle) && this->ball.vSpeed.isDown()) // paddle
{
if(ball.collides(rPaddleLeft)) ball.vSpeed.add(Vector(-1,0)); // left side of paddle has bias to the left
if(ball.collides(rPaddleRight)) ball.vSpeed.add(Vector(1,0)); // right side of paddle has bias to the right
- //this->ball.Bounce(Vector(1,-1)); // bounce vertical at same speed
- ball.Bounce(Vector(1,-1.1)); // bounce from paddle at higher speed
+ ball.Bounce(Vector(1,-1)); // bounce vertical at same speed
+ //ball.Bounce(Vector(1,-1.05)); // bounce from paddle at higher speed
- this->pwmTicksLeft = Game::BOUNCE2_SOUND_TICKS;
+ this->snd.beepLong();
this->nScore++;
this->printf(100, 0, "Score: %d ", this->nScore);
}
@@ -264,16 +463,7 @@
this->initializeBall(); // start a new ball
}
}
-
-void Game::checkPwm() {
- if (this->pwmTicksLeft == 0) {
- this->pwm.write(0.0);
- }
- else {
- this->pwmTicksLeft--;
- this->pwm.write(0.5);
- }
-}
+*/
void Game::printf(int x, int y, const char *szFormat, ...)
{
@@ -294,6 +484,7 @@
this->drawString(Game::LOSE_1, HEIGHT / 2 - CHAR_HEIGHT);
this->drawString(Game::LOSE_2, HEIGHT / 2);
+ this->snd.playTune();
while (this->circle.read())
wait_ms(1);