Brick Breaker

Dependencies:   4DGL-uLCD-SE mbed-rtos mbed

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);
+    }
+    
+};
+