Added Vector2 class to replace sf::Vector2, featuring comparison operator.
This commit is contained in:
parent
602cc605e8
commit
e469211e95
36 changed files with 271 additions and 230 deletions
|
@ -23,14 +23,14 @@ const int Game::FPS_GOAL = 60;
|
||||||
*/
|
*/
|
||||||
Game::Game(tgui::Window& window) :
|
Game::Game(tgui::Window& window) :
|
||||||
mWindow(window),
|
mWindow(window),
|
||||||
mWorldView(sf::Vector2f(0, 0), mWindow.getView().getSize()),
|
mWorldView(Vector2f(0, 0), mWindow.getView().getSize()),
|
||||||
mGenerator(mWorld, mPathfinder),
|
mGenerator(mWorld, mPathfinder),
|
||||||
mQuit(false),
|
mQuit(false),
|
||||||
mPaused(false) {
|
mPaused(false) {
|
||||||
mWindow.setFramerateLimit(FPS_GOAL);
|
mWindow.setFramerateLimit(FPS_GOAL);
|
||||||
mWindow.setKeyRepeatEnabled(false);
|
mWindow.setKeyRepeatEnabled(false);
|
||||||
|
|
||||||
mGenerator.generateCurrentAreaIfNeeded(sf::Vector2f());
|
mGenerator.generateCurrentAreaIfNeeded(Vector2f());
|
||||||
mPlayer = std::shared_ptr<Player>(new Player(mWorld, mPathfinder,
|
mPlayer = std::shared_ptr<Player>(new Player(mWorld, mPathfinder,
|
||||||
mGenerator.getPlayerSpawn()));
|
mGenerator.getPlayerSpawn()));
|
||||||
mPlayer->setLeftGadget(std::shared_ptr<Gadget>(new Heal()));
|
mPlayer->setLeftGadget(std::shared_ptr<Gadget>(new Heal()));
|
||||||
|
@ -221,9 +221,9 @@ Game::keyDown(const sf::Event& event) {
|
||||||
/**
|
/**
|
||||||
* Converts a screen coordinate to a world coordinate.
|
* Converts a screen coordinate to a world coordinate.
|
||||||
*/
|
*/
|
||||||
sf::Vector2<float>
|
Vector2<float>
|
||||||
Game::convertCoordinates(int x, int y) {
|
Game::convertCoordinates(int x, int y) {
|
||||||
return mWindow.mapPixelToCoords(sf::Vector2i(x, y), mWorldView);
|
return mWindow.mapPixelToCoords(Vector2i(x, y), mWorldView);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -36,7 +36,7 @@ private:
|
||||||
void mouseDown(const sf::Event& event);
|
void mouseDown(const sf::Event& event);
|
||||||
void mouseUp(const sf::Event& event);
|
void mouseUp(const sf::Event& event);
|
||||||
|
|
||||||
sf::Vector2<float> convertCoordinates(int x, int y);
|
Vector2<float> convertCoordinates(int x, int y);
|
||||||
void updateGui();
|
void updateGui();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -32,7 +32,7 @@ Pathfinder::astarArea(Area* start, Area* end) const {
|
||||||
assert(start);
|
assert(start);
|
||||||
assert(end);
|
assert(end);
|
||||||
auto heuristic_cost_estimate = [](Area* start, Area* end) {
|
auto heuristic_cost_estimate = [](Area* start, Area* end) {
|
||||||
return thor::length(sf::Vector2f(end->center - start->center));
|
return thor::length(Vector2f(end->center - start->center));
|
||||||
};
|
};
|
||||||
|
|
||||||
std::set<Area*> closed;
|
std::set<Area*> closed;
|
||||||
|
@ -91,37 +91,37 @@ Pathfinder::astarArea(Area* start, Area* end) const {
|
||||||
* @param radius Radius of the moving object.
|
* @param radius Radius of the moving object.
|
||||||
* @return Path from end to start (path from start to end in reverse order).
|
* @return Path from end to start (path from start to end in reverse order).
|
||||||
*/
|
*/
|
||||||
std::vector<sf::Vector2f>
|
std::vector<Vector2f>
|
||||||
Pathfinder::getPath(const sf::Vector2f& start, const sf::Vector2f& end,
|
Pathfinder::getPath(const Vector2f& start, const Vector2f& end,
|
||||||
float radius) const {
|
float radius) const {
|
||||||
if (!getArea(end))
|
if (!getArea(end))
|
||||||
return std::vector<sf::Vector2f>();
|
return std::vector<Vector2f>();
|
||||||
std::vector<Portal*> portals = astarArea(getArea(start), getArea(end));
|
std::vector<Portal*> portals = astarArea(getArea(start), getArea(end));
|
||||||
if (portals.empty())
|
if (portals.empty())
|
||||||
return std::vector<sf::Vector2f>();
|
return std::vector<Vector2f>();
|
||||||
std::vector<sf::Vector2f> path;
|
std::vector<Vector2f> path;
|
||||||
|
|
||||||
path.push_back(end);
|
path.push_back(end);
|
||||||
for (auto p : portals) {
|
for (auto p : portals) {
|
||||||
// Find the point on the line of the portal closest to the previous point.
|
// Find the point on the line of the portal closest to the previous point.
|
||||||
sf::Vector2f startToEnd = sf::Vector2f(p->end - p->start);
|
Vector2f startToEnd = Vector2f(p->end - p->start);
|
||||||
float percentage = thor::dotProduct(startToEnd, path.back() - sf::Vector2f(p->start)) /
|
float percentage = thor::dotProduct(startToEnd, path.back() - Vector2f(p->start)) /
|
||||||
thor::squaredLength(startToEnd);
|
thor::squaredLength(startToEnd);
|
||||||
sf::Vector2f point;
|
Vector2f point;
|
||||||
|
|
||||||
if (percentage < 0 || percentage > 1.0f) {
|
if (percentage < 0 || percentage > 1.0f) {
|
||||||
if (thor::squaredLength(sf::Vector2f(p->start) - path.back()) <
|
if (thor::squaredLength(Vector2f(p->start) - path.back()) <
|
||||||
thor::squaredLength(sf::Vector2f(p->end) - path.back())) {
|
thor::squaredLength(Vector2f(p->end) - path.back())) {
|
||||||
thor::setLength(startToEnd, WALL_DISTANCE_MULTIPLIER * radius);
|
thor::setLength(startToEnd, WALL_DISTANCE_MULTIPLIER * radius);
|
||||||
point = sf::Vector2f(p->start) + startToEnd;
|
point = Vector2f(p->start) + startToEnd;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
thor::setLength(startToEnd, WALL_DISTANCE_MULTIPLIER * radius);
|
thor::setLength(startToEnd, WALL_DISTANCE_MULTIPLIER * radius);
|
||||||
point = sf::Vector2f(p->end) - startToEnd;
|
point = Vector2f(p->end) - startToEnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
point = sf::Vector2f(p->start) + startToEnd * percentage;
|
point = Vector2f(p->start) + startToEnd * percentage;
|
||||||
|
|
||||||
// Take two points on a line orthogonal to the portal.
|
// Take two points on a line orthogonal to the portal.
|
||||||
thor::setLength(startToEnd, radius);
|
thor::setLength(startToEnd, radius);
|
||||||
|
@ -148,7 +148,7 @@ Pathfinder::insertArea(const sf::FloatRect& rect) {
|
||||||
rect.top * Tile::TILE_SIZE.y - Tile::TILE_SIZE.y / 2.0f,
|
rect.top * Tile::TILE_SIZE.y - Tile::TILE_SIZE.y / 2.0f,
|
||||||
rect.width * Tile::TILE_SIZE.x,
|
rect.width * Tile::TILE_SIZE.x,
|
||||||
rect.height * Tile::TILE_SIZE.y);
|
rect.height * Tile::TILE_SIZE.y);
|
||||||
a.center = sf::Vector2f(a.area.left + a.area.width / 2,
|
a.center = Vector2f(a.area.left + a.area.width / 2,
|
||||||
a.area.top + a.area.height / 2);
|
a.area.top + a.area.height / 2);
|
||||||
mAreas.push_back(a);
|
mAreas.push_back(a);
|
||||||
}
|
}
|
||||||
|
@ -174,8 +174,8 @@ Pathfinder::generatePortals() {
|
||||||
.getOverlap(Interval::IntervalFromPoints(other.area.top,
|
.getOverlap(Interval::IntervalFromPoints(other.area.top,
|
||||||
other.area.top + other.area.height));
|
other.area.top + other.area.height));
|
||||||
if (overlap.getLength() > 0) {
|
if (overlap.getLength() > 0) {
|
||||||
portal.start = sf::Vector2f(other.area.left, overlap.start);
|
portal.start = Vector2f(other.area.left, overlap.start);
|
||||||
portal.end = sf::Vector2f(other.area.left, overlap.end);
|
portal.end = Vector2f(other.area.left, overlap.end);
|
||||||
it.portals.push_back(portal);
|
it.portals.push_back(portal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,8 +185,8 @@ Pathfinder::generatePortals() {
|
||||||
.getOverlap(Interval::IntervalFromPoints(other.area.top,
|
.getOverlap(Interval::IntervalFromPoints(other.area.top,
|
||||||
other.area.top + other.area.height));
|
other.area.top + other.area.height));
|
||||||
if (overlap.getLength() > 0) {
|
if (overlap.getLength() > 0) {
|
||||||
portal.start = sf::Vector2f(it.area.left, overlap.start);
|
portal.start = Vector2f(it.area.left, overlap.start);
|
||||||
portal.end = sf::Vector2f(it.area.left, overlap.end);
|
portal.end = Vector2f(it.area.left, overlap.end);
|
||||||
it.portals.push_back(portal);
|
it.portals.push_back(portal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,8 +196,8 @@ Pathfinder::generatePortals() {
|
||||||
.getOverlap(Interval::IntervalFromPoints(other.area.left,
|
.getOverlap(Interval::IntervalFromPoints(other.area.left,
|
||||||
other.area.left + other.area.width));
|
other.area.left + other.area.width));
|
||||||
if (overlap.getLength() > 0) {
|
if (overlap.getLength() > 0) {
|
||||||
portal.start = sf::Vector2f(overlap.start, other.area.top);
|
portal.start = Vector2f(overlap.start, other.area.top);
|
||||||
portal.end = sf::Vector2f(overlap.end, other.area.top);
|
portal.end = Vector2f(overlap.end, other.area.top);
|
||||||
it.portals.push_back(portal);
|
it.portals.push_back(portal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,8 +207,8 @@ Pathfinder::generatePortals() {
|
||||||
.getOverlap(Interval::IntervalFromPoints(other.area.left,
|
.getOverlap(Interval::IntervalFromPoints(other.area.left,
|
||||||
other.area.left + other.area.width));
|
other.area.left + other.area.width));
|
||||||
if (overlap.getLength() > 0) {
|
if (overlap.getLength() > 0) {
|
||||||
portal.start = sf::Vector2f(overlap.start, it.area.top);
|
portal.start = Vector2f(overlap.start, it.area.top);
|
||||||
portal.end = sf::Vector2f(overlap.end, it.area.top);
|
portal.end = Vector2f(overlap.end, it.area.top);
|
||||||
it.portals.push_back(portal);
|
it.portals.push_back(portal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ Pathfinder::generatePortals() {
|
||||||
* Returns the area where point is in.
|
* Returns the area where point is in.
|
||||||
*/
|
*/
|
||||||
Pathfinder::Area*
|
Pathfinder::Area*
|
||||||
Pathfinder::getArea(const sf::Vector2f& point) const {
|
Pathfinder::getArea(const Vector2f& point) const {
|
||||||
for (auto& area : mAreas) {
|
for (auto& area : mAreas) {
|
||||||
if (area.area.contains(point))
|
if (area.area.contains(point))
|
||||||
// Make the return value non-const for convenience.
|
// Make the return value non-const for convenience.
|
||||||
|
@ -236,8 +236,8 @@ Pathfinder::getArea(const sf::Vector2f& point) const {
|
||||||
void
|
void
|
||||||
Pathfinder::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
Pathfinder::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
for (auto& area : mAreas) {
|
for (auto& area : mAreas) {
|
||||||
sf::RectangleShape rect(sf::Vector2f(area.area.width, area.area.height));
|
sf::RectangleShape rect(Vector2f(area.area.width, area.area.height));
|
||||||
rect.setPosition(sf::Vector2f(area.area.left, area.area.top));
|
rect.setPosition(Vector2f(area.area.left, area.area.top));
|
||||||
rect.setFillColor(sf::Color(area.area.width * 30, 127, 0, 96));
|
rect.setFillColor(sf::Color(area.area.width * 30, 127, 0, 96));
|
||||||
target.draw(rect);
|
target.draw(rect);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include <SFML/System.hpp>
|
#include <SFML/System.hpp>
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
#include "util/Vector.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to find paths between points in the world.
|
* Used to find paths between points in the world.
|
||||||
*
|
*
|
||||||
|
@ -25,11 +27,11 @@ private:
|
||||||
public:
|
public:
|
||||||
void insertArea(const sf::FloatRect& rect);
|
void insertArea(const sf::FloatRect& rect);
|
||||||
void generatePortals();
|
void generatePortals();
|
||||||
std::vector<sf::Vector2f> getPath(const sf::Vector2f& start,
|
std::vector<Vector2f> getPath(const Vector2f& start,
|
||||||
const sf::Vector2f& end, float radius) const;
|
const Vector2f& end, float radius) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Area* getArea(const sf::Vector2f& point) const;
|
Area* getArea(const Vector2f& point) const;
|
||||||
std::vector<Portal*> astarArea(Area* start, Area* end) const;
|
std::vector<Portal*> astarArea(Area* start, Area* end) const;
|
||||||
void draw(sf::RenderTarget& target, sf::RenderStates states) const;
|
void draw(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||||
|
|
||||||
|
@ -44,8 +46,8 @@ private:
|
||||||
* Redundant data as portals are saved twice.
|
* Redundant data as portals are saved twice.
|
||||||
*/
|
*/
|
||||||
struct Pathfinder::Portal {
|
struct Pathfinder::Portal {
|
||||||
sf::Vector2f start;
|
Vector2f start;
|
||||||
sf::Vector2f end;
|
Vector2f end;
|
||||||
Area* area;
|
Area* area;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -54,7 +56,7 @@ struct Pathfinder::Portal {
|
||||||
*/
|
*/
|
||||||
struct Pathfinder::Area {
|
struct Pathfinder::Area {
|
||||||
sf::FloatRect area;
|
sf::FloatRect area;
|
||||||
sf::Vector2f center;
|
Vector2f center;
|
||||||
std::vector<Portal> portals;
|
std::vector<Portal> portals;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ World::remove(std::shared_ptr<Sprite> drawable) {
|
||||||
* Returns all characters that are within maxDistance from position.
|
* Returns all characters that are within maxDistance from position.
|
||||||
*/
|
*/
|
||||||
std::vector<std::shared_ptr<Character> >
|
std::vector<std::shared_ptr<Character> >
|
||||||
World::getCharacters(const sf::Vector2f& position, float maxDistance) const {
|
World::getCharacters(const Vector2f& position, float maxDistance) const {
|
||||||
std::vector<std::shared_ptr<Character> > visible;
|
std::vector<std::shared_ptr<Character> > visible;
|
||||||
for (const auto& it : mCharacters) {
|
for (const auto& it : mCharacters) {
|
||||||
if (position == it->getPosition())
|
if (position == it->getPosition())
|
||||||
|
@ -81,7 +81,7 @@ World::step(int elapsed) {
|
||||||
it--;
|
it--;
|
||||||
}
|
}
|
||||||
// Don't run collision tests if sprite is not moving.
|
// Don't run collision tests if sprite is not moving.
|
||||||
else if ((*it)->getSpeed() != sf::Vector2f())
|
else if ((*it)->getSpeed() != Vector2f())
|
||||||
applyMovement(*it, elapsed);
|
applyMovement(*it, elapsed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ World::step(int elapsed) {
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
World::applyMovement(std::shared_ptr<Sprite> sprite, int elapsed) {
|
World::applyMovement(std::shared_ptr<Sprite> sprite, int elapsed) {
|
||||||
sf::Vector2f offset = sprite->getSpeed() * (elapsed / 1000.0f);
|
Vector2f offset = sprite->getSpeed() * (elapsed / 1000.0f);
|
||||||
for (auto w = mDrawables.begin(); w != mDrawables.end(); w++) {
|
for (auto w = mDrawables.begin(); w != mDrawables.end(); w++) {
|
||||||
for (const auto& other : w->second) {
|
for (const auto& other : w->second) {
|
||||||
if (sprite == other)
|
if (sprite == other)
|
||||||
|
@ -158,19 +158,19 @@ World::draw(sf::RenderTarget& target, sf::RenderStates states) const {
|
||||||
* @return True if the ray was not blocked.
|
* @return True if the ray was not blocked.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
World::raycast(const sf::Vector2f& lineStart,
|
World::raycast(const Vector2f& lineStart,
|
||||||
const sf::Vector2f& lineEnd) const {
|
const Vector2f& lineEnd) const {
|
||||||
assert(lineStart != lineEnd);
|
assert(lineStart != lineEnd);
|
||||||
sf::Vector2f lineCenter = lineStart + 0.5f * (lineEnd - lineStart);
|
Vector2f lineCenter = lineStart + 0.5f * (lineEnd - lineStart);
|
||||||
for (const auto& it : mDrawables.at(Sprite::Category::CATEGORY_WORLD)) {
|
for (const auto& it : mDrawables.at(Sprite::Category::CATEGORY_WORLD)) {
|
||||||
if (!it->collisionEnabled(Sprite::CATEGORY_ACTOR))
|
if (!it->collisionEnabled(Sprite::CATEGORY_ACTOR))
|
||||||
continue;
|
continue;
|
||||||
sf::Vector2f axis = it->getPosition() - lineCenter;
|
Vector2f axis = it->getPosition() - lineCenter;
|
||||||
if (axis == sf::Vector2f())
|
if (axis == Vector2f())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
axis = thor::unitVector(axis);
|
axis = thor::unitVector(axis);
|
||||||
sf::Vector2f halfsize = it->getSize() / 2.0f;
|
Vector2f halfsize = it->getSize() / 2.0f;
|
||||||
float rectPosProjected = thor::dotProduct(axis, it->getPosition());
|
float rectPosProjected = thor::dotProduct(axis, it->getPosition());
|
||||||
float lineStartProjected = thor::dotProduct(axis, lineStart);
|
float lineStartProjected = thor::dotProduct(axis, lineStart);
|
||||||
float lineEndProjected = thor::dotProduct(axis, lineEnd);
|
float lineEndProjected = thor::dotProduct(axis, lineEnd);
|
||||||
|
@ -180,7 +180,7 @@ World::raycast(const sf::Vector2f& lineStart,
|
||||||
float rectHalfWidthProjected = std::max(
|
float rectHalfWidthProjected = std::max(
|
||||||
abs(thor::dotProduct(axis, halfsize)),
|
abs(thor::dotProduct(axis, halfsize)),
|
||||||
abs(thor::dotProduct(axis,
|
abs(thor::dotProduct(axis,
|
||||||
sf::Vector2f(halfsize.x, -halfsize.y))));
|
Vector2f(halfsize.x, -halfsize.y))));
|
||||||
Interval line = Interval::IntervalFromPoints(lineStartProjected,
|
Interval line = Interval::IntervalFromPoints(lineStartProjected,
|
||||||
lineEndProjected);
|
lineEndProjected);
|
||||||
Interval rect = Interval::IntervalFromRadius(rectPosProjected,
|
Interval rect = Interval::IntervalFromRadius(rectPosProjected,
|
||||||
|
@ -196,7 +196,7 @@ World::raycast(const sf::Vector2f& lineStart,
|
||||||
* Returns the item closest to position after linear search.
|
* Returns the item closest to position after linear search.
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<Item>
|
std::shared_ptr<Item>
|
||||||
World::getNearestItem(const sf::Vector2f& position) const {
|
World::getNearestItem(const Vector2f& position) const {
|
||||||
std::shared_ptr<Item> closest;
|
std::shared_ptr<Item> closest;
|
||||||
float distance = std::numeric_limits<float>::max();
|
float distance = std::numeric_limits<float>::max();
|
||||||
for (const auto& v : mDrawables) {
|
for (const auto& v : mDrawables) {
|
||||||
|
|
|
@ -28,10 +28,10 @@ public:
|
||||||
void step(int elapsed);
|
void step(int elapsed);
|
||||||
void think(int elapsed);
|
void think(int elapsed);
|
||||||
std::vector<std::shared_ptr<Character> >
|
std::vector<std::shared_ptr<Character> >
|
||||||
getCharacters(const sf::Vector2f& position, float maxDistance) const;
|
getCharacters(const Vector2f& position, float maxDistance) const;
|
||||||
bool raycast(const sf::Vector2f& lineStart,
|
bool raycast(const Vector2f& lineStart,
|
||||||
const sf::Vector2f& lineEnd) const;
|
const Vector2f& lineEnd) const;
|
||||||
std::shared_ptr<Item> getNearestItem(const sf::Vector2f& position) const;
|
std::shared_ptr<Item> getNearestItem(const Vector2f& position) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ const float Character::ITEM_PICKUP_MAX_DISTANCE_SQUARED = 2500.0f;
|
||||||
/**
|
/**
|
||||||
* Saves pointer to this instance in static var for think().
|
* Saves pointer to this instance in static var for think().
|
||||||
*/
|
*/
|
||||||
Character::Character(const sf::Vector2f& position, Category category,
|
Character::Character(const Vector2f& position, Category category,
|
||||||
unsigned short mask, const Yaml& config, World& world,
|
unsigned short mask, const Yaml& config, World& world,
|
||||||
Pathfinder& pathfinder) :
|
Pathfinder& pathfinder) :
|
||||||
Circle(position, category, mask, config),
|
Circle(position, category, mask, config),
|
||||||
|
@ -133,7 +133,7 @@ Character::releaseTrigger() {
|
||||||
* @return True if a path was found.
|
* @return True if a path was found.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
Character::setDestination(const sf::Vector2f& destination) {
|
Character::setDestination(const Vector2f& destination) {
|
||||||
mPath = mPathfinder.getPath(getPosition(), destination, getRadius());
|
mPath = mPathfinder.getPath(getPosition(), destination, getRadius());
|
||||||
return !mPath.empty();
|
return !mPath.empty();
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ Character::move() {
|
||||||
if (thor::length(mPath.back() - getPosition()) < POINT_REACHED_DISTANCE) {
|
if (thor::length(mPath.back() - getPosition()) < POINT_REACHED_DISTANCE) {
|
||||||
mPath.pop_back();
|
mPath.pop_back();
|
||||||
if (mPath.empty())
|
if (mPath.empty())
|
||||||
setSpeed(sf::Vector2f(), 0);
|
setSpeed(Vector2f(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ Character::isMoving() const {
|
||||||
* Tests if a target is visible from the current position.
|
* Tests if a target is visible from the current position.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
Character::isVisible(const sf::Vector2f& target) const {
|
Character::isVisible(const Vector2f& target) const {
|
||||||
return mWorld.raycast(getPosition(), target);
|
return mWorld.raycast(getPosition(), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +284,6 @@ Character::pickUpItem() {
|
||||||
mRightGadget = mLeftGadget;
|
mRightGadget = mLeftGadget;
|
||||||
mLeftGadget = gadget;
|
mLeftGadget = gadget;
|
||||||
}
|
}
|
||||||
// TODO: implement (or just make invisible?)
|
|
||||||
mWorld.remove(item);
|
mWorld.remove(item);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -31,7 +31,7 @@ public:
|
||||||
static const float VISION_DISTANCE;
|
static const float VISION_DISTANCE;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Character(const sf::Vector2f& position, Category category,
|
explicit Character(const Vector2f& position, Category category,
|
||||||
unsigned short mask, const Yaml& config, World& world,
|
unsigned short mask, const Yaml& config, World& world,
|
||||||
Pathfinder& pathfinder);
|
Pathfinder& pathfinder);
|
||||||
virtual ~Character() = 0;
|
virtual ~Character() = 0;
|
||||||
|
@ -45,9 +45,9 @@ protected:
|
||||||
float getMovementSpeed() const;
|
float getMovementSpeed() const;
|
||||||
void pullTrigger();
|
void pullTrigger();
|
||||||
void releaseTrigger();
|
void releaseTrigger();
|
||||||
bool setDestination(const sf::Vector2f& destination);
|
bool setDestination(const Vector2f& destination);
|
||||||
bool isMoving() const;
|
bool isMoving() const;
|
||||||
bool isVisible(const sf::Vector2f& target) const;
|
bool isVisible(const Vector2f& target) const;
|
||||||
std::vector<std::shared_ptr<Character> > getCharacters() const;
|
std::vector<std::shared_ptr<Character> > getCharacters() const;
|
||||||
int getMagazineAmmo() const;
|
int getMagazineAmmo() const;
|
||||||
int getTotalAmmo() const;
|
int getTotalAmmo() const;
|
||||||
|
@ -90,8 +90,8 @@ private:
|
||||||
std::shared_ptr<Weapon> mActiveWeapon;
|
std::shared_ptr<Weapon> mActiveWeapon;
|
||||||
std::shared_ptr<Gadget> mLeftGadget;
|
std::shared_ptr<Gadget> mLeftGadget;
|
||||||
std::shared_ptr<Gadget> mRightGadget;
|
std::shared_ptr<Gadget> mRightGadget;
|
||||||
std::vector<sf::Vector2f> mPath; //< Contains nodes to reach a set destination.
|
std::vector<Vector2f> mPath; //< Contains nodes to reach a set destination.
|
||||||
sf::Vector2f mLastPosition;
|
Vector2f mLastPosition;
|
||||||
Faction mFaction;
|
Faction mFaction;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
#include "Rectangle.h"
|
#include "Rectangle.h"
|
||||||
#include "../util/Yaml.h"
|
#include "../util/Yaml.h"
|
||||||
|
|
||||||
Circle::Circle(const sf::Vector2f& position, Category category,
|
Circle::Circle(const Vector2f& position, Category category,
|
||||||
unsigned short mask, const Yaml& config,
|
unsigned short mask, const Yaml& config,
|
||||||
const sf::Vector2f& direction) :
|
const Vector2f& direction) :
|
||||||
Sprite(position, category, mask, config.get("size", sf::Vector2f()),
|
Sprite(position, category, mask, config.get("size", Vector2f()),
|
||||||
config.get("texture", std::string()), direction) {
|
config.get("texture", std::string()), direction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ Circle::Circle(const sf::Vector2f& position, Category category,
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
Circle::testCollision(std::shared_ptr<Sprite> other,
|
Circle::testCollision(std::shared_ptr<Sprite> other,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond) {
|
Vector2f& offsetFirst, const Vector2f& offsetSecond) {
|
||||||
Rectangle* rect = dynamic_cast<Rectangle*>(other.get());
|
Rectangle* rect = dynamic_cast<Rectangle*>(other.get());
|
||||||
Circle* circle = dynamic_cast<Circle*>(other.get());
|
Circle* circle = dynamic_cast<Circle*>(other.get());
|
||||||
if (circle != nullptr)
|
if (circle != nullptr)
|
||||||
|
|
|
@ -18,13 +18,13 @@ class Yaml;
|
||||||
*/
|
*/
|
||||||
class Circle : public CollisionModel, public Sprite {
|
class Circle : public CollisionModel, public Sprite {
|
||||||
public:
|
public:
|
||||||
explicit Circle(const sf::Vector2f& position, Category category,
|
explicit Circle(const Vector2f& position, Category category,
|
||||||
unsigned short mask, const Yaml& config,
|
unsigned short mask, const Yaml& config,
|
||||||
const sf::Vector2f& direction = sf::Vector2f(0, 0));
|
const Vector2f& direction = Vector2f(0, 0));
|
||||||
virtual ~Circle() = default;
|
virtual ~Circle() = default;
|
||||||
|
|
||||||
bool testCollision(std::shared_ptr<Sprite> other,
|
bool testCollision(std::shared_ptr<Sprite> other,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond);
|
Vector2f& offsetFirst, const Vector2f& offsetSecond);
|
||||||
float getRadius() const;
|
float getRadius() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,10 @@ CollisionModel::~CollisionModel() {
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
CollisionModel::testCollision(const Circle& circle, const Rectangle& rect,
|
CollisionModel::testCollision(const Circle& circle, const Rectangle& rect,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond) {
|
Vector2f& offsetFirst, const Vector2f& offsetSecond) {
|
||||||
sf::Vector2f halfSize = rect.getSize() / 2.0f;
|
Vector2f halfSize = rect.getSize() / 2.0f;
|
||||||
sf::Vector2f rectNewPos = rect.getPosition() + offsetSecond;
|
Vector2f rectNewPos = rect.getPosition() + offsetSecond;
|
||||||
sf::Vector2f circleRotatedPos = circle.getPosition() + offsetFirst - rectNewPos;
|
Vector2f circleRotatedPos = circle.getPosition() + offsetFirst - rectNewPos;
|
||||||
circleRotatedPos = thor::rotatedVector(circleRotatedPos, -rect.mShape.getRotation());
|
circleRotatedPos = thor::rotatedVector(circleRotatedPos, -rect.mShape.getRotation());
|
||||||
circleRotatedPos += rectNewPos;
|
circleRotatedPos += rectNewPos;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ CollisionModel::testCollision(const Circle& circle, const Rectangle& rect,
|
||||||
.getOverlap(Interval::IntervalFromRadius(rectNewPos.y, halfSize.y))
|
.getOverlap(Interval::IntervalFromRadius(rectNewPos.y, halfSize.y))
|
||||||
.getLength();
|
.getLength();
|
||||||
offsetFirst += ((circleRotatedPos.y > rectNewPos.y) ? 1.0f : - 1.0f) *
|
offsetFirst += ((circleRotatedPos.y > rectNewPos.y) ? 1.0f : - 1.0f) *
|
||||||
thor::rotatedVector(sf::Vector2f(0, overlapY), rect.mShape.getRotation());
|
thor::rotatedVector(Vector2f(0, overlapY), rect.mShape.getRotation());
|
||||||
return overlapY > 0;
|
return overlapY > 0;
|
||||||
}
|
}
|
||||||
// Same here (just switched x/y).
|
// Same here (just switched x/y).
|
||||||
|
@ -55,14 +55,14 @@ CollisionModel::testCollision(const Circle& circle, const Rectangle& rect,
|
||||||
.getOverlap(Interval::IntervalFromRadius(rectNewPos.x, halfSize.x))
|
.getOverlap(Interval::IntervalFromRadius(rectNewPos.x, halfSize.x))
|
||||||
.getLength();
|
.getLength();
|
||||||
offsetFirst += ((circleRotatedPos.x > rectNewPos.x) ? 1.0f : - 1.0f) *
|
offsetFirst += ((circleRotatedPos.x > rectNewPos.x) ? 1.0f : - 1.0f) *
|
||||||
thor::rotatedVector(sf::Vector2f(overlapX, 0), rect.mShape.getRotation());
|
thor::rotatedVector(Vector2f(overlapX, 0), rect.mShape.getRotation());
|
||||||
return overlapX > 0;
|
return overlapX > 0;
|
||||||
}
|
}
|
||||||
// Test if the circle is colliding with a corner of the rectangle, using
|
// Test if the circle is colliding with a corner of the rectangle, using
|
||||||
// the same method as circle-circle collision (distance to corner instead
|
// the same method as circle-circle collision (distance to corner instead
|
||||||
// of radius.
|
// of radius.
|
||||||
else {
|
else {
|
||||||
sf::Vector2f axis(thor::unitVector(rectNewPos - circleRotatedPos));
|
Vector2f axis(thor::unitVector(rectNewPos - circleRotatedPos));
|
||||||
|
|
||||||
// Use correct vector for corner projections (positive/negative
|
// Use correct vector for corner projections (positive/negative
|
||||||
// direction does not matter).
|
// direction does not matter).
|
||||||
|
@ -72,7 +72,7 @@ CollisionModel::testCollision(const Circle& circle, const Rectangle& rect,
|
||||||
rectHalfSizeProjected = thor::dotProduct(axis, halfSize);
|
rectHalfSizeProjected = thor::dotProduct(axis, halfSize);
|
||||||
else
|
else
|
||||||
rectHalfSizeProjected = thor::dotProduct(axis,
|
rectHalfSizeProjected = thor::dotProduct(axis,
|
||||||
sf::Vector2f(halfSize.x, -halfSize.y));
|
Vector2f(halfSize.x, -halfSize.y));
|
||||||
|
|
||||||
Interval projectedCircle = Interval::IntervalFromRadius(
|
Interval projectedCircle = Interval::IntervalFromRadius(
|
||||||
thor::dotProduct(axis, circleRotatedPos),
|
thor::dotProduct(axis, circleRotatedPos),
|
||||||
|
@ -100,8 +100,8 @@ CollisionModel::testCollision(const Circle& circle, const Rectangle& rect,
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
CollisionModel::testCollision(const Circle& first, const Circle& second,
|
CollisionModel::testCollision(const Circle& first, const Circle& second,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond) {
|
Vector2f& offsetFirst, const Vector2f& offsetSecond) {
|
||||||
sf::Vector2f axis(thor::unitVector(second.getPosition() + offsetFirst -
|
Vector2f axis(thor::unitVector(second.getPosition() + offsetFirst -
|
||||||
(first.getPosition() + offsetSecond)));
|
(first.getPosition() + offsetSecond)));
|
||||||
Interval projectedFirst = Interval::IntervalFromRadius(
|
Interval projectedFirst = Interval::IntervalFromRadius(
|
||||||
thor::dotProduct(axis, first.getPosition() + offsetFirst),
|
thor::dotProduct(axis, first.getPosition() + offsetFirst),
|
||||||
|
@ -125,6 +125,6 @@ CollisionModel::testCollision(const Circle& first, const Circle& second,
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
CollisionModel::testCollision(const Rectangle& first, const Rectangle& second,
|
CollisionModel::testCollision(const Rectangle& first, const Rectangle& second,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond) {
|
Vector2f& offsetFirst, const Vector2f& offsetSecond) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
class Circle;
|
class Circle;
|
||||||
class Rectangle;
|
class Rectangle;
|
||||||
|
|
||||||
#include <SFML/System.hpp>
|
#include "../util/Vector.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class providing helper functions to test for collisions between shapes.
|
* Abstract class providing helper functions to test for collisions between shapes.
|
||||||
|
@ -24,11 +24,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static bool testCollision(const Circle& circle, const Rectangle& rect,
|
static bool testCollision(const Circle& circle, const Rectangle& rect,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond);
|
Vector2f& offsetFirst, const Vector2f& offsetSecond);
|
||||||
static bool testCollision(const Circle& first, const Circle& second,
|
static bool testCollision(const Circle& first, const Circle& second,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond);
|
Vector2f& offsetFirst, const Vector2f& offsetSecond);
|
||||||
static bool testCollision(const Rectangle& first, const Rectangle& second,
|
static bool testCollision(const Rectangle& first, const Rectangle& second,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond);
|
Vector2f& offsetFirst, const Vector2f& offsetSecond);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DG_COLLISIONMODEL_H_ */
|
#endif /* DG_COLLISIONMODEL_H_ */
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
#include "Circle.h"
|
#include "Circle.h"
|
||||||
#include "../util/Yaml.h"
|
#include "../util/Yaml.h"
|
||||||
|
|
||||||
Rectangle::Rectangle(const sf::Vector2f& position, Category category,
|
Rectangle::Rectangle(const Vector2f& position, Category category,
|
||||||
unsigned short mask, const Yaml& config,
|
unsigned short mask, const Yaml& config,
|
||||||
const sf::Vector2f& direction) :
|
const Vector2f& direction) :
|
||||||
Sprite(position, category, mask, config.get("size", sf::Vector2f()),
|
Sprite(position, category, mask, config.get("size", Vector2f()),
|
||||||
config.get("texture", std::string()), direction) {
|
config.get("texture", std::string()), direction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ Rectangle::Rectangle(const sf::Vector2f& position, Category category,
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
Rectangle::testCollision(std::shared_ptr<Sprite> other,
|
Rectangle::testCollision(std::shared_ptr<Sprite> other,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond) {
|
Vector2f& offsetFirst, const Vector2f& offsetSecond) {
|
||||||
Rectangle* rect = dynamic_cast<Rectangle*>(other.get());
|
Rectangle* rect = dynamic_cast<Rectangle*>(other.get());
|
||||||
Circle* circle = dynamic_cast<Circle*>(other.get());
|
Circle* circle = dynamic_cast<Circle*>(other.get());
|
||||||
if (circle != nullptr)
|
if (circle != nullptr)
|
||||||
|
|
|
@ -18,13 +18,13 @@ class Yaml;
|
||||||
*/
|
*/
|
||||||
class Rectangle : public CollisionModel, public Sprite {
|
class Rectangle : public CollisionModel, public Sprite {
|
||||||
public:
|
public:
|
||||||
explicit Rectangle(const sf::Vector2f& position, Category category,
|
explicit Rectangle(const Vector2f& position, Category category,
|
||||||
unsigned short mask, const Yaml& config,
|
unsigned short mask, const Yaml& config,
|
||||||
const sf::Vector2f& direction = sf::Vector2f(0, 0));
|
const Vector2f& direction = sf::Vector2f(0, 0));
|
||||||
virtual ~Rectangle() = default;
|
virtual ~Rectangle() = default;
|
||||||
|
|
||||||
bool testCollision(std::shared_ptr<Sprite> other,
|
bool testCollision(std::shared_ptr<Sprite> other,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond);
|
Vector2f& offsetFirst, const Vector2f& offsetSecond);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DG_RECTANGLE_H_ */
|
#endif /* DG_RECTANGLE_H_ */
|
||||||
|
|
|
@ -13,14 +13,14 @@
|
||||||
#include "../util/Log.h"
|
#include "../util/Log.h"
|
||||||
#include "../util/ResourceManager.h"
|
#include "../util/ResourceManager.h"
|
||||||
|
|
||||||
Sprite::Sprite(const sf::Vector2f& position, Category category,
|
Sprite::Sprite(const Vector2f& position, Category category,
|
||||||
unsigned short mask, const sf::Vector2f& size,
|
unsigned short mask, const Vector2f& size,
|
||||||
const std::string& texture, const sf::Vector2f& direction) :
|
const std::string& texture, const Vector2f& direction) :
|
||||||
mCategory(category),
|
mCategory(category),
|
||||||
mMask(mask) {
|
mMask(mask) {
|
||||||
mShape.setSize(size);
|
mShape.setSize(size);
|
||||||
mShape.setOrigin(size / 2.0f);
|
mShape.setOrigin(size / 2.0f);
|
||||||
mShape.setTextureRect(sf::IntRect(sf::Vector2i(), sf::Vector2i(size)));
|
mShape.setTextureRect(sf::IntRect(Vector2i(), Vector2i(size)));
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
setDirection(direction);
|
setDirection(direction);
|
||||||
try {
|
try {
|
||||||
|
@ -37,7 +37,7 @@ Sprite::Sprite(const sf::Vector2f& position, Category category,
|
||||||
/**
|
/**
|
||||||
* Returns the position of the sprite (center).
|
* Returns the position of the sprite (center).
|
||||||
*/
|
*/
|
||||||
sf::Vector2f
|
Vector2f
|
||||||
Sprite::getPosition() const {
|
Sprite::getPosition() const {
|
||||||
return mShape.getPosition();
|
return mShape.getPosition();
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ Sprite::getPosition() const {
|
||||||
/**
|
/**
|
||||||
* Returns the movement speed of the sprite.
|
* Returns the movement speed of the sprite.
|
||||||
*/
|
*/
|
||||||
sf::Vector2f
|
Vector2f
|
||||||
Sprite::getSpeed() const {
|
Sprite::getSpeed() const {
|
||||||
return mSpeed;
|
return mSpeed;
|
||||||
}
|
}
|
||||||
|
@ -53,9 +53,9 @@ Sprite::getSpeed() const {
|
||||||
/**
|
/**
|
||||||
* Returns the angle of the sprite.
|
* Returns the angle of the sprite.
|
||||||
*/
|
*/
|
||||||
sf::Vector2f
|
Vector2f
|
||||||
Sprite::getDirection() const {
|
Sprite::getDirection() const {
|
||||||
return thor::rotatedVector(sf::Vector2f(0, - 1), mShape.getRotation());
|
return thor::rotatedVector(Vector2f(0, - 1), mShape.getRotation());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,10 +78,10 @@ Sprite::getCategory() const {
|
||||||
* Returns the size of the sprite as a vector (bottom left to top right),
|
* Returns the size of the sprite as a vector (bottom left to top right),
|
||||||
* does not consider rotation.
|
* does not consider rotation.
|
||||||
*/
|
*/
|
||||||
sf::Vector2f
|
Vector2f
|
||||||
Sprite::getSize() const {
|
Sprite::getSize() const {
|
||||||
sf::FloatRect bounds = mShape.getLocalBounds();
|
sf::FloatRect bounds = mShape.getLocalBounds();
|
||||||
return sf::Vector2f(bounds.width, bounds.height);
|
return Vector2f(bounds.width, bounds.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -127,8 +127,8 @@ Sprite::setDelete(bool value) {
|
||||||
* @param speed Movement speed in pixels per second.
|
* @param speed Movement speed in pixels per second.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Sprite::setSpeed(sf::Vector2f direction, float speed) {
|
Sprite::setSpeed(Vector2f direction, float speed) {
|
||||||
if (direction != sf::Vector2f())
|
if (direction != Vector2f())
|
||||||
thor::setLength(direction, speed);
|
thor::setLength(direction, speed);
|
||||||
mSpeed = direction;
|
mSpeed = direction;
|
||||||
}
|
}
|
||||||
|
@ -138,8 +138,8 @@ Sprite::setSpeed(sf::Vector2f direction, float speed) {
|
||||||
* but is otherwise meaningless.
|
* but is otherwise meaningless.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Sprite::setDirection(const sf::Vector2f& direction) {
|
Sprite::setDirection(const Vector2f& direction) {
|
||||||
if (direction != sf::Vector2f())
|
if (direction != Vector2f())
|
||||||
mShape.setRotation(thor::polarAngle(direction) + 90);
|
mShape.setRotation(thor::polarAngle(direction) + 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +147,6 @@ Sprite::setDirection(const sf::Vector2f& direction) {
|
||||||
* Sets the position of thr Sprite.
|
* Sets the position of thr Sprite.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Sprite::setPosition(const sf::Vector2f& position) {
|
Sprite::setPosition(const Vector2f& position) {
|
||||||
mShape.setPosition(position);
|
mShape.setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
|
|
||||||
|
#include "../util/Vector.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An sprite that is rendered in the world.
|
* An sprite that is rendered in the world.
|
||||||
*/
|
*/
|
||||||
|
@ -38,30 +40,30 @@ public:
|
||||||
|
|
||||||
// Public functions.
|
// Public functions.
|
||||||
public:
|
public:
|
||||||
explicit Sprite(const sf::Vector2f& position, Category category,
|
explicit Sprite(const Vector2f& position, Category category,
|
||||||
unsigned short mask, const sf::Vector2f& size,
|
unsigned short mask, const Vector2f& size,
|
||||||
const std::string& texture, const sf::Vector2f& direction);
|
const std::string& texture, const Vector2f& direction);
|
||||||
virtual ~Sprite() = default;
|
virtual ~Sprite() = default;
|
||||||
|
|
||||||
sf::Vector2f getPosition() const;
|
Vector2f getPosition() const;
|
||||||
sf::Vector2f getSpeed() const;
|
Vector2f getSpeed() const;
|
||||||
sf::Vector2f getDirection() const;
|
Vector2f getDirection() const;
|
||||||
bool getDelete() const;
|
bool getDelete() const;
|
||||||
Category getCategory() const;
|
Category getCategory() const;
|
||||||
sf::Vector2f getSize() const;
|
Vector2f getSize() const;
|
||||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
|
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;
|
||||||
bool collisionEnabled(Category category) const;
|
bool collisionEnabled(Category category) const;
|
||||||
bool isInside(const sf::FloatRect& rect) const;
|
bool isInside(const sf::FloatRect& rect) const;
|
||||||
|
|
||||||
virtual bool testCollision(std::shared_ptr<Sprite> other,
|
virtual bool testCollision(std::shared_ptr<Sprite> other,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond) = 0;
|
Vector2f& offsetFirst, const Vector2f& offsetSecond) = 0;
|
||||||
virtual void onCollide(std::shared_ptr<Sprite> other);
|
virtual void onCollide(std::shared_ptr<Sprite> other);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setDelete(bool value);
|
void setDelete(bool value);
|
||||||
void setSpeed(sf::Vector2f direction, float speed);
|
void setSpeed(Vector2f direction, float speed);
|
||||||
void setDirection(const sf::Vector2f& direction);
|
void setDirection(const Vector2f& direction);
|
||||||
void setPosition(const sf::Vector2f& position);
|
void setPosition(const Vector2f& position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class CollisionModel;
|
friend class CollisionModel;
|
||||||
|
@ -69,7 +71,7 @@ private:
|
||||||
|
|
||||||
sf::RectangleShape mShape;
|
sf::RectangleShape mShape;
|
||||||
std::shared_ptr<sf::Texture> mTexture;
|
std::shared_ptr<sf::Texture> mTexture;
|
||||||
sf::Vector2f mSpeed;
|
Vector2f mSpeed;
|
||||||
Category mCategory;
|
Category mCategory;
|
||||||
unsigned short mMask;
|
unsigned short mMask;
|
||||||
bool mDelete = false;
|
bool mDelete = false;
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
* @param world Box2d world.
|
* @param world Box2d world.
|
||||||
* @param texture Texture to display for bullet.
|
* @param texture Texture to display for bullet.
|
||||||
*/
|
*/
|
||||||
Bullet::Bullet(const sf::Vector2f& position, Character& shooter,
|
Bullet::Bullet(const Vector2f& position, Character& shooter,
|
||||||
sf::Vector2f direction, const Yaml& config, float speed,
|
Vector2f direction, const Yaml& config, float speed,
|
||||||
float damage, float maxRange) :
|
float damage, float maxRange) :
|
||||||
Circle(position, CATEGORY_PARTICLE, ~CATEGORY_PARTICLE,
|
Circle(position, CATEGORY_PARTICLE, ~CATEGORY_PARTICLE,
|
||||||
config, thor::rotatedVector(direction, -90.0f)),
|
config, thor::rotatedVector(direction, -90.0f)),
|
||||||
|
|
|
@ -18,8 +18,8 @@ class Yaml;
|
||||||
*/
|
*/
|
||||||
class Bullet : public Circle {
|
class Bullet : public Circle {
|
||||||
public:
|
public:
|
||||||
explicit Bullet(const sf::Vector2f& position, Character& shooter,
|
explicit Bullet(const Vector2f& position, Character& shooter,
|
||||||
sf::Vector2f direction, const Yaml& config, float speed,
|
Vector2f direction, const Yaml& config, float speed,
|
||||||
float damage, float maxRange);
|
float damage, float maxRange);
|
||||||
|
|
||||||
void onCollide(std::shared_ptr<Sprite> other);
|
void onCollide(std::shared_ptr<Sprite> other);
|
||||||
|
@ -29,7 +29,7 @@ private:
|
||||||
const int mDamage;
|
const int mDamage;
|
||||||
const float mSpeed;
|
const float mSpeed;
|
||||||
const float mMaxRangeSquared;
|
const float mMaxRangeSquared;
|
||||||
sf::Vector2f mStartPoint;
|
Vector2f mStartPoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DG_BULLET_H_ */
|
#endif /* DG_BULLET_H_ */
|
||||||
|
|
|
@ -37,27 +37,24 @@ Generator::Generator(World& world, Pathfinder& pathfinder) :
|
||||||
* GENERATE_AREA_SIZE and GENERATE_AREA_RANGE).
|
* GENERATE_AREA_SIZE and GENERATE_AREA_RANGE).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Generator::generateCurrentAreaIfNeeded(const sf::Vector2f& playerPosition) {
|
Generator::generateCurrentAreaIfNeeded(const Vector2f& playerPosition) {
|
||||||
auto compare = [](const sf::Vector2i& a, const sf::Vector2i& b) {
|
std::map<Vector2i, float> open;
|
||||||
return a.x < b.x || (a.x == b.x && a.y < b.y);
|
std::set<Vector2i> closed;
|
||||||
};
|
|
||||||
std::map<sf::Vector2i, float, decltype(compare)> open(compare);
|
|
||||||
std::set<sf::Vector2i, decltype(compare)> closed(compare);
|
|
||||||
|
|
||||||
sf::Vector2i start((int) floor(playerPosition.x / Tile::TILE_SIZE.x),
|
Vector2i start((int) floor(playerPosition.x / Tile::TILE_SIZE.x),
|
||||||
(int) floor(playerPosition.y / Tile::TILE_SIZE.y));
|
(int) floor(playerPosition.y / Tile::TILE_SIZE.y));
|
||||||
start /= GENERATE_AREA_SIZE;
|
start /= GENERATE_AREA_SIZE;
|
||||||
auto makePair = [&start](const sf::Vector2i& point) {
|
auto makePair = [&start](const Vector2i& point) {
|
||||||
return std::make_pair(point, thor::length(sf::Vector2f(point - start)));
|
return std::make_pair(point, thor::length(Vector2f(point - start)));
|
||||||
};
|
};
|
||||||
|
|
||||||
open.insert(makePair(start));
|
open.insert(makePair(start));
|
||||||
while (!open.empty()) {
|
while (!open.empty()) {
|
||||||
auto intComp = [](const std::pair<sf::Vector2i, float>& left,
|
auto intComp = [](const std::pair<Vector2i, float>& left,
|
||||||
const std::pair<sf::Vector2i, float>& right) {
|
const std::pair<Vector2i, float>& right) {
|
||||||
return left.second < right.second;
|
return left.second < right.second;
|
||||||
};
|
};
|
||||||
sf::Vector2i current =
|
Vector2i current =
|
||||||
std::min_element(open.begin(), open.end(), intComp)->first;
|
std::min_element(open.begin(), open.end(), intComp)->first;
|
||||||
float distance = open[current];
|
float distance = open[current];
|
||||||
open.erase(current);
|
open.erase(current);
|
||||||
|
@ -65,8 +62,8 @@ Generator::generateCurrentAreaIfNeeded(const sf::Vector2f& playerPosition) {
|
||||||
if (!mGenerated[current.x][current.y] && distance <= GENERATE_AREA_RANGE) {
|
if (!mGenerated[current.x][current.y] && distance <= GENERATE_AREA_RANGE) {
|
||||||
mGenerated[current.x][current.y] = true;
|
mGenerated[current.x][current.y] = true;
|
||||||
sf::IntRect area(current * GENERATE_AREA_SIZE -
|
sf::IntRect area(current * GENERATE_AREA_SIZE -
|
||||||
sf::Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE) / 2,
|
Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE) / 2,
|
||||||
sf::Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE));
|
Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE));
|
||||||
generateTiles(area);
|
generateTiles(area);
|
||||||
for (const auto& enemyPosition : getEnemySpawns(area)) {
|
for (const auto& enemyPosition : getEnemySpawns(area)) {
|
||||||
float distance = thor::length(enemyPosition - playerPosition);
|
float distance = thor::length(enemyPosition - playerPosition);
|
||||||
|
@ -76,14 +73,14 @@ Generator::generateCurrentAreaIfNeeded(const sf::Vector2f& playerPosition) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mGenerated[current.x][current.y] && distance <= GENERATE_AREA_RANGE) {
|
if (mGenerated[current.x][current.y] && distance <= GENERATE_AREA_RANGE) {
|
||||||
if (closed.find(sf::Vector2i(current.x + 1, current.y)) == closed.end())
|
if (closed.find(Vector2i(current.x + 1, current.y)) == closed.end())
|
||||||
open.insert(makePair(sf::Vector2i(current.x + 1, current.y)));
|
open.insert(makePair(Vector2i(current.x + 1, current.y)));
|
||||||
if (closed.find(sf::Vector2i(current.x, current.y + 1)) == closed.end())
|
if (closed.find(Vector2i(current.x, current.y + 1)) == closed.end())
|
||||||
open.insert(makePair(sf::Vector2i(current.x, current.y + 1)));
|
open.insert(makePair(Vector2i(current.x, current.y + 1)));
|
||||||
if (closed.find(sf::Vector2i(current.x - 1, current.y)) == closed.end())
|
if (closed.find(Vector2i(current.x - 1, current.y)) == closed.end())
|
||||||
open.insert(makePair(sf::Vector2i(current.x - 1, current.y)));
|
open.insert(makePair(Vector2i(current.x - 1, current.y)));
|
||||||
if (closed.find(sf::Vector2i(current.x, current.y - 1)) == closed.end())
|
if (closed.find(Vector2i(current.x, current.y - 1)) == closed.end())
|
||||||
open.insert(makePair(sf::Vector2i(current.x, current.y - 1)));
|
open.insert(makePair(Vector2i(current.x, current.y - 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,16 +91,16 @@ Generator::generateCurrentAreaIfNeeded(const sf::Vector2f& playerPosition) {
|
||||||
*
|
*
|
||||||
* FIXME: Some nodes are selected more than once.
|
* FIXME: Some nodes are selected more than once.
|
||||||
*/
|
*/
|
||||||
std::vector<sf::Vector2i>
|
std::vector<Vector2i>
|
||||||
Generator::createMinimalSpanningTree(const sf::Vector2i& start,
|
Generator::createMinimalSpanningTree(const Vector2i& start,
|
||||||
const float limit) {
|
const float limit) {
|
||||||
std::vector<sf::Vector2i> open;
|
std::vector<Vector2i> open;
|
||||||
std::vector<sf::Vector2i> selected;
|
std::vector<Vector2i> selected;
|
||||||
open.push_back(start);
|
open.push_back(start);
|
||||||
float totalWeight = 0.0f;
|
float totalWeight = 0.0f;
|
||||||
|
|
||||||
while (totalWeight < limit) {
|
while (totalWeight < limit) {
|
||||||
sf::Vector2i current;
|
Vector2i current;
|
||||||
float minValue = std::numeric_limits<float>::max();
|
float minValue = std::numeric_limits<float>::max();
|
||||||
for (auto& o : open) {
|
for (auto& o : open) {
|
||||||
if (mTileNoise.getNoise(o.x, o.y) + 1.0f < minValue) {
|
if (mTileNoise.getNoise(o.x, o.y) + 1.0f < minValue) {
|
||||||
|
@ -115,15 +112,15 @@ Generator::createMinimalSpanningTree(const sf::Vector2i& start,
|
||||||
selected.push_back(current);
|
selected.push_back(current);
|
||||||
totalWeight += minValue;
|
totalWeight += minValue;
|
||||||
|
|
||||||
auto insertOnlyNew = [&open, &selected](const sf::Vector2i& v) {
|
auto insertOnlyNew = [&open, &selected](const Vector2i& v) {
|
||||||
if (std::find(open.begin(), open.end(), v) == open.end()
|
if (std::find(open.begin(), open.end(), v) == open.end()
|
||||||
&& std::find(selected.begin(), selected.end(), v) == selected.end())
|
&& std::find(selected.begin(), selected.end(), v) == selected.end())
|
||||||
open.push_back(v);
|
open.push_back(v);
|
||||||
};
|
};
|
||||||
insertOnlyNew(sf::Vector2i(current.x + 1, current.y));
|
insertOnlyNew(Vector2i(current.x + 1, current.y));
|
||||||
insertOnlyNew(sf::Vector2i(current.x, current.y + 1));
|
insertOnlyNew(Vector2i(current.x, current.y + 1));
|
||||||
insertOnlyNew(sf::Vector2i(current.x - 1, current.y));
|
insertOnlyNew(Vector2i(current.x - 1, current.y));
|
||||||
insertOnlyNew(sf::Vector2i(current.x, current.y - 1));
|
insertOnlyNew(Vector2i(current.x, current.y - 1));
|
||||||
}
|
}
|
||||||
return selected;
|
return selected;
|
||||||
}
|
}
|
||||||
|
@ -144,19 +141,19 @@ Generator::generateTiles(const sf::IntRect& area) {
|
||||||
assert(area.width && !(area.width & (area.width - 1)));
|
assert(area.width && !(area.width & (area.width - 1)));
|
||||||
assert(area.height && !(area.height & (area.height - 1)));
|
assert(area.height && !(area.height & (area.height - 1)));
|
||||||
|
|
||||||
sf::Vector2i start;
|
Vector2i start;
|
||||||
float minValue = std::numeric_limits<float>::max();
|
float minValue = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
// Find lowest value for tree start.
|
// Find lowest value for tree start.
|
||||||
for (int x = area.left; x < area.left + area.width; x++)
|
for (int x = area.left; x < area.left + area.width; x++)
|
||||||
for (int y = area.top; y < area.top + area.height; y++) {
|
for (int y = area.top; y < area.top + area.height; y++) {
|
||||||
if (mTileNoise.getNoise(x, y) + 1.0f < minValue) {
|
if (mTileNoise.getNoise(x, y) + 1.0f < minValue) {
|
||||||
start = sf::Vector2i(x, y);
|
start = Vector2i(x, y);
|
||||||
minValue = mTileNoise.getNoise(x, y) + 1.0f;
|
minValue = mTileNoise.getNoise(x, y) + 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<sf::Vector2i> selected = createMinimalSpanningTree(start, 12.0f);
|
std::vector<Vector2i> selected = createMinimalSpanningTree(start, 12.0f);
|
||||||
|
|
||||||
// For rooms, take minimum bounding box of spanning tree.
|
// For rooms, take minimum bounding box of spanning tree.
|
||||||
|
|
||||||
|
@ -191,22 +188,22 @@ Generator::generateTiles(const sf::IntRect& area) {
|
||||||
*
|
*
|
||||||
* @param area Area for which enemy spawns should be returned.
|
* @param area Area for which enemy spawns should be returned.
|
||||||
*/
|
*/
|
||||||
std::vector<sf::Vector2f>
|
std::vector<Vector2f>
|
||||||
Generator::getEnemySpawns(const sf::IntRect& area) {
|
Generator::getEnemySpawns(const sf::IntRect& area) {
|
||||||
auto compare = [](const sf::Vector2f& a, const sf::Vector2f& b) {
|
auto compare = [](const Vector2f& a, const Vector2f& b) {
|
||||||
return a.x < b.x || (a.x == b.x && a.y < b.y);
|
return a.x < b.x || (a.x == b.x && a.y < b.y);
|
||||||
};
|
};
|
||||||
std::set<sf::Vector2f, decltype(compare)> ret(compare);
|
std::set<Vector2f, decltype(compare)> ret(compare);
|
||||||
for (int x = area.left; x < area.left + area.width; x++) {
|
for (int x = area.left; x < area.left + area.width; x++) {
|
||||||
for (int y = area.top; y < area.top + area.height; y++) {
|
for (int y = area.top; y < area.top + area.height; y++) {
|
||||||
if (mCharacterNoise.getNoise(x, y) < -0.85f) {
|
if (mCharacterNoise.getNoise(x, y) < -0.85f) {
|
||||||
sf::Vector2i tilePosition = findClosestFloor(sf::Vector2i(x, y));
|
Vector2i tilePosition = findClosestFloor(Vector2i(x, y));
|
||||||
ret.insert(sf::Vector2f(tilePosition.x * Tile::TILE_SIZE.x,
|
ret.insert(Vector2f(tilePosition.x * Tile::TILE_SIZE.x,
|
||||||
tilePosition.y * Tile::TILE_SIZE.y));
|
tilePosition.y * Tile::TILE_SIZE.y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::vector<sf::Vector2f>(ret.begin(), ret.end());
|
return std::vector<Vector2f>(ret.begin(), ret.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -245,10 +242,10 @@ Generator::generateAreas(const sf::IntRect& area) {
|
||||||
/**
|
/**
|
||||||
* Returns a valid position (floor) for the player to spawn at.
|
* Returns a valid position (floor) for the player to spawn at.
|
||||||
*/
|
*/
|
||||||
sf::Vector2f
|
Vector2f
|
||||||
Generator::getPlayerSpawn() const {
|
Generator::getPlayerSpawn() const {
|
||||||
sf::Vector2i spawn = findClosestFloor(sf::Vector2i(0, 0));
|
Vector2i spawn = findClosestFloor(Vector2i(0, 0));
|
||||||
return sf::Vector2f(spawn.x * Tile::TILE_SIZE.x,
|
return Vector2f(spawn.x * Tile::TILE_SIZE.x,
|
||||||
spawn.y * Tile::TILE_SIZE.y);
|
spawn.y * Tile::TILE_SIZE.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,25 +255,22 @@ Generator::getPlayerSpawn() const {
|
||||||
* @warn Will fail if no floor tile has been generated yet.
|
* @warn Will fail if no floor tile has been generated yet.
|
||||||
* @position Point to start search for a floor tile from.
|
* @position Point to start search for a floor tile from.
|
||||||
*/
|
*/
|
||||||
sf::Vector2i
|
Vector2i
|
||||||
Generator::findClosestFloor(const sf::Vector2i& position) const {
|
Generator::findClosestFloor(const Vector2i& position) const {
|
||||||
auto compare = [](const sf::Vector2i& a, const sf::Vector2i& b) {
|
std::map<Vector2i, float> open;
|
||||||
return a.x < b.x || (a.x == b.x && a.y < b.y);
|
std::set<Vector2i> closed;
|
||||||
};
|
Vector2i start = position;
|
||||||
std::map<sf::Vector2i, float, decltype(compare)> open(compare);
|
auto makePair = [&start](const Vector2i& point) {
|
||||||
std::set<sf::Vector2i, decltype(compare)> closed(compare);
|
return std::make_pair(point, thor::length(Vector2f(point - start)));
|
||||||
sf::Vector2i start = position;
|
|
||||||
auto makePair = [&start](const sf::Vector2i& point) {
|
|
||||||
return std::make_pair(point, thor::length(sf::Vector2f(point - start)));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
open.insert(makePair(start));
|
open.insert(makePair(start));
|
||||||
while (!open.empty()) {
|
while (!open.empty()) {
|
||||||
auto intComp = [](const std::pair<sf::Vector2i, float>& left,
|
auto intComp = [](const std::pair<Vector2i, float>& left,
|
||||||
const std::pair<sf::Vector2i, float>& right) {
|
const std::pair<Vector2i, float>& right) {
|
||||||
return left.second < right.second;
|
return left.second < right.second;
|
||||||
};
|
};
|
||||||
sf::Vector2i current = std::min_element(open.begin(), open.end(), intComp)->first;
|
Vector2i current = std::min_element(open.begin(), open.end(), intComp)->first;
|
||||||
open.erase(current);
|
open.erase(current);
|
||||||
closed.insert(current);
|
closed.insert(current);
|
||||||
if (mTiles.count(current.x) != 0 &&
|
if (mTiles.count(current.x) != 0 &&
|
||||||
|
@ -285,17 +279,17 @@ Generator::findClosestFloor(const sf::Vector2i& position) const {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (closed.find(sf::Vector2i(current.x + 1, current.y)) == closed.end())
|
if (closed.find(Vector2i(current.x + 1, current.y)) == closed.end())
|
||||||
open.insert(makePair(sf::Vector2i(current.x + 1, current.y)));
|
open.insert(makePair(Vector2i(current.x + 1, current.y)));
|
||||||
if (closed.find(sf::Vector2i(current.x, current.y + 1)) == closed.end())
|
if (closed.find(Vector2i(current.x, current.y + 1)) == closed.end())
|
||||||
open.insert(makePair(sf::Vector2i(current.x, current.y + 1)));
|
open.insert(makePair(Vector2i(current.x, current.y + 1)));
|
||||||
if (closed.find(sf::Vector2i(current.x - 1, current.y)) == closed.end())
|
if (closed.find(Vector2i(current.x - 1, current.y)) == closed.end())
|
||||||
open.insert(makePair(sf::Vector2i(current.x - 1, current.y)));
|
open.insert(makePair(Vector2i(current.x - 1, current.y)));
|
||||||
if (closed.find(sf::Vector2i(current.x, current.y - 1)) == closed.end())
|
if (closed.find(Vector2i(current.x, current.y - 1)) == closed.end())
|
||||||
open.insert(makePair(sf::Vector2i(current.x, current.y - 1)));
|
open.insert(makePair(Vector2i(current.x, current.y - 1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No floor tile found in the entire world.
|
// No floor tile found in the entire world.
|
||||||
assert(false);
|
assert(false);
|
||||||
return sf::Vector2i();
|
return Vector2i();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "../sprites/Tile.h"
|
#include "../sprites/Tile.h"
|
||||||
#include "SimplexNoise.h"
|
#include "SimplexNoise.h"
|
||||||
|
#include "../util/Vector.h"
|
||||||
|
|
||||||
class World;
|
class World;
|
||||||
class Pathfinder;
|
class Pathfinder;
|
||||||
|
@ -22,9 +23,9 @@ class Pathfinder;
|
||||||
class Generator {
|
class Generator {
|
||||||
public:
|
public:
|
||||||
explicit Generator(World& world, Pathfinder& pathfinder);
|
explicit Generator(World& world, Pathfinder& pathfinder);
|
||||||
void generateCurrentAreaIfNeeded(const sf::Vector2f& position);
|
void generateCurrentAreaIfNeeded(const Vector2f& position);
|
||||||
sf::Vector2f getPlayerSpawn() const;
|
Vector2f getPlayerSpawn() const;
|
||||||
std::vector<sf::Vector2f> getEnemySpawns(const sf::IntRect& area);
|
std::vector<Vector2f> getEnemySpawns(const sf::IntRect& area);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<int, std::map<int, Tile::Type> > array;
|
typedef std::map<int, std::map<int, Tile::Type> > array;
|
||||||
|
@ -32,9 +33,9 @@ private:
|
||||||
private:
|
private:
|
||||||
void generateAreas(const sf::IntRect& area);
|
void generateAreas(const sf::IntRect& area);
|
||||||
void generateTiles(const sf::IntRect& area);
|
void generateTiles(const sf::IntRect& area);
|
||||||
sf::Vector2i findClosestFloor(const sf::Vector2i& position) const;
|
Vector2i findClosestFloor(const Vector2i& position) const;
|
||||||
std::vector<sf::Vector2i> createMinimalSpanningTree(
|
std::vector<Vector2i> createMinimalSpanningTree(
|
||||||
const sf::Vector2i& start, const float limit);
|
const Vector2i& start, const float limit);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const int GENERATE_AREA_SIZE;
|
static const int GENERATE_AREA_SIZE;
|
||||||
|
|
|
@ -9,18 +9,18 @@
|
||||||
|
|
||||||
#include "../World.h"
|
#include "../World.h"
|
||||||
|
|
||||||
Item::Item(const sf::Vector2f& size, const std::string& texture) :
|
Item::Item(const Vector2f& size, const std::string& texture) :
|
||||||
Sprite(sf::Vector2f(), CATEGORY_NONSOLID, MASK_NONE, size, texture,
|
Sprite(Vector2f(), CATEGORY_NONSOLID, MASK_NONE, size, texture,
|
||||||
sf::Vector2f()) {
|
Vector2f()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Item::drop(const sf::Vector2f& position) {
|
Item::drop(const Vector2f& position) {
|
||||||
setPosition(position);
|
setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Item::testCollision(std::shared_ptr<Sprite> other,
|
Item::testCollision(std::shared_ptr<Sprite> other,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond) {
|
Vector2f& offsetFirst, const Vector2f& offsetSecond) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,12 +14,12 @@ class World;
|
||||||
|
|
||||||
class Item : public Sprite {
|
class Item : public Sprite {
|
||||||
public:
|
public:
|
||||||
Item(const sf::Vector2f& size, const std::string& texture);
|
Item(const Vector2f& size, const std::string& texture);
|
||||||
virtual ~Item() {};
|
virtual ~Item() {};
|
||||||
|
|
||||||
void drop(const sf::Vector2f& position);
|
void drop(const Vector2f& position);
|
||||||
bool testCollision(std::shared_ptr<Sprite> other,
|
bool testCollision(std::shared_ptr<Sprite> other,
|
||||||
sf::Vector2f& offsetFirst, const sf::Vector2f& offsetSecond);
|
Vector2f& offsetFirst, const Vector2f& offsetSecond);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DG_ITEM_H_ */
|
#endif /* DG_ITEM_H_ */
|
||||||
|
|
|
@ -20,7 +20,7 @@ Shield::onUse(Character& character) {
|
||||||
mCharacter = &character;
|
mCharacter = &character;
|
||||||
if (mRotatingShield)
|
if (mRotatingShield)
|
||||||
mRotatingShield->setDelete(true);
|
mRotatingShield->setDelete(true);
|
||||||
sf::Vector2f offset = mCharacter->getDirection() * mCharacter->getRadius();
|
Vector2f offset = mCharacter->getDirection() * mCharacter->getRadius();
|
||||||
mRotatingShield = std::shared_ptr<RotatingShield>(
|
mRotatingShield = std::shared_ptr<RotatingShield>(
|
||||||
new RotatingShield(mCharacter->getPosition() + offset));
|
new RotatingShield(mCharacter->getPosition() + offset));
|
||||||
mCharacter->mWorld.insert(mRotatingShield);
|
mCharacter->mWorld.insert(mRotatingShield);
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "../util/Yaml.h"
|
#include "../util/Yaml.h"
|
||||||
|
|
||||||
Weapon::Weapon(World& world, Character& holder, const Yaml& config) :
|
Weapon::Weapon(World& world, Character& holder, const Yaml& config) :
|
||||||
Item(sf::Vector2f(80, 30), "weapon.png"),
|
Item(Vector2f(80, 30), "weapon.png"),
|
||||||
mWorld(world),
|
mWorld(world),
|
||||||
mHolder(&holder),
|
mHolder(&holder),
|
||||||
mName(config.get("name", std::string())),
|
mName(config.get("name", std::string())),
|
||||||
|
@ -154,15 +154,15 @@ Weapon::setHolder(Character& holder) {
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Weapon::insertProjectile(float angle) {
|
Weapon::insertProjectile(float angle) {
|
||||||
sf::Vector2f offset(mHolder->getDirection() * mHolder->getRadius());
|
Vector2f offset(mHolder->getDirection() * mHolder->getRadius());
|
||||||
|
|
||||||
float spread = (mHolder->getSpeed() == sf::Vector2f())
|
float spread = (mHolder->getSpeed() == Vector2f())
|
||||||
? mSpread
|
? mSpread
|
||||||
: mSpreadMoving;
|
: mSpreadMoving;
|
||||||
std::uniform_real_distribution<float> distribution(- spread, spread);
|
std::uniform_real_distribution<float> distribution(- spread, spread);
|
||||||
angle += distribution(mGenerator) + 90.0f;
|
angle += distribution(mGenerator) + 90.0f;
|
||||||
|
|
||||||
sf::Vector2f direction(thor::rotatedVector(mHolder->getDirection(), angle));
|
Vector2f direction(thor::rotatedVector(mHolder->getDirection(), angle));
|
||||||
|
|
||||||
std::shared_ptr<Sprite> projectile(new Bullet(mHolder->getPosition() + offset,
|
std::shared_ptr<Sprite> projectile(new Bullet(mHolder->getPosition() + offset,
|
||||||
*mHolder, direction, mProjectile, mProjectileSpeed,
|
*mHolder, direction, mProjectile, mProjectileSpeed,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "../util/Yaml.h"
|
#include "../util/Yaml.h"
|
||||||
|
|
||||||
Corpse::Corpse(const sf::Vector2f& position) :
|
Corpse::Corpse(const Vector2f& position) :
|
||||||
Circle(position, CATEGORY_NONSOLID, MASK_NONE, Yaml("corpse.yaml")) {
|
Circle(position, CATEGORY_NONSOLID, MASK_NONE, Yaml("corpse.yaml")) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
class Corpse : public Circle {
|
class Corpse : public Circle {
|
||||||
public:
|
public:
|
||||||
explicit Corpse(const sf::Vector2f& position);
|
explicit Corpse(const Vector2f& position);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DG_CORPSE_H_ */
|
#endif /* DG_CORPSE_H_ */
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "../util/Yaml.h"
|
#include "../util/Yaml.h"
|
||||||
|
|
||||||
Enemy::Enemy(World& world, Pathfinder& pathfinder,
|
Enemy::Enemy(World& world, Pathfinder& pathfinder,
|
||||||
const sf::Vector2f& position) :
|
const Vector2f& position) :
|
||||||
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("enemy.yaml"), world,
|
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("enemy.yaml"), world,
|
||||||
pathfinder) {
|
pathfinder) {
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,6 @@ Enemy::onThink(int elapsed) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
releaseTrigger();
|
releaseTrigger();
|
||||||
setSpeed(sf::Vector2f(), 0);
|
setSpeed(Vector2f(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ class World;
|
||||||
class Enemy : public Character {
|
class Enemy : public Character {
|
||||||
public:
|
public:
|
||||||
explicit Enemy(World& world, Pathfinder& pathfinder,
|
explicit Enemy(World& world, Pathfinder& pathfinder,
|
||||||
const sf::Vector2f& position);
|
const Vector2f& position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void onThink(int elapsed) override;
|
virtual void onThink(int elapsed) override;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* Initializes Sprite.
|
* Initializes Sprite.
|
||||||
*/
|
*/
|
||||||
Player::Player(World& world, Pathfinder& pathfinder,
|
Player::Player(World& world, Pathfinder& pathfinder,
|
||||||
const sf::Vector2f& position) :
|
const Vector2f& position) :
|
||||||
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("player.yaml"), world,
|
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("player.yaml"), world,
|
||||||
pathfinder),
|
pathfinder),
|
||||||
mDirection(0) {
|
mDirection(0) {
|
||||||
|
@ -27,7 +27,7 @@ Player::Player(World& world, Pathfinder& pathfinder,
|
||||||
* @param Absolute world coordinates of the crosshair.
|
* @param Absolute world coordinates of the crosshair.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Player::setCrosshairPosition(const sf::Vector2f& position) {
|
Player::setCrosshairPosition(const Vector2f& position) {
|
||||||
mCrosshairPosition = position - getPosition();
|
mCrosshairPosition = position - getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ Player::setDirection(Direction direction, bool unset) {
|
||||||
mDirection = mDirection | direction;
|
mDirection = mDirection | direction;
|
||||||
|
|
||||||
// Convert directions into a vector.
|
// Convert directions into a vector.
|
||||||
sf::Vector2f dirVec(0, 0);
|
Vector2f dirVec(0, 0);
|
||||||
if (mDirection & Direction::RIGHT)
|
if (mDirection & Direction::RIGHT)
|
||||||
dirVec.x += 1.0f;
|
dirVec.x += 1.0f;
|
||||||
if (mDirection & Direction::LEFT)
|
if (mDirection & Direction::LEFT)
|
||||||
|
@ -59,7 +59,7 @@ Player::setDirection(Direction direction, bool unset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Player::setDestination(const sf::Vector2f& destination) {
|
Player::setDestination(const Vector2f& destination) {
|
||||||
mDirection = 0;
|
mDirection = 0;
|
||||||
Character::setDestination(destination);
|
Character::setDestination(destination);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,13 +29,13 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Player(World& world, Pathfinder& pathfinder,
|
explicit Player(World& world, Pathfinder& pathfinder,
|
||||||
const sf::Vector2f& position);
|
const Vector2f& position);
|
||||||
|
|
||||||
void setCrosshairPosition(const sf::Vector2f& position);
|
void setCrosshairPosition(const Vector2f& position);
|
||||||
using Character::pullTrigger;
|
using Character::pullTrigger;
|
||||||
using Character::releaseTrigger;
|
using Character::releaseTrigger;
|
||||||
void setDirection(Direction direction, bool unset);
|
void setDirection(Direction direction, bool unset);
|
||||||
void setDestination(const sf::Vector2f& destination);
|
void setDestination(const Vector2f& destination);
|
||||||
using Character::getMagazineAmmo;
|
using Character::getMagazineAmmo;
|
||||||
using Character::getTotalAmmo;
|
using Character::getTotalAmmo;
|
||||||
using Character::getWeaponName;
|
using Character::getWeaponName;
|
||||||
|
@ -56,7 +56,7 @@ private:
|
||||||
void onThink(int elapsed) override;
|
void onThink(int elapsed) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sf::Vector2f mCrosshairPosition; //< Relative position of the point to fire at (mouse cursor).
|
Vector2f mCrosshairPosition; //< Relative position of the point to fire at (mouse cursor).
|
||||||
unsigned char mDirection; //< Current movement direction for direct control.
|
unsigned char mDirection; //< Current movement direction for direct control.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "../util/Yaml.h"
|
#include "../util/Yaml.h"
|
||||||
|
|
||||||
RotatingShield::RotatingShield(const sf::Vector2f& position) :
|
RotatingShield::RotatingShield(const Vector2f& position) :
|
||||||
Rectangle(position, CATEGORY_WORLD, MASK_ALL,
|
Rectangle(position, CATEGORY_WORLD, MASK_ALL,
|
||||||
Yaml("rotating_shield.yaml")) {
|
Yaml("rotating_shield.yaml")) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
class RotatingShield : public Rectangle {
|
class RotatingShield : public Rectangle {
|
||||||
public:
|
public:
|
||||||
explicit RotatingShield(const sf::Vector2f& position);
|
explicit RotatingShield(const Vector2f& position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Sprite::setDelete;
|
using Sprite::setDelete;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "../util/Yaml.h"
|
#include "../util/Yaml.h"
|
||||||
#include "../World.h"
|
#include "../World.h"
|
||||||
|
|
||||||
const sf::Vector2i Tile::TILE_SIZE = sf::Vector2i(75, 75);
|
const Vector2i Tile::TILE_SIZE = sf::Vector2i(75, 75);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a tile.
|
* Constructs a tile.
|
||||||
|
@ -24,7 +24,7 @@ const sf::Vector2i Tile::TILE_SIZE = sf::Vector2i(75, 75);
|
||||||
* @param world Box2D world object.
|
* @param world Box2D world object.
|
||||||
*/
|
*/
|
||||||
Tile::Tile(Type type, int x, int y) :
|
Tile::Tile(Type type, int x, int y) :
|
||||||
Rectangle(sf::Vector2f(x * TILE_SIZE.x, y * TILE_SIZE.y),
|
Rectangle(Vector2f(x * TILE_SIZE.x, y * TILE_SIZE.y),
|
||||||
CATEGORY_WORLD, (isSolid(type)) ? 0xffff : 0,
|
CATEGORY_WORLD, (isSolid(type)) ? 0xffff : 0,
|
||||||
Yaml(getConfig(type))),
|
Yaml(getConfig(type))),
|
||||||
mType(type) {
|
mType(type) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
Type getType() const;
|
Type getType() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const sf::Vector2i TILE_SIZE; //< Tile size in pixels.
|
static const Vector2i TILE_SIZE; //< Tile size in pixels.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::string getConfig(Type type);
|
static std::string getConfig(Type type);
|
||||||
|
|
44
source/util/Vector.h
Normal file
44
source/util/Vector.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Vector.h
|
||||||
|
*
|
||||||
|
* Created on: 07.08.2013
|
||||||
|
* Author: Felix
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DG_VECTOR_H_
|
||||||
|
#define DG_VECTOR_H_
|
||||||
|
|
||||||
|
#include <SFML/System.hpp>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vector class with comparison operator. All other operators are inherited
|
||||||
|
* from sf::Vector2.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class Vector2 : public sf::Vector2<T> {
|
||||||
|
public:
|
||||||
|
Vector2() : sf::Vector2<T>() {};
|
||||||
|
Vector2(T x, T y) : sf::Vector2<T>(x, y) {};
|
||||||
|
/**
|
||||||
|
* Implicitly catches and converts any vectors that have been converted to
|
||||||
|
* sf::Vector2 (as done by arithmethic operations defined by sf::Vector2).
|
||||||
|
*/
|
||||||
|
template <typename U>
|
||||||
|
Vector2(const sf::Vector2<U>& vector) : sf::Vector2<T>(vector) {};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparison operator meant for containers like std::set.
|
||||||
|
*
|
||||||
|
* Provides a clearly defined, but otherwise meaningless sorting of vectors.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
bool operator <(const Vector2<T>& left, const Vector2<T>& right) {
|
||||||
|
return left.x < right.x || (left.x == right.x && left.y < right.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef Vector2<int> Vector2i;
|
||||||
|
typedef Vector2<float> Vector2f;
|
||||||
|
|
||||||
|
#endif /* DG_VECTOR_H_ */
|
|
@ -13,9 +13,8 @@
|
||||||
|
|
||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
#include <SFML/System.hpp>
|
|
||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to a YAML file.
|
* Interface to a YAML file.
|
||||||
|
@ -45,12 +44,12 @@ private:
|
||||||
* Error handling is done in Yaml::get.
|
* Error handling is done in Yaml::get.
|
||||||
*/
|
*/
|
||||||
namespace {
|
namespace {
|
||||||
void operator>>(const YAML::Node& node, sf::Vector2i& vector) {
|
void operator>>(const YAML::Node& node, Vector2i& vector) {
|
||||||
node[0] >> vector.x;
|
node[0] >> vector.x;
|
||||||
node[1] >> vector.y;
|
node[1] >> vector.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator>>(const YAML::Node& node, sf::Vector2f& vector) {
|
void operator>>(const YAML::Node& node, Vector2f& vector) {
|
||||||
node[0] >> vector.x;
|
node[0] >> vector.x;
|
||||||
node[1] >> vector.y;
|
node[1] >> vector.y;
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue