Brick Breaker
Dependencies: 4DGL-uLCD-SE mbed-rtos mbed
Game.h
- Committer:
- hotwheelharry
- Date:
- 2014-10-21
- Revision:
- 0:099e4258aba4
File content as of revision 0:099e4258aba4:
#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); } };