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:
Sun Feb 01 16:21:24 2015 +0000
Revision:
1:c1ee4c699517
Parent:
0:87ab172a74b4
Child:
2:d4de5a5866fe
moved graph to accelerometer class

Who changed what in which revision?

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