new mods upon mods by devhammer: - Added paddle control using tilting of the console - Finished mute function - Reduced flickering See game.cpp for full info.
Fork of RETRO_Pong_Mod by
This is a mod of the official Pong game released with the RETRO game console.
Revision 1:cd8a3926f263, committed 2014-11-17
- Comitter:
- john_ghielec
- Date:
- Mon Nov 17 19:51:24 2014 +0000
- Parent:
- 0:21669ea33448
- Child:
- 2:6ab46f2e851a
- Commit message:
- Split game logic out into a game file.
Changed in this revision
--- a/DisplayN18.cpp Mon Nov 10 13:04:42 2014 +0000 +++ b/DisplayN18.cpp Mon Nov 17 19:51:24 2014 +0000 @@ -1,7 +1,6 @@ #include "DisplayN18.h" -DisplayN18::DisplayN18() : resetPin(P0_20), backlightPin(P0_19), rsPin(P0_7), csPin(P0_2), spi(P0_21, P0_22, P1_15) -{ +DisplayN18::DisplayN18() : resetPin(P0_20), backlightPin(P0_19), rsPin(P0_7), csPin(P0_2), spi(P0_21, P0_22, P1_15) { this->resetPin.write(false); this->backlightPin.write(true); this->rsPin.write(false); @@ -12,8 +11,7 @@ this->initialize(); } -void DisplayN18::writeCommand(unsigned char command) -{ +void DisplayN18::writeCommand(unsigned char command) { this->rsPin.write(false); this->csPin.write(false); @@ -23,13 +21,11 @@ this->csPin.write(true); } -void DisplayN18::writeData(unsigned char data) -{ +void DisplayN18::writeData(unsigned char data) { this->writeData(&data, 1); } -void DisplayN18::writeData(const unsigned char* data, unsigned int length) -{ +void DisplayN18::writeData(const unsigned char* data, unsigned int length) { this->rsPin.write(true); this->csPin.write(false); @@ -40,8 +36,7 @@ this->csPin.write(true); } -void DisplayN18::reset() -{ +void DisplayN18::reset() { this->resetPin.write(false); wait_ms(300); @@ -49,8 +44,7 @@ wait_ms(500); } -void DisplayN18::initialize() -{ +void DisplayN18::initialize() { this->reset(); this->writeCommand(0x11); @@ -124,8 +118,7 @@ this->clear(); } -void DisplayN18::setClippingArea(unsigned char x, unsigned char y, unsigned char width, unsigned char height) -{ +void DisplayN18::setClippingArea(unsigned char x, unsigned char y, unsigned char width, unsigned char height) { unsigned char data[4] = { 0x00, 0x00, 0x00, 0x00 }; data[1] = x; @@ -139,8 +132,7 @@ this->writeData(data, 4); } -unsigned short DisplayN18::rgbToShort(unsigned char r, unsigned char g, unsigned char b) -{ +unsigned short DisplayN18::rgbToShort(unsigned char r, unsigned char g, unsigned char b) { unsigned short red = r; unsigned short green = g; unsigned short blue = b; @@ -160,27 +152,23 @@ return red | green | blue; } -void DisplayN18::clear(unsigned short backColor) -{ +void DisplayN18::clear(unsigned short backColor) { for (unsigned int i = 0; i < DisplayN18::WIDTH; i += 10) for (unsigned int j = 0; j < DisplayN18::HEIGHT; j += 8) this->fillRect(i, j, 10, 8, backColor); } -void DisplayN18::draw(const unsigned short* data, int x, int y, int width, int height) -{ +void DisplayN18::draw(const unsigned short* data, int x, int y, int width, int height) { this->setClippingArea(x, y, width - 1, height - 1); this->writeCommand(0x2C); this->writeData(reinterpret_cast<const unsigned char*>(data), width * height * 2); } -void DisplayN18::setPixel(int x, int y, unsigned short foreColor) -{ +void DisplayN18::setPixel(int x, int y, unsigned short foreColor) { this->draw(&foreColor, x, y, 1, 1); } -void DisplayN18::fillRect(int x, int y, int width, int height, unsigned short foreColor) -{ +void DisplayN18::fillRect(int x, int y, int width, int height, unsigned short foreColor) { this->setClippingArea(static_cast<unsigned char>(x), static_cast<unsigned char>(y), static_cast<unsigned char>(width - 1), static_cast<unsigned char>(height)); this->writeCommand(0x2C); @@ -200,16 +188,14 @@ this->writeData(reinterpret_cast<unsigned char*>(buffer), height * width * 2 - i); } -void DisplayN18::drawRect(int x, int y, int width, int height, unsigned short foreColor) -{ +void DisplayN18::drawRect(int x, int y, int width, int height, unsigned short foreColor) { this->drawLine(x, y, x + width, y, foreColor); this->drawLine(x, y + height, x + width, y + height, foreColor); this->drawLine(x, y, x, y + height, foreColor); this->drawLine(x + width, y, x + width, y + height, foreColor); } -void DisplayN18::fillCircle(int x, int y, int radius, unsigned short foreColor) -{ +void DisplayN18::fillCircle(int x, int y, int radius, unsigned short foreColor) { int f = 1 - radius; int dd_f_x = 1; int dd_f_y = -2 * radius; @@ -219,10 +205,8 @@ for (int i = y - radius; i <= y + radius; i++) this->setPixel(x, i, foreColor); - while (x1 < y1) - { - if (f >= 0) - { + while (x1 < y1) { + if (f >= 0) { y1--; dd_f_y += 2; f += dd_f_y; @@ -232,22 +216,19 @@ dd_f_x += 2; f += dd_f_x; - for (int i = y - y1; i <= y + y1; i++) - { + for (int i = y - y1; i <= y + y1; i++) { this->setPixel(x + x1, i, foreColor); this->setPixel(x - x1, i, foreColor); } - for (int i = y - x1; i <= y + x1; i++) - { + for (int i = y - x1; i <= y + x1; i++) { this->setPixel(x + y1, i, foreColor); this->setPixel(x - y1, i, foreColor); } } } -void DisplayN18::drawCircle(int x, int y, int radius, unsigned short foreColor) -{ +void DisplayN18::drawCircle(int x, int y, int radius, unsigned short foreColor) { int f = 1 - radius; int dd_f_x = 1; int dd_f_y = -2 * radius; @@ -259,10 +240,8 @@ this->setPixel(x + radius, y, foreColor); this->setPixel(x - radius, y, foreColor); - while (x1 < y1) - { - if (f >= 0) - { + while (x1 < y1) { + if (f >= 0) { y1--; dd_f_y += 2; f += dd_f_y; @@ -284,12 +263,9 @@ } } -void DisplayN18::drawLine(int x0, int y0, int x1, int y1, unsigned short foreColor) -{ - if (x0 == x1) - { - if (y1 < y0) - { +void DisplayN18::drawLine(int x0, int y0, int x1, int y1, unsigned short foreColor) { + if (x0 == x1) { + if (y1 < y0) { int temp = y0; y0 = y1; y1 = temp; @@ -308,10 +284,8 @@ return; } - if (y0 == y1) - { - if (x1 < x0) - { + if (y0 == y1) { + if (x1 < x0) { int temp = x0; x0 = x1; x1 = temp; @@ -333,8 +307,7 @@ int t; bool steep = ((y1 - y0) < 0 ? -(y1 - y0) : (y1 - y0)) > ((x1 - x0) < 0 ? -(x1 - x0) : (x1 - x0)); - if (steep) - { + if (steep) { t = x0; x0 = y0; y0 = t; @@ -343,8 +316,7 @@ y1 = t; } - if (x0 > x1) - { + if (x0 > x1) { t = x0; x0 = x1; x1 = t; @@ -361,13 +333,9 @@ int err = (dx / 2); int ystep; - if (y0 < y1) - ystep = 1; - else - ystep = -1; + ystep = y0 < y1 ? 1 : -1; - for (; x0 < x1; x0++) - { + for (; x0 < x1; x0++) { if (steep) this->setPixel(y0, x0, foreColor); else @@ -375,8 +343,7 @@ err -= dy; - if (err < 0) - { + if (err < 0) { y0 += (char)ystep; err += dx; } @@ -481,14 +448,12 @@ 0x08, 0x08, 0x2a, 0x1c, 0x08 /* ~ */ }; -void DisplayN18::drawCharacter(int x, int y, const char character, unsigned short foreColor, unsigned short backColor, unsigned char fontSize) -{ +void DisplayN18::drawCharacter(int x, int y, const char character, unsigned short foreColor, unsigned short backColor, unsigned char fontSize) { if (character > 126 || character < 32) return; unsigned short* horizontal = new unsigned short[DisplayN18::CHAR_HEIGHT * fontSize]; - for (int i = 0; i < DisplayN18::CHAR_WIDTH; i++) - { + for (int i = 0; i < DisplayN18::CHAR_WIDTH; i++) { for (int j = 0; j < DisplayN18::CHAR_HEIGHT; j++) for (int k = 0; k < fontSize; k++) horizontal[j * fontSize + k] = characters[(character - 32) * 5 + i] & (1 << j) ? foreColor : backColor; @@ -507,13 +472,11 @@ delete[] horizontal; } -void DisplayN18::drawString(int x, int y, const char* str, unsigned short foreColor, unsigned short backColor, unsigned char fontSize) -{ +void DisplayN18::drawString(int x, int y, const char* str, unsigned short foreColor, unsigned short backColor, unsigned char fontSize) { if (*str == '\0') return; - do - { + do { this->drawCharacter(x, y, *str, foreColor, backColor, fontSize); x += (DisplayN18::CHAR_WIDTH + DisplayN18::CHAR_SPACING) * fontSize;
--- a/DisplayN18.h Mon Nov 10 13:04:42 2014 +0000 +++ b/DisplayN18.h Mon Nov 17 19:51:24 2014 +0000 @@ -2,8 +2,7 @@ #pragma once -class DisplayN18 -{ +class DisplayN18 { static const unsigned char STEP = 4; DigitalOut resetPin;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Game.cpp Mon Nov 17 19:51:24 2014 +0000 @@ -0,0 +1,153 @@ +#include "Game.h" + +const char* Game::LOSE_1 = "You lose."; +const char* Game::LOSE_2 = "Press ship to restart."; +const char* Game::SPLASH = "Press ship to start."; + +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) { + srand(this->ain.read_u16()); + + this->initialize(); +} + +void Game::initialize() { + this->initializeBall(); + + this->paddleX = DisplayN18::WIDTH / 2 - Game::PADDLE_WIDTH / 2; + this->pwmTicksLeft = 0; + this->lives = 4; + + this->pwm.period_ms(1); + this->pwm.write(0.00); + + this->disp.clear(); +} + +void Game::initializeBall() { + this->ballX = DisplayN18::WIDTH / 2 - Game::BALL_RADIUS; + this->ballY = DisplayN18::HEIGHT / 4 - Game::BALL_RADIUS; + + this->ballSpeedX = rand() % (Game::MAX_BALL_SPEED * 2); + this->ballSpeedY = rand() % (Game::MAX_BALL_SPEED * 2); + + this->ballSpeedX -= Game::MAX_BALL_SPEED; + this->ballSpeedY -= Game::MAX_BALL_SPEED; + + if (this->ballSpeedX == 0) + this->ballSpeedX++; + + if (this->ballSpeedY == 0) + this->ballSpeedY--; +} + +void Game::tick() { + this->clearPaddle(); + this->clearBall(); + + this->updatePaddle(); + this->updateBall(); + + this->checkCollision(); + + this->drawPaddle(); + this->drawBall(); + + this->checkPwm(); + this->checkLives(); +} + +void Game::drawString(const char* str, int y) { + this->disp.drawString(DisplayN18::WIDTH / 2 - (DisplayN18::CHAR_WIDTH + DisplayN18::CHAR_SPACING) * strlen(str) / 2, y, str, DisplayN18::WHITE, DisplayN18::BLACK); +} + +void Game::showSplashScreen() { + this->drawString(Game::SPLASH, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT / 2); + + while (this->circle.read()) + wait_ms(1); + + this->disp.clear(); +} + +void Game::clearPaddle() { + this->disp.fillRect(this->paddleX, DisplayN18::HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT, DisplayN18::BLACK); +} + +void Game::drawPaddle() { + this->disp.fillRect(this->paddleX, DisplayN18::HEIGHT - Game::PADDLE_HEIGHT, Game::PADDLE_WIDTH, Game::PADDLE_HEIGHT, DisplayN18::BLUE); +} + +void Game::updatePaddle() { + if (this->left.read()) + this->paddleX += Game::PADDLE_SPEED; + + if (this->right.read()) + this->paddleX -= Game::PADDLE_SPEED; +} + +void Game::clearBall() { + this->disp.fillRect(this->ballX - Game::BALL_RADIUS, ballY - Game::BALL_RADIUS, Game::BALL_RADIUS * 2, Game::BALL_RADIUS * 2, DisplayN18::BLACK); +} + +void Game::drawBall() { + this->disp.fillRect(this->ballX - Game::BALL_RADIUS, ballY - Game::BALL_RADIUS, Game::BALL_RADIUS * 2, Game::BALL_RADIUS * 2, DisplayN18::RED); +} + +void Game::updateBall() { + this->ballX += this->ballSpeedX; + this->ballY += this->ballSpeedY; +} + +void Game::checkCollision() { + if (this->paddleX < 0) + this->paddleX = 0; + + if (this->paddleX + Game::PADDLE_WIDTH > DisplayN18::WIDTH) + this->paddleX = DisplayN18::WIDTH - Game::PADDLE_WIDTH; + + if ((this->ballX - Game::BALL_RADIUS < 0 && this->ballSpeedX < 0) || (this->ballX + Game::BALL_RADIUS >= DisplayN18::WIDTH && this->ballSpeedX > 0)) + this->ballSpeedX *= -1; + + if (this->ballY - Game::BALL_RADIUS < 0 && this->ballSpeedY < 0) + this->ballSpeedY *= -1; + + if (this->ballY + Game::BALL_RADIUS >= DisplayN18::HEIGHT - Game::PADDLE_HEIGHT && this->ballSpeedY > 0) { + if (this->ballY + Game::BALL_RADIUS >= DisplayN18::HEIGHT) { + this->initializeBall(); + + this->lives--; + } + else if (this->ballX > this->paddleX && this->ballX < this->paddleX + Game::PADDLE_WIDTH) { + this->ballSpeedY *= -1; + + this->pwmTicksLeft = Game::BOUNCE_SOUND_TICKS; + } + } +} + +void Game::checkPwm() { + if (this->pwmTicksLeft == 0) { + this->pwm.write(0.0); + } + else { + this->pwmTicksLeft--; + this->pwm.write(0.5); + } +} + +void Game::checkLives() { + if (this->lives == 0) { + this->disp.clear(); + + this->drawString(Game::LOSE_1, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT); + this->drawString(Game::LOSE_2, DisplayN18::HEIGHT / 2); + + while (this->circle.read()) + wait_ms(1); + + this->initialize(); + } + else { + this->disp.drawCharacter(0, 0, static_cast<char>(this->lives + '0'), DisplayN18::WHITE, DisplayN18::BLACK); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Game.h Mon Nov 17 19:51:24 2014 +0000 @@ -0,0 +1,62 @@ +#include "mbed.h" + +#include "DisplayN18.h" + +#pragma once + +class Game { + static const char* LOSE_1; + static const char* LOSE_2; + static const char* SPLASH; + + static const int BALL_RADIUS = 3; + static const int MAX_BALL_SPEED = 5; + static const int PADDLE_WIDTH = 38; + static const int PADDLE_HEIGHT = 4; + static const int PADDLE_SPEED = 4; + static const int BOUNCE_SOUND_TICKS = 2; + + int ballX; + int ballY; + int ballSpeedX; + int ballSpeedY; + int paddleX; + int pwmTicksLeft; + int lives; + + DigitalIn left; + DigitalIn right; + DigitalIn down; + DigitalIn up; + DigitalIn square; + DigitalIn circle; + DigitalOut led1; + DigitalOut led2; + PwmOut pwm; + AnalogIn ain; + I2C i2c; + DisplayN18 disp; + + void initialize(); + void initializeBall(); + + void drawString(const char* str, int y); + + void clearPaddle(); + void drawPaddle(); + void updatePaddle(); + + void clearBall(); + void drawBall(); + void updateBall(); + + void checkCollision(); + void checkPwm(); + void checkLives(); + + public: + Game(); + + void showSplashScreen(); + void tick(); +}; \ No newline at end of file
--- a/Main.cpp Mon Nov 10 13:04:42 2014 +0000 +++ b/Main.cpp Mon Nov 17 19:51:24 2014 +0000 @@ -1,225 +1,15 @@ #include "mbed.h" -#include "DisplayN18.h" - -DigitalIn left(P0_14, PullUp); -DigitalIn right(P0_11, PullUp); -DigitalIn down(P0_12, PullUp); -DigitalIn up(P0_13, PullUp); -DigitalIn square(P0_16, PullUp); -DigitalIn circle(P0_1, PullUp); -DigitalOut led1(P0_9); -DigitalOut led2(P0_8); -PwmOut pwm(P0_18); -AnalogIn ain(P0_15); -I2C i2c(P0_5, P0_4); -DisplayN18 disp; - -int ballX, ballY, ballSpeedX, ballSpeedY, paddleX, pwmTicksLeft, lives; - -const char* LOSE_1 = "You lose."; -const char* LOSE_2 = "Press circle to restart."; -const char* SPLASH = "Press circle to start."; - -const char I2C_ADDR = 0x1C << 1; -const int BALL_RADIUS = 4; -const int MIN_BALL_SPEED = 2; -const int MAX_BALL_SPEED = 4; -const int PADDLE_WIDTH = 40; -const int PADDLE_HEIGHT = 5; -const int PADDLE_SPEED = 5; -const int BOUNCE_SOUND_TICKS = 2; - -void initializeBall() { - ballX = DisplayN18::WIDTH / 2 - BALL_RADIUS; - ballY = DisplayN18::HEIGHT / 4 - BALL_RADIUS; - - ballSpeedX = rand() % (MAX_BALL_SPEED - MIN_BALL_SPEED) + MIN_BALL_SPEED; - ballSpeedY = rand() % (MAX_BALL_SPEED - MIN_BALL_SPEED) + MIN_BALL_SPEED; - - if (rand() % 2) - ballSpeedX *= -1; - - if (rand() % 2) - ballSpeedY *= -1; - - if (ballSpeedX == 0) - ballSpeedX++; - - if (ballSpeedY == 0) - ballSpeedY++; -} - -void initializeGame() { - initializeBall(); - - paddleX = DisplayN18::WIDTH / 2 - PADDLE_WIDTH / 2; - pwmTicksLeft = 0; - lives = 4; - - pwm.period_ms(1); - pwm.write(0.00); - - disp.clear(); -} - -void drawString(const char* str, int y) { - disp.drawString(DisplayN18::WIDTH / 2 - (DisplayN18::CHAR_WIDTH + DisplayN18::CHAR_SPACING) * strlen(str) / 2, y, str, DisplayN18::WHITE, DisplayN18::BLACK); -} - -void doSplash() { - drawString(SPLASH, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT / 2); - - while (circle) - wait_ms(1); -} - -void clearPaddle() { - disp.fillRect(paddleX, DisplayN18::HEIGHT - PADDLE_HEIGHT, PADDLE_WIDTH, PADDLE_HEIGHT, DisplayN18::BLACK); -} - -void drawPaddle() { - disp.fillRect(paddleX, DisplayN18::HEIGHT - PADDLE_HEIGHT, PADDLE_WIDTH, PADDLE_HEIGHT, DisplayN18::BLUE); -} - -void updatePaddle() { - if (left) - paddleX += PADDLE_SPEED; - - if (right) - paddleX -= PADDLE_SPEED; -} - -void clearBall() { - disp.fillRect(ballX - BALL_RADIUS, ballY - BALL_RADIUS, BALL_RADIUS * 2, BALL_RADIUS * 2, DisplayN18::BLACK); -} - -void drawBall() { - disp.fillRect(ballX - BALL_RADIUS, ballY - BALL_RADIUS, BALL_RADIUS * 2, BALL_RADIUS * 2, DisplayN18::RED); -} - -void updateBall() { - ballX += ballSpeedX; - ballY += ballSpeedY; -} - -void checkCollision() { - if (paddleX < 0) - paddleX = 0; - - if (paddleX + PADDLE_WIDTH > DisplayN18::WIDTH) - paddleX = DisplayN18::WIDTH - PADDLE_WIDTH; - - if ((ballX - BALL_RADIUS < 0 && ballSpeedX < 0) || (ballX + BALL_RADIUS >= DisplayN18::WIDTH && ballSpeedX > 0)) - ballSpeedX *= -1; - - if (ballY - BALL_RADIUS < 0 && ballSpeedY < 0) - ballSpeedY *= -1; - - if (ballY + BALL_RADIUS >= DisplayN18::HEIGHT - PADDLE_HEIGHT && ballSpeedY > 0) { - if (ballY + BALL_RADIUS >= DisplayN18::HEIGHT) { - initializeBall(); - - lives--; - } - else if (ballX > paddleX && ballX < paddleX + PADDLE_WIDTH) { - ballSpeedY *= -1; - - pwmTicksLeft = BOUNCE_SOUND_TICKS; - } - } -} - -void checkPwm() { - if (pwmTicksLeft == 0) { - pwm.write(0.0); - } - else { - pwmTicksLeft--; - pwm.write(0.5); - } -} - -void checkLives() { - if (lives == 0) { - disp.clear(); - - drawString(LOSE_1, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT); - drawString(LOSE_2, DisplayN18::HEIGHT / 2); - - while (circle) - wait_ms(1); - - initializeGame(); - } - else { - disp.drawCharacter(0, 0, static_cast<char>(lives + '0'), DisplayN18::WHITE, DisplayN18::BLACK); - } -} - -int read_short(char address) { - char buffer[2]; - - i2c.write(I2C_ADDR, &address, 1, true); - i2c.read(I2C_ADDR | 1, buffer, 2); - - return ((buffer[0] << 2) | (buffer[1] >> 6)) & 0x3F; -} - -int write_register(char address, char value) { - char buffer[2] = { address, value }; - return i2c.write(I2C_ADDR, buffer, 2); -} - -void get_xyz(int& x, int& y, int& z) { - x = read_short(0x01); - y = read_short(0x03); - z = read_short(0x05); - - if (x > 511) x -= 1024; - if (y > 511) y -= 1024; - if (z > 511) z -= 1024; -} - -void print_int(int value, int x, int y) { - char buffer[10]; - int len = sprintf(buffer, "%d", value); - - disp.drawString(x, y, buffer, DisplayN18::WHITE, DisplayN18::BLACK); -} +#include "Game.h" int main() { - int x, y, z; - - write_register(0x2A, 0x01); - - //srand(ain.read_u16()); - - //doSplash(); - - //initializeGame(); + Game game; + + game.showSplashScreen(); while (true) { - /*clearPaddle(); - clearBall(); - - updatePaddle(); - updateBall(); - - checkCollision(); - - drawPaddle(); - drawBall(); + game.tick(); - checkPwm(); - checkLives();*/ - - get_xyz(x, y, z); - - print_int(x, 0, 0); - print_int(y, 0, 15); - print_int(z, 0, 30); - - wait_ms(100); + wait_ms(25); } } \ No newline at end of file