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
Added more balls

Who changed what in which revision?

UserRevisionLine numberNew contents of line
maxint 0:87ab172a74b4 1 #include "Ball.h"
maxint 0:87ab172a74b4 2
maxint 2:d4de5a5866fe 3 Ball::Ball() : vSpeed()
maxint 2:d4de5a5866fe 4 { // constructor
maxint 2:d4de5a5866fe 5 }
maxint 2:d4de5a5866fe 6
maxint 1:c1ee4c699517 7 Ball::Ball(LCD_ST7735* pDisp) : vSpeed()
maxint 0:87ab172a74b4 8 { // constructor
maxint 1:c1ee4c699517 9 this->pDisp=pDisp;
maxint 2:d4de5a5866fe 10 this->fActive=false;
maxint 0:87ab172a74b4 11 }
maxint 0:87ab172a74b4 12
maxint 1:c1ee4c699517 13 uint16_t Ball::dimmedColor(uint16_t uColor)
maxint 0:87ab172a74b4 14 {
maxint 1:c1ee4c699517 15 uint16_t r, g, b;
maxint 1:c1ee4c699517 16
maxint 1:c1ee4c699517 17 r=(uColor >> 11) <<3;
maxint 1:c1ee4c699517 18 g=((uColor >> 5) & 0x3F) <<2;
maxint 1:c1ee4c699517 19 b=(uColor & 0x1F) << 3;
maxint 1:c1ee4c699517 20 r=r*2/3;
maxint 1:c1ee4c699517 21 g=g*2/3;
maxint 1:c1ee4c699517 22 b=b*2/3;
maxint 1:c1ee4c699517 23 // r=r/2;
maxint 1:c1ee4c699517 24 // g=g/2;
maxint 1:c1ee4c699517 25 // b=b/2;
maxint 1:c1ee4c699517 26
maxint 1:c1ee4c699517 27 return(Color565::fromRGB((uint16_t)r,(uint16_t)g,(uint16_t)b));
maxint 1:c1ee4c699517 28 }
maxint 1:c1ee4c699517 29
maxint 1:c1ee4c699517 30 void Ball::initialize(int nX, int nY, int nR, uint16_t uColor)
maxint 1:c1ee4c699517 31 {
maxint 0:87ab172a74b4 32 this->pos.set(nX, nY);
maxint 1:c1ee4c699517 33 this->nRadius=nR;
maxint 1:c1ee4c699517 34 this->uColor=uColor;
maxint 1:c1ee4c699517 35 this->uColorHigh=uColor;
maxint 1:c1ee4c699517 36 this->uColorMid=dimmedColor(uColorHigh);
maxint 1:c1ee4c699517 37 this->uColorLow=dimmedColor(uColorMid);
maxint 1:c1ee4c699517 38
maxint 0:87ab172a74b4 39 }
maxint 0:87ab172a74b4 40
maxint 0:87ab172a74b4 41 void Ball::setSpeed(int X, int Y)
maxint 0:87ab172a74b4 42 {
maxint 0:87ab172a74b4 43 this->vSpeed.set(X, Y);
maxint 0:87ab172a74b4 44 }
maxint 0:87ab172a74b4 45
maxint 0:87ab172a74b4 46 void Ball::changeSpeed(bool fUp)
maxint 0:87ab172a74b4 47 {
maxint 0:87ab172a74b4 48 if(fUp)
maxint 0:87ab172a74b4 49 {
maxint 0:87ab172a74b4 50 if(this->vSpeed.getSize()<=4.0) this->vSpeed.add(1.0);
maxint 0:87ab172a74b4 51 }
maxint 0:87ab172a74b4 52 else
maxint 0:87ab172a74b4 53 {
maxint 2:d4de5a5866fe 54 if(this->vSpeed.getSize()>=1.0)
maxint 2:d4de5a5866fe 55 this->vSpeed.add(-1.0);
maxint 2:d4de5a5866fe 56 else // TODO: added code below to allow zero speed pause of ball
maxint 2:d4de5a5866fe 57 this->vSpeed.set(0,0);
maxint 0:87ab172a74b4 58 }
maxint 0:87ab172a74b4 59 }
maxint 0:87ab172a74b4 60
maxint 1:c1ee4c699517 61 void Ball::unmove()
maxint 1:c1ee4c699517 62 { // move back to previous position
maxint 1:c1ee4c699517 63 pos.set(pos.getPrev());
maxint 1:c1ee4c699517 64 }
maxint 1:c1ee4c699517 65
maxint 0:87ab172a74b4 66 void Ball::update()
maxint 0:87ab172a74b4 67 {
maxint 0:87ab172a74b4 68 this->pos.move(this->vSpeed);
maxint 0:87ab172a74b4 69 }
maxint 0:87ab172a74b4 70
maxint 0:87ab172a74b4 71 Circle Ball::getBoundingCircle()
maxint 0:87ab172a74b4 72 {
maxint 1:c1ee4c699517 73 return(Circle(this->pos.getX(), this->pos.getY(), this->nRadius));
maxint 0:87ab172a74b4 74 }
maxint 0:87ab172a74b4 75
maxint 0:87ab172a74b4 76 bool Ball::collides(Rectangle r)
maxint 0:87ab172a74b4 77 {
maxint 1:c1ee4c699517 78 Circle cBall=this->getBoundingCircle();
maxint 1:c1ee4c699517 79 Rectangle rBall=cBall.getBoundingRectangle();
maxint 0:87ab172a74b4 80
maxint 0:87ab172a74b4 81 /*
maxint 0:87ab172a74b4 82 char szBuffer[256];
maxint 0:87ab172a74b4 83 sprintf(szBuffer, "c:%d,%d ", cBall.getX(), cBall.getY());
maxint 1:c1ee4c699517 84 this->pDisp->drawString(font_oem, 0, 0, szBuffer);
maxint 0:87ab172a74b4 85 */
maxint 0:87ab172a74b4 86 return(rBall.collides(r));
maxint 0:87ab172a74b4 87 }
maxint 0:87ab172a74b4 88
maxint 0:87ab172a74b4 89 void Ball::Bounce(Vector vBounce)
maxint 0:87ab172a74b4 90 { // change the direction in a certain direction
maxint 1:c1ee4c699517 91 this->unmove(); // undo move to pre-bouncing position to avoid drawing on colliding position
maxint 1:c1ee4c699517 92
maxint 0:87ab172a74b4 93 this->vSpeed.multiply(vBounce);
maxint 0:87ab172a74b4 94
maxint 0:87ab172a74b4 95 // check speed w/max
maxint 0:87ab172a74b4 96 if(this->vSpeed.y>5.0) this->vSpeed.y=5;
maxint 0:87ab172a74b4 97 }
maxint 0:87ab172a74b4 98
maxint 0:87ab172a74b4 99
maxint 0:87ab172a74b4 100
maxint 0:87ab172a74b4 101 void Ball::clear()
maxint 0:87ab172a74b4 102 {
maxint 0:87ab172a74b4 103 Point p=pos.getCur();
maxint 1:c1ee4c699517 104 this->pDisp->fillCircle(p.getX(),p.getY(), this->nRadius, Color565::Black, Color565::Black);
maxint 0:87ab172a74b4 105 }
maxint 0:87ab172a74b4 106
maxint 0:87ab172a74b4 107 void Ball::clearPrev()
maxint 0:87ab172a74b4 108 {
maxint 0:87ab172a74b4 109 Point p=pos.getPrev();
maxint 1:c1ee4c699517 110 this->pDisp->fillCircle(p.getX(),p.getY(), this->nRadius, Color565::Black, Color565::Black);
maxint 0:87ab172a74b4 111 }
maxint 0:87ab172a74b4 112
maxint 0:87ab172a74b4 113
maxint 0:87ab172a74b4 114 void Ball::draw()
maxint 0:87ab172a74b4 115 { // render the object on the screen, based on its current position
maxint 0:87ab172a74b4 116 Point p=pos.getCur();
maxint 1:c1ee4c699517 117 if(this->nRadius>3)
maxint 0:87ab172a74b4 118 {
maxint 1:c1ee4c699517 119 this->pDisp->fillCircle(p.getX(), p.getY(), this->nRadius, this->uColorLow, this->uColorLow);
maxint 1:c1ee4c699517 120 this->pDisp->fillCircle(p.getX()-this->nRadius/3, p.getY()-this->nRadius/3, this->nRadius/2, this->uColorMid, this->uColorMid);
maxint 1:c1ee4c699517 121 this->pDisp->setPixel(p.getX()-this->nRadius/2, p.getY()-this->nRadius/2, this->uColorHigh);
maxint 0:87ab172a74b4 122 }
maxint 0:87ab172a74b4 123 else
maxint 1:c1ee4c699517 124 this->pDisp->fillCircle(p.getX(), p.getY(), this->nRadius, this->uColorMid, this->uColorMid);
maxint 0:87ab172a74b4 125 }
maxint 0:87ab172a74b4 126
maxint 0:87ab172a74b4 127 void Ball::redraw()
maxint 0:87ab172a74b4 128 { // redraw the ball if its position has changed
maxint 0:87ab172a74b4 129 if(pos.hasChanged())
maxint 0:87ab172a74b4 130 {
maxint 0:87ab172a74b4 131 clearPrev();
maxint 0:87ab172a74b4 132 draw();
maxint 0:87ab172a74b4 133 }
maxint 0:87ab172a74b4 134 }