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/Map.cpp
- Committer:
- kocemax
- Date:
- 2019-04-10
- Revision:
- 7:cd3cafda3dd4
- Parent:
- 6:39bda45efeed
- Child:
- 8:9b77eea95088
File content as of revision 7:cd3cafda3dd4:
#include "Map.h"
#include "Ball.h"
void Level1::initBricks(Map & map)
{
int w = 41;
int h = 2;
int gap = 1;
int y = 0;
for (int j = 0; j < 7; ++j) {
int x = 0;
for (int i = 0; i < 2; ++i) {
Brick b;
b.x = x;
b.y = y;
b.w = w;
b.h = h;
map.addBrick(b);
x += w + gap;
}
y += h + gap;
}
}
void Level2::initBricks(Map & map)
{
int w = 5;
int h = 1;
int gap = 1;
int y = 0;
for (int j = 0; j < 15; ++j) {
int x = 0;
for (int i = 0; i < 14; ++i) {
Brick b;
b.x = x;
b.y = y;
b.w = w;
b.h = h;
map.addBrick(b);
x += w + gap;
}
y += h + gap;
}
}
// Constructor
Map::Map()
{
levels.push_back(new Level1());
levels.push_back(new Level2());
reset();
}
// Destructor
Map::~Map()
{
}
void Map::initBricks()
{
bricks.clear();
Level* level = levels[currentLevel];
level->initBricks(*this);
}
void Map::drawMap(N5110 &lcd)
{
vector<Brick>::size_type end = bricks.size();
for (int i = 0; i < end; i++) {
const Brick& b = bricks[i];
lcd.drawRect(b.x,b.y,b.w,b.h,FILL_BLACK);
}
}
//See: https://stackoverflow.com/questions/31022269/collision-detection-between-two-rectangles-in-java
bool rectIntersect(
int Ax, int Ay, int Aw, int Ah,
float Bx, float By, float Bw, float Bh)
{
return
Bx + Bw > Ax &&
By + Bh > Ay &&
Ax + Aw > Bx &&
Ay + Ah > By;
}
//Normals to each side of the rectangle
const Vector2D Up = {0, -1};
const Vector2D Down = {0, 1};
const Vector2D Left = {-1, 0};
const Vector2D Right = {1, 0};
//See: https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
// r = d - 2(d dot n)n
void reflect(Vector2D &d, const Vector2D &n)
{
float dotProd = d.x * n.x + d.y * n.y;
float s = 2 * dotProd;
d.x = d.x - s * n.x;
d.y = d.y - s * n.y;
}
void Map::resolveCollision(const Brick &b, GameObject &obj)
{
// take velocity of the ball to determine direction and previous coords
float vx = obj.getVelocity().x;
float vy = obj.getVelocity().y;
// take the previous x and y coords
float x = obj.getPos().x - vx;
float y = obj.getPos().y - vy;
// sides of the bricks
float leftX = b.x;
float rightX = b.x + b.w;
//float topY = b.y;
//float bottomY = b.y + b.h;
// mid of x and y coords
//float cx = b.x + b.w/2.0f;
float cy = b.y + b.h/2.0f;
// distance between ball and rectangle center
//float dx = x - cx;
//float dy = y - cy;
Vector2D &vel = obj.getVelocity();
float thresh = 0.1;
if (x > rightX - thresh) {
// hit right
reflect(vel, Right);
} else if (x < leftX + thresh) {
// hit left
reflect(vel, Left);
} else if (y < cy) {
// hit top
reflect(vel, Up);
} else if (y > cy) {
// hit bottom
reflect(vel, Down);
} else {
if (vy > 0) {
// hit top
reflect(vel, Up);
} else {
// hit bottom
reflect(vel, Down);
}
}
}
void Map::checkCollision(GameObject &obj)
{
vector<Brick>::size_type end = bricks.size();
for (int i = 0; i < end; i++) {
const Brick& b = bricks[i];
if (rectIntersect(b.x, b.y, b.w, b.h,
obj.getPos().x, obj.getPos().y, obj.getW(), obj.getH())) {
resolveCollision(b, obj);
bricks.erase(bricks.begin() + i);
break;
}
}
}
bool Map::checkLevel()
{
if (bricks.size() == 0) {
// cleared level
++currentLevel;
printf("cleared level! %d %d\n", currentLevel, hasWon());
if (!hasWon()) {
// initialize next level
initBricks();
}
return true;
}
return false;
}
void Map::reset()
{
currentLevel = 0;
initBricks();
}