Kostadin Chakarov / Mbed 2 deprecated el17kec

Dependencies:   mbed

Committer:
kocemax
Date:
Wed May 08 13:49:01 2019 +0000
Revision:
8:9b77eea95088
Parent:
7:cd3cafda3dd4
Child:
9:f720f5d87420
Finally, implemented power ups and fixed the angles after pad collision. Also started commenting, not much time left, so will finish the commenting and if I have more time will add a couple more 'negative' power ups.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kocemax 5:12c179da4788 1 #include "Map.h"
kocemax 6:39bda45efeed 2 #include "Ball.h"
kocemax 5:12c179da4788 3
kocemax 8:9b77eea95088 4 // Levels
kocemax 8:9b77eea95088 5
kocemax 7:cd3cafda3dd4 6 void Level1::initBricks(Map & map)
kocemax 7:cd3cafda3dd4 7 {
kocemax 7:cd3cafda3dd4 8 int w = 41;
kocemax 7:cd3cafda3dd4 9 int h = 2;
kocemax 7:cd3cafda3dd4 10 int gap = 1;
kocemax 7:cd3cafda3dd4 11 int y = 0;
kocemax 8:9b77eea95088 12 for (int j = 0; j < 9; ++j) {
kocemax 7:cd3cafda3dd4 13 int x = 0;
kocemax 7:cd3cafda3dd4 14 for (int i = 0; i < 2; ++i) {
kocemax 7:cd3cafda3dd4 15 Brick b;
kocemax 7:cd3cafda3dd4 16 b.x = x;
kocemax 7:cd3cafda3dd4 17 b.y = y;
kocemax 7:cd3cafda3dd4 18 b.w = w;
kocemax 7:cd3cafda3dd4 19 b.h = h;
kocemax 7:cd3cafda3dd4 20 map.addBrick(b);
kocemax 7:cd3cafda3dd4 21
kocemax 7:cd3cafda3dd4 22 x += w + gap;
kocemax 7:cd3cafda3dd4 23 }
kocemax 7:cd3cafda3dd4 24 y += h + gap;
kocemax 7:cd3cafda3dd4 25 }
kocemax 7:cd3cafda3dd4 26 }
kocemax 7:cd3cafda3dd4 27
kocemax 7:cd3cafda3dd4 28 void Level2::initBricks(Map & map)
kocemax 7:cd3cafda3dd4 29 {
kocemax 8:9b77eea95088 30 int w = 20;
kocemax 8:9b77eea95088 31 int h = 2;
kocemax 7:cd3cafda3dd4 32 int gap = 1;
kocemax 7:cd3cafda3dd4 33 int y = 0;
kocemax 7:cd3cafda3dd4 34
kocemax 8:9b77eea95088 35 for (int j = 0; j < 9; ++j) {
kocemax 7:cd3cafda3dd4 36 int x = 0;
kocemax 8:9b77eea95088 37 for (int i = 0; i < 4; ++i) {
kocemax 7:cd3cafda3dd4 38 Brick b;
kocemax 7:cd3cafda3dd4 39 b.x = x;
kocemax 7:cd3cafda3dd4 40 b.y = y;
kocemax 7:cd3cafda3dd4 41 b.w = w;
kocemax 7:cd3cafda3dd4 42 b.h = h;
kocemax 7:cd3cafda3dd4 43 map.addBrick(b);
kocemax 7:cd3cafda3dd4 44
kocemax 7:cd3cafda3dd4 45 x += w + gap;
kocemax 7:cd3cafda3dd4 46 }
kocemax 7:cd3cafda3dd4 47 y += h + gap;
kocemax 7:cd3cafda3dd4 48 }
kocemax 7:cd3cafda3dd4 49 }
kocemax 7:cd3cafda3dd4 50
kocemax 5:12c179da4788 51
kocemax 8:9b77eea95088 52 // Power-Ups
kocemax 8:9b77eea95088 53
kocemax 8:9b77eea95088 54
kocemax 8:9b77eea95088 55 // rows,cols
kocemax 8:9b77eea95088 56 int powerUpPaddleSizeSprite[PowerUpH][PowerUpW] = {
kocemax 8:9b77eea95088 57 { 0,1,0 },
kocemax 8:9b77eea95088 58 { 1,1,1 },
kocemax 8:9b77eea95088 59 { 0,1,0 },
kocemax 8:9b77eea95088 60 { 1,1,1 }
kocemax 8:9b77eea95088 61 };
kocemax 8:9b77eea95088 62
kocemax 8:9b77eea95088 63 // rows,cols
kocemax 8:9b77eea95088 64 int powerUpPaddleSpeedSprite[PowerUpH][PowerUpW] = {
kocemax 8:9b77eea95088 65 { 0,1,0 },
kocemax 8:9b77eea95088 66 { 0,1,0 },
kocemax 8:9b77eea95088 67 { 1,1,1 },
kocemax 8:9b77eea95088 68 { 1,1,1 }
kocemax 8:9b77eea95088 69 };
kocemax 8:9b77eea95088 70
kocemax 8:9b77eea95088 71 // rows,cols
kocemax 8:9b77eea95088 72 int powerUpBallSpeedSprite[PowerUpH][PowerUpW] = {
kocemax 8:9b77eea95088 73 { 0,1,0 },
kocemax 8:9b77eea95088 74 { 1,1,1 },
kocemax 8:9b77eea95088 75 { 1,1,1 },
kocemax 8:9b77eea95088 76 { 0,1,0 }
kocemax 8:9b77eea95088 77 };
kocemax 8:9b77eea95088 78
kocemax 8:9b77eea95088 79 void PowerUpType::draw(N5110 &lcd, PowerUp &pUp) {
kocemax 8:9b77eea95088 80 //printf("%f, %f; %d,%d - %d\n", pUp.getPos().x,pUp.getPos().y,pUp.getH(),pUp.getW(), (int)((int*)sprite));
kocemax 8:9b77eea95088 81 lcd.drawSprite(pUp.getPos().x,pUp.getPos().y,pUp.getH(),pUp.getW(), (int*)sprite);
kocemax 8:9b77eea95088 82 }
kocemax 8:9b77eea95088 83
kocemax 8:9b77eea95088 84 PowerUpType* PowerUpTypes[3] = {
kocemax 8:9b77eea95088 85 new PaddleSizePUpType(0, *powerUpPaddleSizeSprite),
kocemax 8:9b77eea95088 86 new PaddleSpeedPUpType(1, *powerUpPaddleSpeedSprite),
kocemax 8:9b77eea95088 87 new BallSpeedPUpType(2, *powerUpBallSpeedSprite)
kocemax 8:9b77eea95088 88 };
kocemax 8:9b77eea95088 89
kocemax 8:9b77eea95088 90 PowerUp::PowerUp(float x, float y, PowerUpType& pUpType) : _pUpType(&pUpType)
kocemax 8:9b77eea95088 91 {
kocemax 8:9b77eea95088 92 pos.x = x;
kocemax 8:9b77eea95088 93 pos.y = y;
kocemax 8:9b77eea95088 94 velocity.x = 0;
kocemax 8:9b77eea95088 95 velocity.y = 0.5f;
kocemax 8:9b77eea95088 96 w = PowerUpW;
kocemax 8:9b77eea95088 97 h = PowerUpH;
kocemax 8:9b77eea95088 98 }
kocemax 8:9b77eea95088 99
kocemax 8:9b77eea95088 100
kocemax 8:9b77eea95088 101 void PowerUp::draw(N5110 &lcd) {
kocemax 8:9b77eea95088 102 //printf("powerup %.02f , %.02f, %d\n", pos.x, pos.y, powerUpSprite[0][2]);
kocemax 8:9b77eea95088 103 _pUpType->draw(lcd, *this);
kocemax 8:9b77eea95088 104 }
kocemax 8:9b77eea95088 105
kocemax 8:9b77eea95088 106 void PaddleSizePUpType::giveBonus(Paddle &paddle, Ball &ball) {
kocemax 8:9b77eea95088 107 int add = 2;
kocemax 8:9b77eea95088 108 paddle.setW(paddle.getW()+add);
kocemax 8:9b77eea95088 109 }
kocemax 8:9b77eea95088 110
kocemax 8:9b77eea95088 111 void PaddleSpeedPUpType::giveBonus(Paddle &paddle, Ball &ball) {
kocemax 8:9b77eea95088 112 float add = 0.2f;
kocemax 8:9b77eea95088 113 paddle.setSpeed(paddle.getSpeed() + add);
kocemax 8:9b77eea95088 114 }
kocemax 8:9b77eea95088 115
kocemax 8:9b77eea95088 116 void BallSpeedPUpType::giveBonus(Paddle &paddle, Ball &ball) {
kocemax 8:9b77eea95088 117 float multiply = 0.9f;
kocemax 8:9b77eea95088 118 Vector2D& v = ball.getVelocity();
kocemax 8:9b77eea95088 119
kocemax 8:9b77eea95088 120 // 1. create variable speed = magnitude (length) of v
kocemax 8:9b77eea95088 121 // 2. change speed by ...
kocemax 8:9b77eea95088 122 // 3. Then normalize v and multiply by speed
kocemax 8:9b77eea95088 123 float oldSpeed = sqrt(v.x*v.x + v.y*v.y);
kocemax 8:9b77eea95088 124 float speed = oldSpeed * multiply;
kocemax 8:9b77eea95088 125
kocemax 8:9b77eea95088 126 v.x = (v.x / oldSpeed) * speed;
kocemax 8:9b77eea95088 127 v.y = (v.y / oldSpeed) * speed;
kocemax 8:9b77eea95088 128
kocemax 8:9b77eea95088 129 }
kocemax 8:9b77eea95088 130
kocemax 8:9b77eea95088 131 // Map
kocemax 8:9b77eea95088 132
kocemax 8:9b77eea95088 133 /** Constructor */
kocemax 5:12c179da4788 134 Map::Map()
kocemax 5:12c179da4788 135 {
kocemax 7:cd3cafda3dd4 136 levels.push_back(new Level1());
kocemax 7:cd3cafda3dd4 137 levels.push_back(new Level2());
kocemax 7:cd3cafda3dd4 138 reset();
kocemax 5:12c179da4788 139 }
kocemax 5:12c179da4788 140
kocemax 7:cd3cafda3dd4 141
kocemax 8:9b77eea95088 142 /** Destructor */
kocemax 5:12c179da4788 143 Map::~Map()
kocemax 5:12c179da4788 144 {
kocemax 5:12c179da4788 145
kocemax 5:12c179da4788 146 }
kocemax 5:12c179da4788 147
kocemax 6:39bda45efeed 148 void Map::initBricks()
kocemax 5:12c179da4788 149 {
kocemax 7:cd3cafda3dd4 150 bricks.clear();
kocemax 7:cd3cafda3dd4 151
kocemax 8:9b77eea95088 152 Level *level = levels[currentLevel];
kocemax 7:cd3cafda3dd4 153 level->initBricks(*this);
kocemax 6:39bda45efeed 154 }
kocemax 6:39bda45efeed 155
kocemax 7:cd3cafda3dd4 156 void Map::drawMap(N5110 &lcd)
kocemax 8:9b77eea95088 157 {
kocemax 6:39bda45efeed 158 vector<Brick>::size_type end = bricks.size();
kocemax 7:cd3cafda3dd4 159 for (int i = 0; i < end; i++) {
kocemax 6:39bda45efeed 160 const Brick& b = bricks[i];
kocemax 6:39bda45efeed 161 lcd.drawRect(b.x,b.y,b.w,b.h,FILL_BLACK);
kocemax 6:39bda45efeed 162 }
kocemax 8:9b77eea95088 163
kocemax 8:9b77eea95088 164
kocemax 8:9b77eea95088 165 for (int i = 0; i < powerUps.size(); i++) {
kocemax 8:9b77eea95088 166 powerUps[i].draw(lcd);
kocemax 8:9b77eea95088 167 }
kocemax 6:39bda45efeed 168 }
kocemax 7:cd3cafda3dd4 169 //See: https://stackoverflow.com/questions/31022269/collision-detection-between-two-rectangles-in-java
kocemax 7:cd3cafda3dd4 170 bool rectIntersect(
kocemax 7:cd3cafda3dd4 171 int Ax, int Ay, int Aw, int Ah,
kocemax 7:cd3cafda3dd4 172 float Bx, float By, float Bw, float Bh)
kocemax 7:cd3cafda3dd4 173 {
kocemax 7:cd3cafda3dd4 174 return
kocemax 7:cd3cafda3dd4 175 Bx + Bw > Ax &&
kocemax 7:cd3cafda3dd4 176 By + Bh > Ay &&
kocemax 7:cd3cafda3dd4 177 Ax + Aw > Bx &&
kocemax 7:cd3cafda3dd4 178 Ay + Ah > By;
kocemax 7:cd3cafda3dd4 179 }
kocemax 6:39bda45efeed 180
kocemax 7:cd3cafda3dd4 181 //Normals to each side of the rectangle
kocemax 7:cd3cafda3dd4 182 const Vector2D Up = {0, -1};
kocemax 7:cd3cafda3dd4 183 const Vector2D Down = {0, 1};
kocemax 7:cd3cafda3dd4 184 const Vector2D Left = {-1, 0};
kocemax 7:cd3cafda3dd4 185 const Vector2D Right = {1, 0};
kocemax 7:cd3cafda3dd4 186
kocemax 7:cd3cafda3dd4 187 //See: https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
kocemax 7:cd3cafda3dd4 188 // r = d - 2(d dot n)n
kocemax 7:cd3cafda3dd4 189 void reflect(Vector2D &d, const Vector2D &n)
kocemax 7:cd3cafda3dd4 190 {
kocemax 7:cd3cafda3dd4 191 float dotProd = d.x * n.x + d.y * n.y;
kocemax 7:cd3cafda3dd4 192 float s = 2 * dotProd;
kocemax 7:cd3cafda3dd4 193
kocemax 7:cd3cafda3dd4 194 d.x = d.x - s * n.x;
kocemax 7:cd3cafda3dd4 195 d.y = d.y - s * n.y;
kocemax 7:cd3cafda3dd4 196 }
kocemax 7:cd3cafda3dd4 197
kocemax 7:cd3cafda3dd4 198 void Map::resolveCollision(const Brick &b, GameObject &obj)
kocemax 6:39bda45efeed 199 {
kocemax 7:cd3cafda3dd4 200 // take velocity of the ball to determine direction and previous coords
kocemax 7:cd3cafda3dd4 201 float vx = obj.getVelocity().x;
kocemax 7:cd3cafda3dd4 202 float vy = obj.getVelocity().y;
kocemax 7:cd3cafda3dd4 203 // take the previous x and y coords
kocemax 7:cd3cafda3dd4 204 float x = obj.getPos().x - vx;
kocemax 7:cd3cafda3dd4 205 float y = obj.getPos().y - vy;
kocemax 7:cd3cafda3dd4 206 // sides of the bricks
kocemax 7:cd3cafda3dd4 207 float leftX = b.x;
kocemax 7:cd3cafda3dd4 208 float rightX = b.x + b.w;
kocemax 7:cd3cafda3dd4 209 //float topY = b.y;
kocemax 7:cd3cafda3dd4 210 //float bottomY = b.y + b.h;
kocemax 7:cd3cafda3dd4 211
kocemax 7:cd3cafda3dd4 212 // mid of x and y coords
kocemax 7:cd3cafda3dd4 213 //float cx = b.x + b.w/2.0f;
kocemax 7:cd3cafda3dd4 214 float cy = b.y + b.h/2.0f;
kocemax 7:cd3cafda3dd4 215
kocemax 7:cd3cafda3dd4 216 Vector2D &vel = obj.getVelocity();
kocemax 7:cd3cafda3dd4 217 float thresh = 0.1;
kocemax 7:cd3cafda3dd4 218 if (x > rightX - thresh) {
kocemax 7:cd3cafda3dd4 219 // hit right
kocemax 7:cd3cafda3dd4 220 reflect(vel, Right);
kocemax 7:cd3cafda3dd4 221 } else if (x < leftX + thresh) {
kocemax 7:cd3cafda3dd4 222 // hit left
kocemax 7:cd3cafda3dd4 223 reflect(vel, Left);
kocemax 7:cd3cafda3dd4 224 } else if (y < cy) {
kocemax 7:cd3cafda3dd4 225 // hit top
kocemax 7:cd3cafda3dd4 226 reflect(vel, Up);
kocemax 7:cd3cafda3dd4 227 } else if (y > cy) {
kocemax 7:cd3cafda3dd4 228 // hit bottom
kocemax 7:cd3cafda3dd4 229 reflect(vel, Down);
kocemax 7:cd3cafda3dd4 230 } else {
kocemax 7:cd3cafda3dd4 231 if (vy > 0) {
kocemax 7:cd3cafda3dd4 232 // hit top
kocemax 7:cd3cafda3dd4 233 reflect(vel, Up);
kocemax 7:cd3cafda3dd4 234 } else {
kocemax 7:cd3cafda3dd4 235 // hit bottom
kocemax 7:cd3cafda3dd4 236 reflect(vel, Down);
kocemax 7:cd3cafda3dd4 237 }
kocemax 7:cd3cafda3dd4 238 }
kocemax 6:39bda45efeed 239 }
kocemax 6:39bda45efeed 240
kocemax 8:9b77eea95088 241 void Map::checkCollision(Ball &ball, Paddle &paddle)
kocemax 6:39bda45efeed 242 {
kocemax 8:9b77eea95088 243 // check bricks
kocemax 6:39bda45efeed 244 vector<Brick>::size_type end = bricks.size();
kocemax 7:cd3cafda3dd4 245 for (int i = 0; i < end; i++) {
kocemax 6:39bda45efeed 246 const Brick& b = bricks[i];
kocemax 7:cd3cafda3dd4 247 if (rectIntersect(b.x, b.y, b.w, b.h,
kocemax 8:9b77eea95088 248 ball.getPos().x, ball.getPos().y, ball.getW(), ball.getH())) {
kocemax 8:9b77eea95088 249 // brick collision event!
kocemax 8:9b77eea95088 250
kocemax 8:9b77eea95088 251 // bounce the ball
kocemax 8:9b77eea95088 252 resolveCollision(b, ball);
kocemax 8:9b77eea95088 253
kocemax 8:9b77eea95088 254 // (maybe) spawn power-up
kocemax 8:9b77eea95088 255 onBrickHit(b);
kocemax 8:9b77eea95088 256
kocemax 8:9b77eea95088 257 // remove brick
kocemax 6:39bda45efeed 258 bricks.erase(bricks.begin() + i);
kocemax 8:9b77eea95088 259
kocemax 6:39bda45efeed 260 break;
kocemax 8:9b77eea95088 261
kocemax 5:12c179da4788 262 }
kocemax 5:12c179da4788 263 }
kocemax 8:9b77eea95088 264
kocemax 8:9b77eea95088 265 /** check power ups */
kocemax 8:9b77eea95088 266 for (int i = 0; i < powerUps.size(); i++)
kocemax 8:9b77eea95088 267 {
kocemax 8:9b77eea95088 268 PowerUp& p = powerUps[i];
kocemax 8:9b77eea95088 269 /** use rectIntersect to check for collisions between power-up and pad */
kocemax 8:9b77eea95088 270 if (rectIntersect(p.getPos().x, p.getPos().y, p.getW(), p.getH(),
kocemax 8:9b77eea95088 271 paddle.getPos().x, paddle.getPos().y, paddle.getW(), paddle.getH())) {
kocemax 8:9b77eea95088 272
kocemax 8:9b77eea95088 273 p.giveBonus(paddle, ball);
kocemax 8:9b77eea95088 274
kocemax 8:9b77eea95088 275 powerUps.erase(&p);
kocemax 8:9b77eea95088 276 break;
kocemax 8:9b77eea95088 277 }
kocemax 8:9b77eea95088 278
kocemax 8:9b77eea95088 279 }
kocemax 8:9b77eea95088 280 }
kocemax 8:9b77eea95088 281
kocemax 8:9b77eea95088 282 void Map::onBrickHit(const Brick& brick) {
kocemax 8:9b77eea95088 283 if ((rand() % 100) < PowerUpDropChancePct) {
kocemax 8:9b77eea95088 284 // spawn power up
kocemax 8:9b77eea95088 285 int type = rand() % 3; // each power up has the same rarity
kocemax 8:9b77eea95088 286
kocemax 8:9b77eea95088 287 //printf("Power up - t=%d", type);
kocemax 8:9b77eea95088 288 PowerUpType& pUpType = *PowerUpTypes[type];
kocemax 8:9b77eea95088 289
kocemax 8:9b77eea95088 290 //printf(", pUpType=%d\n", pUpType.type);
kocemax 8:9b77eea95088 291
kocemax 8:9b77eea95088 292 powerUps.push_back(
kocemax 8:9b77eea95088 293 PowerUp(brick.x+(brick.w/2)-PowerUpW/2, brick.y, pUpType)
kocemax 8:9b77eea95088 294 );
kocemax 8:9b77eea95088 295 }
kocemax 8:9b77eea95088 296 }
kocemax 8:9b77eea95088 297
kocemax 8:9b77eea95088 298 void Map::update() {
kocemax 8:9b77eea95088 299 for (int i = 0; i < powerUps.size(); i++) {
kocemax 8:9b77eea95088 300 powerUps[i].move();
kocemax 8:9b77eea95088 301 }
kocemax 5:12c179da4788 302 }
kocemax 5:12c179da4788 303
kocemax 7:cd3cafda3dd4 304 bool Map::checkLevel()
kocemax 7:cd3cafda3dd4 305 {
kocemax 7:cd3cafda3dd4 306 if (bricks.size() == 0) {
kocemax 7:cd3cafda3dd4 307 // cleared level
kocemax 7:cd3cafda3dd4 308 ++currentLevel;
kocemax 8:9b77eea95088 309 // printf("cleared level! %d %d\n", currentLevel, hasWon());
kocemax 7:cd3cafda3dd4 310 if (!hasWon()) {
kocemax 7:cd3cafda3dd4 311 // initialize next level
kocemax 7:cd3cafda3dd4 312 initBricks();
kocemax 5:12c179da4788 313 }
kocemax 7:cd3cafda3dd4 314 return true;
kocemax 5:12c179da4788 315 }
kocemax 7:cd3cafda3dd4 316 return false;
kocemax 7:cd3cafda3dd4 317 }
kocemax 7:cd3cafda3dd4 318
kocemax 7:cd3cafda3dd4 319 void Map::reset()
kocemax 7:cd3cafda3dd4 320 {
kocemax 7:cd3cafda3dd4 321 currentLevel = 0;
kocemax 7:cd3cafda3dd4 322 initBricks();
kocemax 8:9b77eea95088 323 powerUps.clear();
kocemax 5:12c179da4788 324 }