Brick Breaker
Dependencies: 4DGL-uLCD-SE mbed-rtos mbed
Diff: Game.h
- Revision:
- 0:099e4258aba4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Game.h Tue Oct 21 16:14:11 2014 +0000 @@ -0,0 +1,382 @@ +#include <vector> +#include "Graphics.h" +#include <cmath> +#include <string> +#include <sstream> + + +float frand(){ + return (float)rand()/(float)RAND_MAX; +} +double round(double d) +{ + return floor(d + 0.5); +} + +class Melody{ + public: + std::vector<float> notes; +}; + +class Audio{ +private: + Mutex mutex; + AnalogOut& audio; +public: + Audio(AnalogOut& ao) : audio(ao) + { + } + + void playSong(Melody& s){ + mutex.lock(); + + mutex.unlock(); + } + void triggerShot(){ + mutex.lock(); + + mutex.unlock(); + } + void run(){ + while(true){ + + Thread::wait(100); //ms + } + } +}; + +class Controller{ +public: + + AnalogIn& sliderh; + AnalogIn& sliderv; + DigitalIn& button; +public: + Controller(AnalogIn& sliderh, AnalogIn& sliderv, DigitalIn& btn) : sliderh(sliderh), sliderv(sliderv), button(btn) + { + + } +}; + + + +class Physics{ +private: + +public: + float dt; + + void step(Scene& scene){ + Block& b = scene.ball; + + if(b.locked) + { + b.store_prev(); + b.updated = true; + b.next_coord.x = scene.paddle.coord.x + scene.paddle.size.x/2.0 - b.size.x/2.0; + b.next_coord.y = scene.paddle.coord.y - b.size.y - 1; + b.next_velocity.x = 0; + b.next_velocity.y = 0; + + b.next_swap(); + return; + } + + + //move things + if(b.velocity.x != 0 || b.velocity.y != 0) + { + b.store_prev(); + b.updated = true; + b.next_coord.x = b.coord.x + dt * b.velocity.x; + b.next_coord.y = b.coord.y + dt * b.velocity.y; + + b.next_velocity.x = b.velocity.x; + b.next_velocity.y = b.velocity.y; + } + + if( b.coord.x < 0) + { + b.next_coord.x = 0; + b.next_velocity.x = b.velocity.x * -1.0; + } + if( b.coord.x + b.size.x > 128){ + b.next_coord.x = 128-b.size.x; + b.next_velocity.x = b.velocity.x * -1.0; + } + + if(b.coord.y < 0) + { + b.next_coord.y = 0; + b.next_velocity.y = b.velocity.y * -1.0; + } + + //collision with blocks + int hitcount = 0; + for(std::list<Block>::iterator j = scene.blocks.begin(); j != scene.blocks.end(); j++){ + if(j->color == 0x444444){ + hitcount++; + } + if( j->interactive && b.touching( *j ) ){ + bool h = false; + bool v = false; + + //from right + if( b.coord.x > j->coord.x && b.coord.x < (j->coord.x + j->size.x) ){ + b.next_coord.x = j->coord.x + j->size.x; + b.next_velocity.x = b.next_velocity.x * -1.0; + h = true; + } + //from left + if(b.coord.x + b.size.x > j->coord.x && b.coord.x < (j->coord.x) ){ + b.next_coord.x = j->coord.x - b.size.x; + b.next_velocity.x = b.next_velocity.x * -1.0; + h = true; + } + + // from top + if( b.coord.y + b.size.y > j->coord.y && b.coord.y < (j->coord.y) ){ + b.next_coord.y = (j->coord.y - b.size.y); + b.next_velocity.y = b.next_velocity.y * -1.0; + b.next_coord.x = b.coord.x; + v = true; + } + //from bottom + if( b.coord.y < j->coord.y + j->size.y && b.coord.y + b.size.y > (j->coord.y) ){ + b.next_coord.y = (j->coord.y + j->size.y); + b.next_velocity.y = b.next_velocity.y * -1.0; + b.next_coord.x = b.coord.x; + v = true; + } + + if(h || v){ + + j->color = 0x444444; + j->updated = true; + j->interactive = false; + } + + + + + + + scene.score++; + std::stringstream ss; + ss << "Score:" << scene.score; + scene.text[0].message = ss.str(); + scene.text[0].updated = true; + + } + else{ + b.color = WHITE; + } + } + + if(hitcount == scene.blocks.size()){ + scene.beat = true; + } + + + + //collision with paddle + if(b.next_coord.y + b.size.y > scene.paddle.coord.y && b.next_coord.y - b.velocity.y < scene.paddle.coord.y + && (b.next_coord.x + b.size.x > scene.paddle.coord.x && b.next_coord.x < scene.paddle.coord.x + scene.paddle.size.x)){ + if(!b.locked){ + float pmid = scene.paddle.coord.x + scene.paddle.size.x/2.0; + float bmid = b.next_coord.x + b.size.x/2.0; + float d = bmid - pmid; + b.next_velocity.x = b.velocity.x + d/(scene.paddle.size.x/2.0) * 30.0; + if(b.next_velocity.x > 50) + { b.next_velocity.x = 50; } + if(b.next_velocity.x < -50) + { b.next_velocity.x = -50;} + + b.next_velocity.y = (b.velocity.y * -1.0) * 1.01; + b.next_coord.x = b.coord.x; + b.next_coord.y = scene.paddle.next_coord.y - b.size.y - 1; + } + } + + + //update all the new positions + b.next_swap(); + + }; + +}; + + +class Game{ +private: + Renderer& renderer; + Audio& audio; + Controller& controller; + + Physics physics; + Scene scene; + + int level; + + Scene menu; + +public: + Game(Renderer& renderer, Audio& aud, Controller& ctrl) + : renderer(renderer), audio(aud), controller(ctrl) + { + level = 0; + scene.bg = Color((int)renderer.background); + + buildScene(); + physics.dt = 0.1; + } + +private: + void buildMenu(){ + + } + void buildScene(){ + + scene.lives = 3; + scene.score = 0; + scene.beat = false; + + // build bricks + float vertical = 10; + float spacing = 2; + vec2 bgrid = {5,3}; + vec2 bsize; + bsize.x = (renderer.screen.x-spacing) / (bgrid.x) - 2; + bsize.y = 4; + + int colorscheme = level; + + for(int i = 0; i < bgrid.x; i++){ + for(int j = 0; j < bgrid.y; j++){ + Block b; + b.velocity.x = 0; + b.velocity.y = 0; + b.size = bsize; + b.coord.x = spacing + (bsize.x + spacing)*i; + b.coord.y = spacing + (bsize.y + spacing)*j + vertical; + b.copy(); + b.color = RED; + switch(colorscheme){ + case 0: b.color = Color(0x66+round(0x99*((float)(bgrid.y-j)/(float)bgrid.y)),0,0); + break; + case 1: b.color = Color(0,0x66+round(0x99*((float)(bgrid.y-j)/(float)bgrid.y)), 0); + break; + case 2: b.color = Color(0,0,0x66+round(0x99*((float)(bgrid.y-j)/(float)bgrid.y))); + break; + case 3: b.color = Color(round(0xff*(frand())), + round(0xff*(frand())), + round(0xff*(frand())) + ); + break; + + default: b.color = RED; + } + scene.blocks.push_back(b); + } + } + + Block pad; + pad.locked = true; + pad.size.x = renderer.screen.x / 4.0; + pad.size.y = 4; + pad.coord.x = renderer.screen.x / 4.0 + pad.size.x / 2.0; + pad.coord.y = renderer.screen.y - spacing - pad.size.y; + pad.copy(); + pad.color = WHITE; + scene.paddle = pad; + + + Block b; + b.size.x = 4; + b.size.y = 4; + b.coord.x = pad.coord.x + pad.size.x/2.0 - b.size.x/2.0; + b.coord.y = pad.coord.y - b.size.y - 1; + b.color = WHITE; + b.locked = true; + b.copy(); + scene.ball = b; + + Text tscore; + tscore.coord.x = renderer.screen.x / 6 - 12; + tscore.coord.y = 0; + tscore.font = FONT_7X8; + tscore.color = WHITE; + tscore.message = "Score:0"; + scene.text.push_back(tscore); + + Text tlives; + tlives.coord.x = 0; + tlives.coord.y = 0; + tlives.font = FONT_7X8; + tlives.color = WHITE; + tlives.message = "Lives:3"; + scene.text.push_back(tlives); + } + void getInput(){ + float pos = controller.sliderh; + scene.paddle.store_prev(); + scene.paddle.coord.x = (renderer.screen.x - scene.paddle.size.x - 4) * pos + 2; + scene.paddle.updated = true; + + Block& b = scene.ball; + if(b.locked) + { + if(controller.button ){ + b.locked = false; + b.velocity.y = -80.0; + } + } + } + void gameLogic(){ + if(scene.ball.coord.y > renderer.screen.y){ + scene.lives--; + std::stringstream ss; + ss << "Lives:" << scene.lives; + scene.text[1].message = ss.str(); + scene.text[1].updated = true; + + scene.ball.locked = true; + } + + if(scene.lives == 0){ + scene = Scene(); + level = 0; + buildScene(); + + renderer.g.filled_rectangle(0, 0, 128, 10, renderer.background); + } + + if(scene.beat){ + level++; + scene.ball.store_prev(); + Block cb = scene.ball; + + int score = scene.score; + scene = Scene(); + buildScene(); + scene.score = score; + std::stringstream ss; + ss << "Score:" << scene.score; + scene.text[0].message = ss.str(); + scene.text[0].updated = true; + + renderer.g.filled_rectangle(cb.coord.x, cb.coord.y, cb.coord.x+cb.size.x, cb.coord.y+cb.size.y, renderer.background); + renderer.g.filled_rectangle(0, 0, 128, 10, renderer.background); + + } + } +public: + void loop(){ + getInput(); + gameLogic(); + physics.step(scene); + renderer.render(scene); + } + +}; +