Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Thu Jul 14 2022 02:02:53 by
1.7.2