Some random attempts at programming the retro console

Dependencies:   LCD_ST7735 mbed

Fork of RETRO_Pong_Mod by G. Andrew Duthie

Committer:
loop
Date:
Sat Feb 28 17:39:08 2015 +0000
Revision:
10:ba2dea5fffd1
Parent:
9:5c4a3e89a713
Remove some unused stuff

Who changed what in which revision?

UserRevisionLine numberNew contents of line
devhammer 3:2f09c90a732d 1 // Updated version of the official firmware for the Outrageous Circuits RETRO
devhammer 3:2f09c90a732d 2 // Modified by G. Andrew Duthie (devhammer)
devhammer 3:2f09c90a732d 3 // Changes:
devhammer 3:2f09c90a732d 4 // - Added sounds for all ball bounces
devhammer 3:2f09c90a732d 5 // - Changed ball from square to circle
devhammer 3:2f09c90a732d 6 // - Adjusted collision detection to add ball speed every 10 paddle hits
devhammer 3:2f09c90a732d 7 // - Added scoring
devhammer 3:2f09c90a732d 8 // - Added mute function (not fully implemented...needs to be set up on a button).
loop 7:c0f12f624832 9 // Further mods buy loop (loop23)
loop 7:c0f12f624832 10 // Changes:
loop 7:c0f12f624832 11 // - Removed useless stuff
loop 7:c0f12f624832 12 // - Read accelerometer in game
devhammer 3:2f09c90a732d 13
john_ghielec 1:cd8a3926f263 14 #include "Game.h"
john_ghielec 1:cd8a3926f263 15
john_ghielec 1:cd8a3926f263 16 const char* Game::LOSE_1 = "You lose.";
john_ghielec 1:cd8a3926f263 17 const char* Game::LOSE_2 = "Press ship to restart.";
john_ghielec 2:6ab46f2e851a 18 const char* Game::SPLASH_1 = "Press ship to start.";
john_ghielec 2:6ab46f2e851a 19 const char* Game::SPLASH_2 = "Press robot to switch.";
devhammer 3:2f09c90a732d 20 const char* Game::LIVES = "Lives: ";
devhammer 3:2f09c90a732d 21 const char* Game::SCORE = "Score: ";
john_ghielec 1:cd8a3926f263 22
loop 7:c0f12f624832 23 Game::Game(): left(P0_14, PullUp),
loop 7:c0f12f624832 24 right(P0_11, PullUp),
loop 7:c0f12f624832 25 down(P0_12, PullUp),
loop 7:c0f12f624832 26 up(P0_13, PullUp),
loop 7:c0f12f624832 27 square(P0_16, PullUp),
loop 7:c0f12f624832 28 circle(P0_1, PullUp),
loop 7:c0f12f624832 29 led1(P0_9),
loop 7:c0f12f624832 30 led2(P0_8),
loop 7:c0f12f624832 31 pwm(P0_18),
loop 7:c0f12f624832 32 ain(P0_15),
loop 7:c0f12f624832 33 i2c(P0_5, P0_4),
loop 9:5c4a3e89a713 34 disp(P0_19, P0_20, P0_7, P0_21, P0_22, P1_15, P0_2, LCD_ST7735::RGB) {
john_ghielec 1:cd8a3926f263 35 srand(this->ain.read_u16());
john_ghielec 1:cd8a3926f263 36
john_ghielec 2:6ab46f2e851a 37 this->lastUp = false;
john_ghielec 2:6ab46f2e851a 38 this->lastDown = false;
loop 9:5c4a3e89a713 39 this->cCol = 0;
john_ghielec 2:6ab46f2e851a 40
john_ghielec 2:6ab46f2e851a 41 this->i2c.frequency(400);
john_ghielec 2:6ab46f2e851a 42 this->writeRegister(0x2A, 0x01);
john_ghielec 2:6ab46f2e851a 43
loop 7:c0f12f624832 44 this->colors[0] = Color565::Red;
loop 7:c0f12f624832 45 this->colors[1] = Color565::Green;
loop 7:c0f12f624832 46 this->colors[2] = Color565::Blue;
john_ghielec 1:cd8a3926f263 47 this->initialize();
john_ghielec 1:cd8a3926f263 48 }
john_ghielec 1:cd8a3926f263 49
john_ghielec 2:6ab46f2e851a 50 void Game::readRegisters(char address, char* buffer, int len) {
john_ghielec 2:6ab46f2e851a 51 this->i2c.write(Game::I2C_ADDR, &address, 1, true);
john_ghielec 2:6ab46f2e851a 52 this->i2c.read(Game::I2C_ADDR | 1, buffer, len);
john_ghielec 2:6ab46f2e851a 53 }
john_ghielec 2:6ab46f2e851a 54
john_ghielec 2:6ab46f2e851a 55 int Game::writeRegister(char address, char value) {
john_ghielec 2:6ab46f2e851a 56 char buffer[2] = { address, value };
john_ghielec 2:6ab46f2e851a 57
john_ghielec 2:6ab46f2e851a 58 return this->i2c.write(Game::I2C_ADDR, buffer, 2);
john_ghielec 2:6ab46f2e851a 59 }
john_ghielec 2:6ab46f2e851a 60
john_ghielec 2:6ab46f2e851a 61 double Game::convert(char* buffer) {
loop 9:5c4a3e89a713 62 int val = ((buffer[0] << 2) | (buffer[1] >> 6));
john_ghielec 2:6ab46f2e851a 63
loop 9:5c4a3e89a713 64 if (val > 511)
loop 9:5c4a3e89a713 65 val -= 1024;
john_ghielec 2:6ab46f2e851a 66
john_ghielec 2:6ab46f2e851a 67 return val / 512.0;
john_ghielec 2:6ab46f2e851a 68 }
john_ghielec 2:6ab46f2e851a 69
loop 9:5c4a3e89a713 70 void Game::getXY(float& x, float& y) {
loop 7:c0f12f624832 71 char buffer[4];
loop 7:c0f12f624832 72 this->readRegisters(0x01, buffer, 4);
loop 7:c0f12f624832 73 x = this->convert(buffer);
loop 7:c0f12f624832 74 y = this->convert(buffer + 2);
loop 7:c0f12f624832 75 }
loop 7:c0f12f624832 76
john_ghielec 2:6ab46f2e851a 77 void Game::printDouble(double value, int x, int y) {
john_ghielec 2:6ab46f2e851a 78 char buffer[10];
john_ghielec 2:6ab46f2e851a 79 int len = sprintf(buffer, "%.1f", value);
loop 7:c0f12f624832 80 this->disp.drawString(font_ibm, x, y, buffer);
john_ghielec 2:6ab46f2e851a 81 }
john_ghielec 2:6ab46f2e851a 82
loop 8:c63981a45c95 83 void Game::initialize() {
loop 9:5c4a3e89a713 84 this->disp.setOrientation(LCD_ST7735::Rotate270, false);
loop 9:5c4a3e89a713 85 this->disp.clearScreen();
john_ghielec 1:cd8a3926f263 86 this->initializeBall();
john_ghielec 1:cd8a3926f263 87 this->pwmTicksLeft = 0;
john_ghielec 1:cd8a3926f263 88 this->lives = 4;
devhammer 3:2f09c90a732d 89 this->score = 0;
loop 7:c0f12f624832 90 this->muted = false;
loop 9:5c4a3e89a713 91 this->pwm.period(0.3);
loop 9:5c4a3e89a713 92 this->pwm.write(0.00);
john_ghielec 1:cd8a3926f263 93 }
john_ghielec 1:cd8a3926f263 94
john_ghielec 1:cd8a3926f263 95 void Game::initializeBall() {
loop 7:c0f12f624832 96 this->ballX = disp.getWidth() / 2 - Game::BALL_RADIUS;
loop 7:c0f12f624832 97 this->ballY = disp.getHeight() / 4 - Game::BALL_RADIUS;
loop 9:5c4a3e89a713 98 this->ballSpeedX = 1.0f;
loop 9:5c4a3e89a713 99 this->ballSpeedY = 1.0f;
loop 9:5c4a3e89a713 100 this->ballAccelX = 0.0f;
loop 9:5c4a3e89a713 101 this->ballAccelY = 0.0f;
john_ghielec 2:6ab46f2e851a 102 }
john_ghielec 2:6ab46f2e851a 103
loop 5:8a26ad9d9ea1 104 void Game::readAccel() {
loop 9:5c4a3e89a713 105 float x, y;
loop 7:c0f12f624832 106 this->getXY(x, y);
loop 6:20788dfdb7b8 107 x = x * 8;
loop 6:20788dfdb7b8 108 y = y * 8;
loop 9:5c4a3e89a713 109 this->ballAccelX = x;
loop 9:5c4a3e89a713 110 this->ballAccelY = y;
loop 9:5c4a3e89a713 111 }
loop 5:8a26ad9d9ea1 112
loop 6:20788dfdb7b8 113 void Game::tick() {
loop 6:20788dfdb7b8 114 int tcount = 0;
john_ghielec 2:6ab46f2e851a 115 this->checkButtons();
john_ghielec 1:cd8a3926f263 116
loop 10:ba2dea5fffd1 117 if ((tcount++ % 10) == 0) {
loop 10:ba2dea5fffd1 118 this->readAccel();
loop 10:ba2dea5fffd1 119 };
loop 10:ba2dea5fffd1 120 this->clearBall();
loop 10:ba2dea5fffd1 121 this->updateBall();
loop 10:ba2dea5fffd1 122 this->checkCollision();
loop 10:ba2dea5fffd1 123 this->drawBall();
loop 10:ba2dea5fffd1 124 //this->checkPwm();
loop 10:ba2dea5fffd1 125 //this->checkLives();
john_ghielec 1:cd8a3926f263 126 }
john_ghielec 1:cd8a3926f263 127
john_ghielec 2:6ab46f2e851a 128 void Game::checkButtons() {
john_ghielec 2:6ab46f2e851a 129 if (!this->square.read()) {
loop 10:ba2dea5fffd1 130 this->muted = !this->muted;
john_ghielec 2:6ab46f2e851a 131 }
john_ghielec 2:6ab46f2e851a 132
loop 9:5c4a3e89a713 133 bool xDir = this->ballSpeedX > 0.0;
loop 9:5c4a3e89a713 134 bool yDir = this->ballSpeedY > 0.0;
john_ghielec 2:6ab46f2e851a 135 bool isUp = !this->up.read();
john_ghielec 2:6ab46f2e851a 136 bool isDown = !this->down.read();
john_ghielec 1:cd8a3926f263 137
john_ghielec 2:6ab46f2e851a 138 if (isUp && isDown) goto end;
john_ghielec 2:6ab46f2e851a 139 if (!isUp && !isDown) goto end;
john_ghielec 2:6ab46f2e851a 140
john_ghielec 2:6ab46f2e851a 141 if (isUp && this->lastUp) goto end;
john_ghielec 2:6ab46f2e851a 142 if (isDown && this->lastDown) goto end;
john_ghielec 2:6ab46f2e851a 143
loop 9:5c4a3e89a713 144 if (!xDir) this->ballSpeedX *= -1.0;
loop 9:5c4a3e89a713 145 if (!yDir) this->ballSpeedY *= -1.0;
john_ghielec 1:cd8a3926f263 146
john_ghielec 2:6ab46f2e851a 147 if (isUp) {
john_ghielec 2:6ab46f2e851a 148 if (++this->ballSpeedX > 5) this->ballSpeedX = 5;
john_ghielec 2:6ab46f2e851a 149 if (++this->ballSpeedY > 5) this->ballSpeedY = 5;
john_ghielec 2:6ab46f2e851a 150 }
john_ghielec 2:6ab46f2e851a 151 else if (isDown) {
john_ghielec 2:6ab46f2e851a 152 if (--this->ballSpeedX == 0) this->ballSpeedX = 1;
john_ghielec 2:6ab46f2e851a 153 if (--this->ballSpeedY == 0) this->ballSpeedY = 1;
john_ghielec 2:6ab46f2e851a 154 }
john_ghielec 1:cd8a3926f263 155
john_ghielec 2:6ab46f2e851a 156 if (!xDir) this->ballSpeedX *= -1;
john_ghielec 2:6ab46f2e851a 157 if (!yDir) this->ballSpeedY *= -1;
john_ghielec 2:6ab46f2e851a 158
john_ghielec 2:6ab46f2e851a 159 end:
john_ghielec 2:6ab46f2e851a 160 this->lastUp = isUp;
john_ghielec 2:6ab46f2e851a 161 this->lastDown = isDown;
john_ghielec 1:cd8a3926f263 162 }
john_ghielec 1:cd8a3926f263 163
john_ghielec 1:cd8a3926f263 164 void Game::drawString(const char* str, int y) {
loop 7:c0f12f624832 165 this->disp.drawString(font_ibm,
loop 7:c0f12f624832 166 this->disp.getWidth() / 2 - (CHAR_WIDTH + CHAR_SPACING) * strlen(str) / 2,
loop 7:c0f12f624832 167 y, str);
john_ghielec 1:cd8a3926f263 168 }
john_ghielec 1:cd8a3926f263 169 void Game::showSplashScreen() {
loop 7:c0f12f624832 170 this->drawString(Game::SPLASH_1, this->disp.getHeight() / 2 - CHAR_HEIGHT / 2);
loop 7:c0f12f624832 171 this->drawString(Game::SPLASH_2, this->disp.getHeight() / 2 + CHAR_HEIGHT / 2);
john_ghielec 1:cd8a3926f263 172 while (this->circle.read())
loop 7:c0f12f624832 173 wait_ms(5);
loop 7:c0f12f624832 174 this->disp.clearScreen();
john_ghielec 1:cd8a3926f263 175 }
john_ghielec 1:cd8a3926f263 176
john_ghielec 1:cd8a3926f263 177 void Game::clearBall() {
loop 7:c0f12f624832 178 this->disp.fillRect(ballX - BALL_RADIUS,
loop 7:c0f12f624832 179 ballY - BALL_RADIUS,
loop 7:c0f12f624832 180 ballX + BALL_RADIUS,
loop 7:c0f12f624832 181 ballY + BALL_RADIUS,
loop 10:ba2dea5fffd1 182 Color565::Black);
john_ghielec 1:cd8a3926f263 183 }
john_ghielec 1:cd8a3926f263 184
john_ghielec 1:cd8a3926f263 185 void Game::drawBall() {
loop 7:c0f12f624832 186 this->disp.fillRect(ballX - BALL_RADIUS,
loop 7:c0f12f624832 187 ballY - BALL_RADIUS,
loop 7:c0f12f624832 188 ballX + BALL_RADIUS,
loop 7:c0f12f624832 189 ballY + BALL_RADIUS,
loop 9:5c4a3e89a713 190 this->colors[this->cCol]);
john_ghielec 1:cd8a3926f263 191 }
john_ghielec 1:cd8a3926f263 192
john_ghielec 1:cd8a3926f263 193 void Game::updateBall() {
loop 5:8a26ad9d9ea1 194 this->ballSpeedX += this->ballAccelX;
loop 9:5c4a3e89a713 195 if(this->ballSpeedX > MAX_SPEED)
loop 9:5c4a3e89a713 196 this->ballSpeedX = MAX_SPEED;
loop 9:5c4a3e89a713 197 if (this->ballSpeedX < -MAX_SPEED)
loop 9:5c4a3e89a713 198 this->ballSpeedX = -MAX_SPEED;
john_ghielec 1:cd8a3926f263 199 this->ballX += this->ballSpeedX;
loop 9:5c4a3e89a713 200
loop 9:5c4a3e89a713 201 this->ballSpeedY += this->ballAccelY;
loop 9:5c4a3e89a713 202 if (this->ballSpeedY > MAX_SPEED)
loop 9:5c4a3e89a713 203 this->ballSpeedY = MAX_SPEED;
loop 9:5c4a3e89a713 204 if (this->ballSpeedY < -MAX_SPEED)
loop 9:5c4a3e89a713 205 this->ballSpeedY = -MAX_SPEED;
john_ghielec 1:cd8a3926f263 206 this->ballY += this->ballSpeedY;
loop 9:5c4a3e89a713 207
loop 9:5c4a3e89a713 208 // Does bounds checking..
loop 9:5c4a3e89a713 209 if ((this->ballX - Game::BALL_RADIUS <= 0 && this->ballSpeedX < 0.0) ||
loop 9:5c4a3e89a713 210 (this->ballX + Game::BALL_RADIUS >= disp.getWidth() && this->ballSpeedX > 0.0)) {
loop 9:5c4a3e89a713 211 this->ballSpeedX *= -1.0;
loop 9:5c4a3e89a713 212 this->bounce();
loop 9:5c4a3e89a713 213 }
loop 9:5c4a3e89a713 214 if ((this->ballY - Game::BALL_RADIUS <= 0 && this->ballSpeedY < 0.0) ||
loop 9:5c4a3e89a713 215 (this->ballY + Game::BALL_RADIUS >= disp.getHeight() && this->ballSpeedY > 0.0)){
loop 9:5c4a3e89a713 216 this->ballSpeedY *= -1.0;
loop 9:5c4a3e89a713 217 this->bounce();
loop 9:5c4a3e89a713 218 }
loop 9:5c4a3e89a713 219 // Sanity
loop 10:ba2dea5fffd1 220 //this->printDouble(this->ballSpeedX, 1, 0);
loop 10:ba2dea5fffd1 221 //this->printDouble(this->ballSpeedY, 1, 8);
loop 10:ba2dea5fffd1 222 //this->printDouble(this->ballAccelX, 120, 0);
loop 10:ba2dea5fffd1 223 //this->printDouble(this->ballAccelY, 120, 8);
loop 9:5c4a3e89a713 224 }
loop 9:5c4a3e89a713 225
loop 9:5c4a3e89a713 226 void Game::bounce() {
loop 9:5c4a3e89a713 227 this->cCol++;
loop 9:5c4a3e89a713 228 if (this->cCol == 3)
loop 9:5c4a3e89a713 229 this->cCol = 0;
loop 9:5c4a3e89a713 230 if (!this->muted) {
loop 9:5c4a3e89a713 231 this->pwm.period_ms(2);
loop 9:5c4a3e89a713 232 this->pwmTicksLeft = Game::BOUNCE_SOUND_TICKS;
loop 9:5c4a3e89a713 233 }
john_ghielec 1:cd8a3926f263 234 }
john_ghielec 1:cd8a3926f263 235
loop 4:84be90860d7c 236 void Game::checkCollision() {
loop 4:84be90860d7c 237 /*
john_ghielec 1:cd8a3926f263 238 if (this->ballY + Game::BALL_RADIUS >= DisplayN18::HEIGHT - Game::PADDLE_HEIGHT && this->ballSpeedY > 0) {
john_ghielec 1:cd8a3926f263 239 if (this->ballY + Game::BALL_RADIUS >= DisplayN18::HEIGHT) {
john_ghielec 1:cd8a3926f263 240 this->initializeBall();
john_ghielec 1:cd8a3926f263 241
john_ghielec 1:cd8a3926f263 242 this->lives--;
devhammer 3:2f09c90a732d 243
devhammer 3:2f09c90a732d 244 if(this->lives > 0) {
devhammer 3:2f09c90a732d 245 if(!this->muted) {
devhammer 3:2f09c90a732d 246 this->pwm.period(1.0/220);
devhammer 3:2f09c90a732d 247 this->pwm.write(0.5);
devhammer 3:2f09c90a732d 248 wait_ms(150);
devhammer 3:2f09c90a732d 249 this->pwm.write(0.0);
devhammer 3:2f09c90a732d 250 }
devhammer 3:2f09c90a732d 251 }
devhammer 3:2f09c90a732d 252
john_ghielec 1:cd8a3926f263 253 }
john_ghielec 1:cd8a3926f263 254 else if (this->ballX > this->paddleX && this->ballX < this->paddleX + Game::PADDLE_WIDTH) {
john_ghielec 1:cd8a3926f263 255 this->ballSpeedY *= -1;
john_ghielec 1:cd8a3926f263 256
devhammer 3:2f09c90a732d 257 if(!this->muted){
devhammer 3:2f09c90a732d 258 this->pwm.period_ms(1);
devhammer 3:2f09c90a732d 259 this->pwmTicksLeft = Game::BOUNCE_SOUND_TICKS;
devhammer 3:2f09c90a732d 260 }
devhammer 3:2f09c90a732d 261 this->score = this->score + 10;
devhammer 3:2f09c90a732d 262 if(this->score % 100 == 0) {
devhammer 3:2f09c90a732d 263 if(this->ballSpeedX < 0){
devhammer 3:2f09c90a732d 264 this->ballSpeedX -= 1;
devhammer 3:2f09c90a732d 265 }
devhammer 3:2f09c90a732d 266 else {
devhammer 3:2f09c90a732d 267 this->ballSpeedX += 1;
devhammer 3:2f09c90a732d 268 }
devhammer 3:2f09c90a732d 269 this->ballSpeedY -= 1;
devhammer 3:2f09c90a732d 270 }
john_ghielec 1:cd8a3926f263 271 }
john_ghielec 1:cd8a3926f263 272 }
devhammer 3:2f09c90a732d 273 char buf[10];
devhammer 3:2f09c90a732d 274 int a = this->score;
devhammer 3:2f09c90a732d 275 sprintf(buf, "%d", a);
loop 7:c0f12f624832 276 this->disp.drawString(LCDST7735.getWidth() - (DisplayN18::CHAR_WIDTH * 12), 0, Game::SCORE, Color565::White, DisplayN18::BLACK);
loop 7:c0f12f624832 277 this->disp.drawString(LCDST7735.getWidth() - (DisplayN18::CHAR_WIDTH * 4), 0, buf, Color565::White, DisplayN18::BLACK);
loop 7:c0f12f624832 278 */
loop 7:c0f12f624832 279
john_ghielec 1:cd8a3926f263 280 }
john_ghielec 1:cd8a3926f263 281 void Game::checkPwm() {
john_ghielec 1:cd8a3926f263 282 if (this->pwmTicksLeft == 0) {
devhammer 3:2f09c90a732d 283 this->pwm.write(0.0);
john_ghielec 1:cd8a3926f263 284 }
john_ghielec 1:cd8a3926f263 285 else {
john_ghielec 1:cd8a3926f263 286 this->pwmTicksLeft--;
john_ghielec 1:cd8a3926f263 287 this->pwm.write(0.5);
john_ghielec 1:cd8a3926f263 288 }
john_ghielec 1:cd8a3926f263 289 }
john_ghielec 1:cd8a3926f263 290
john_ghielec 1:cd8a3926f263 291 void Game::checkLives() {
loop 9:5c4a3e89a713 292 if (this->lives != 0) {
loop 9:5c4a3e89a713 293 this->disp.drawString(font_ibm, 0, 0, Game::LIVES);
loop 9:5c4a3e89a713 294 //this->disp.drawCharacter(DisplayN18::CHAR_WIDTH * 8, 0, static_cast<char>(this->lives + '0'), Color565::White, DisplayN18::BLACK);
loop 9:5c4a3e89a713 295 } else {
loop 7:c0f12f624832 296 this->disp.clearScreen();
devhammer 3:2f09c90a732d 297
loop 7:c0f12f624832 298 this->drawString(Game::LOSE_1, disp.getHeight() / 2 - CHAR_HEIGHT);
loop 7:c0f12f624832 299 this->drawString(Game::LOSE_2, disp.getHeight() / 2);
john_ghielec 1:cd8a3926f263 300
devhammer 3:2f09c90a732d 301 if(!this->muted) {
devhammer 3:2f09c90a732d 302 this->pwm.period(1.0/220);
devhammer 3:2f09c90a732d 303 this->pwm.write(0.5);
devhammer 3:2f09c90a732d 304 wait_ms(150);
devhammer 3:2f09c90a732d 305 this->pwm.write(0.0);
devhammer 3:2f09c90a732d 306
devhammer 3:2f09c90a732d 307 this->pwm.period(1.0/196);
devhammer 3:2f09c90a732d 308 this->pwm.write(0.5);
devhammer 3:2f09c90a732d 309 wait_ms(150);
devhammer 3:2f09c90a732d 310 this->pwm.write(0.0);
devhammer 3:2f09c90a732d 311
devhammer 3:2f09c90a732d 312 this->pwm.period(1.0/164.81);
devhammer 3:2f09c90a732d 313 this->pwm.write(0.5);
devhammer 3:2f09c90a732d 314 wait_ms(150);
devhammer 3:2f09c90a732d 315 this->pwm.write(0.0);
devhammer 3:2f09c90a732d 316 }
devhammer 3:2f09c90a732d 317
john_ghielec 1:cd8a3926f263 318 while (this->circle.read())
john_ghielec 1:cd8a3926f263 319 this->initialize();
john_ghielec 1:cd8a3926f263 320 }
john_ghielec 1:cd8a3926f263 321 }