Kostadin Chakarov / Mbed 2 deprecated el17kec

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Map.cpp Source File

Map.cpp

00001 #include "Map.h"
00002 #include "Ball.h"
00003 
00004 // Levels
00005 
00006 void Level1::initBricks(Map & map)
00007 {
00008     int w = 41;     //width 
00009     int h = 2;      //height 
00010     int gap = 1;    //gap between bricks
00011     int y = 0;      //first y coord of columns
00012     
00013     for (int j = 0; j < 9; ++j) {
00014         int x = 0;  //first x coord of rows
00015         for (int i = 0; i < 2; ++i) {
00016             Brick b;
00017             b.x = x;
00018             b.y = y;
00019             b.w = w;
00020             b.h = h;
00021             map.addBrick(b);
00022 
00023             x += w + gap;
00024         }
00025         y += h + gap;
00026     }
00027 }
00028 
00029 
00030 void Level2::initBricks(Map & map)
00031 {
00032     int w = 20;     //width 
00033     int h = 2;      //height 
00034     int gap = 1;    //gap between bricks
00035     int y = 0;      //first y coord of columns
00036 
00037     for (int j = 0; j < 9; ++j) {
00038         int x = 0;  //first x coord of rows
00039         for (int i = 0; i < 4; ++i) {
00040             Brick b;
00041             b.x = x;
00042             b.y = y;
00043             b.w = w;
00044             b.h = h;
00045             map.addBrick(b);
00046 
00047             x += w + gap;
00048         }
00049         y += h + gap;
00050     }
00051 }
00052 
00053 
00054 void Level3::initBricks(Map & map)
00055 {
00056     int w = 13;     //width 
00057     int h = 2;      //height 
00058     int gap = 1;    //gap between bricks
00059     int y = 0;      //first y coord of columns
00060 
00061     for (int j = 0; j < 9; ++j) {
00062         int x = 0;  //first x coord of rows
00063         for (int i = 0; i < 6; ++i) {
00064             Brick b;
00065             b.x = x;
00066             b.y = y;
00067             b.w = w;
00068             b.h = h;
00069             map.addBrick(b);
00070 
00071             x += w + gap;
00072         }
00073         y += h + gap;
00074     }
00075 }
00076 
00077 // Power-Ups
00078 
00079 //Sprite for each powerup
00080 
00081 //                              rows,cols
00082 int powerUpPaddleSizeSprite[PowerUpH][PowerUpW] =   {
00083     { 0,1,0 },
00084     { 1,1,1 },
00085     { 0,1,0 },
00086     { 1,1,1 }
00087 };
00088 
00089 //                              rows,cols
00090 int powerUpPaddleSpeedSprite[PowerUpH][PowerUpW] =   {
00091     { 0,1,0 },
00092     { 0,1,0 },
00093     { 1,1,1 },
00094     { 1,1,1 }
00095 };
00096 
00097 //                              rows,cols
00098 int powerUpBallSpeedSprite[PowerUpH][PowerUpW] =   {
00099     { 0,1,0 },
00100     { 1,1,1 },
00101     { 1,1,1 },
00102     { 0,1,0 }
00103 };
00104 
00105 
00106 void PowerUpType::draw(N5110 &lcd, PowerUp &pUp) {
00107     //printf("%f, %f; %d,%d - %d\n", pUp.getPos().x,pUp.getPos().y,pUp.getH(),pUp.getW(), (int)((int*)sprite));
00108     lcd.drawSprite(pUp.getPos().x,pUp.getPos().y,pUp.getH(),pUp.getW(), (int*)sprite);
00109 }
00110 
00111 // Array containing all the powerup types 
00112 PowerUpType* PowerUpTypes[3] = {
00113     new PaddleSizePUpType(0, *powerUpPaddleSizeSprite),
00114     new PaddleSpeedPUpType(1, *powerUpPaddleSpeedSprite),
00115     new BallSpeedPUpType(2, *powerUpBallSpeedSprite)
00116 };
00117 
00118 
00119 PowerUp::PowerUp(float x, float y, PowerUpType& pUpType) : _pUpType(&pUpType)
00120 {
00121     pos.x = x;
00122     pos.y = y;
00123     velocity.x = 0;
00124     velocity.y = 0.5f;
00125     w = PowerUpW;
00126     h = PowerUpH;
00127 }
00128 
00129 void PowerUp::draw(N5110 &lcd) {
00130     //printf("powerup %.02f , %.02f, %d\n", pos.x, pos.y, powerUpSprite[0][2]);
00131     _pUpType->draw(lcd, *this);
00132 }
00133 
00134 void PaddleSizePUpType::giveBonus(Paddle &paddle, Ball &ball) {
00135     int add = 2;
00136     paddle.setW(paddle.getW()+add);
00137 }
00138 
00139 void PaddleSpeedPUpType::giveBonus(Paddle &paddle, Ball &ball) {
00140     float add = 0.2f;
00141     paddle.setSpeed(paddle.getSpeed() + add);
00142 }
00143 
00144 void BallSpeedPUpType::giveBonus(Paddle &paddle, Ball &ball) {
00145     float multiply = 0.9f;
00146     Vector2D& v = ball.getVelocity();
00147     
00148     // 1. create variable speed = magnitude (length) of v
00149     // 2. change speed by ...
00150     // 3. Then normalize v and multiply by speed
00151     float oldSpeed = sqrt(v.x*v.x + v.y*v.y);
00152     float speed = oldSpeed * multiply;
00153     
00154     v.x = (v.x / oldSpeed) * speed;
00155     v.y = (v.y / oldSpeed) * speed;
00156     
00157 }
00158 
00159 // Map
00160 
00161 Map::Map()
00162 {
00163     score = 0;                      // Initial score is zero 
00164     levels.push_back(new Level1()); // Stores level 1 in the vector 
00165     levels.push_back(new Level2()); // Stores level 2 in the vector 
00166     levels.push_back(new Level3()); // Stores level 3 in the vector 
00167     reset();                        // Initializes map 
00168 }
00169 
00170 
00171 Map::~Map()
00172 {
00173 
00174 }
00175 
00176 void Map::initBricks()
00177 {
00178     bricks.clear();
00179 
00180     Level *level = levels[currentLevel];
00181     level->initBricks(*this);
00182 }
00183 
00184 void Map::drawMap(N5110 &lcd)
00185 {   
00186     vector<Brick>::size_type end = bricks.size();
00187     for (int i = 0; i < end; i++) {
00188         const Brick& b = bricks[i];
00189         lcd.drawRect(b.x,b.y,b.w,b.h,FILL_BLACK);
00190     }
00191     
00192     
00193     for (int i = 0; i < powerUps.size(); i++) {
00194         powerUps[i].draw(lcd);
00195     }
00196 }
00197 
00198 //See: https://stackoverflow.com/questions/31022269/collision-detection-between-two-rectangles-in-java
00199 bool rectIntersect(
00200     int Ax, int Ay, int Aw, int Ah,
00201     float Bx, float By, float Bw, float Bh)
00202 {
00203     return
00204         Bx + Bw > Ax &&
00205         By + Bh > Ay &&
00206         Ax + Aw > Bx &&
00207         Ay + Ah > By;
00208 }
00209 
00210 //Normals to each side of the rectangle
00211 const Vector2D Up = {0, -1};
00212 const Vector2D Down = {0, 1};
00213 const Vector2D Left = {-1, 0};
00214 const Vector2D Right = {1, 0};
00215 
00216 //See: https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
00217 // r = d - 2(d dot n)n
00218 void reflect(Vector2D &d, const Vector2D &n)
00219 {
00220     float dotProd = d.x * n.x + d.y * n.y;
00221     float s = 2 * dotProd;
00222 
00223     d.x = d.x - s * n.x;
00224     d.y = d.y - s * n.y;
00225 }
00226 
00227 void Map::resolveCollision(const Brick &b, GameObject &obj)
00228 {
00229     // take velocity of the ball to determine direction and previous coords 
00230     float vx = obj.getVelocity().x;
00231     float vy = obj.getVelocity().y;
00232     // take the previous x and y coords 
00233     float x = obj.getPos().x - vx;
00234     float y = obj.getPos().y - vy;
00235     // sides of the bricks 
00236     float leftX = b.x;
00237     float rightX = b.x + b.w;
00238 
00239     // mid of x and y coords
00240     //float cx = b.x + b.w/2.0f; not used
00241     float cy = b.y + b.h/2.0f;
00242 
00243     
00244     Vector2D &vel = obj.getVelocity();
00245     float thresh = 0.1;
00246     // hit right 
00247     if (x > rightX - thresh) {
00248         reflect(vel, Right);
00249     } 
00250     // hit left
00251     else if (x < leftX + thresh) {
00252         reflect(vel, Left);
00253     } 
00254     // hit top
00255     else if (y < cy) {
00256         reflect(vel, Up);
00257     } 
00258     // hit bottom
00259     else if (y > cy) {
00260         reflect(vel, Down);
00261     } 
00262     else {
00263         // hit top
00264         if (vy > 0) {
00265             reflect(vel, Up);
00266         } 
00267         // hit bottom
00268         else {
00269             reflect(vel, Down);
00270         }
00271     }
00272 }
00273 
00274 void Map::checkCollision(Ball &ball, Paddle &paddle)
00275 {
00276     // Check all bricks 
00277     vector<Brick>::size_type end = bricks.size();
00278     for (int i = 0; i < end; i++) {
00279         const Brick& b = bricks[i];
00280         if (rectIntersect(b.x, b.y, b.w, b.h,
00281                           ball.getPos().x, ball.getPos().y, ball.getW(), ball.getH())) {
00282             // Brick collision event! 
00283             
00284             // Bounce the ball 
00285             resolveCollision(b, ball);
00286             
00287             // (maybe) spawn power-up 
00288             onBrickHit(b);
00289             
00290             // Remove brick 
00291             bricks.erase(bricks.begin() + i);
00292             
00293             // Increment score 
00294             score = score + 10;
00295             break;
00296         
00297         }
00298     }
00299     
00300     // Check all power ups 
00301     for (int i = 0; i < powerUps.size(); i++) 
00302     {
00303         PowerUp& p = powerUps[i];
00304         // use rectIntersect to check for collisions between power-up and pad 
00305         if (rectIntersect(p.getPos().x, p.getPos().y, p.getW(), p.getH(),
00306                           paddle.getPos().x, paddle.getPos().y, paddle.getW(), paddle.getH())) {
00307             // If collided give bonus and remove powerup 
00308             p.giveBonus(paddle, ball);                
00309             powerUps.erase(&p);
00310             
00311             break;             
00312         }
00313                           
00314     }
00315 }
00316 
00317 void Map::onBrickHit(const Brick& brick) {
00318     // spawn power up 
00319     if ((rand() % 100) < PowerUpDropChancePct) {
00320         
00321         int type = rand() % 3;  // each power up has the same rarity 
00322         
00323         //printf("Power up - t=%d", type);
00324         PowerUpType& pUpType = *PowerUpTypes[type]; // assign the pUpType to the type we got 
00325         
00326         //printf(", pUpType=%d\n", pUpType.type);
00327         
00328         // store the powerup in the powerups vector 
00329         powerUps.push_back( 
00330             PowerUp(brick.x+(brick.w/2)-PowerUpW/2, brick.y, pUpType)
00331         );
00332        }
00333 }
00334 
00335 void Map::update() {
00336     for (int i = 0; i < powerUps.size(); i++) {
00337         powerUps[i].move();
00338     }
00339 }
00340 
00341 bool Map::checkLevel()
00342 {   
00343     // cleared level 
00344     if (bricks.size() == 0) {
00345         ++currentLevel;     // increment to next level 
00346         // printf("cleared level! %d %d\n", currentLevel, hasWon());
00347         if (!hasWon()) {
00348             powerUps.clear();
00349             initBricks();   // initialize next level 
00350         }
00351         return true;
00352     }
00353     return false;
00354 }
00355 
00356 void Map::reset()
00357 {
00358     score = 0;
00359     currentLevel = 0;
00360     initBricks();
00361     powerUps.clear();
00362 }