diff --git a/source/Game.cpp b/source/Game.cpp index d2fd462..0ca7eaf 100644 --- a/source/Game.cpp +++ b/source/Game.cpp @@ -30,7 +30,7 @@ Game::Game(sf::RenderWindow& window) : generator.generateTiles(mTileManager, mPathfinder, sf::IntRect(-32, -32, 64, 64)); mPlayer = std::shared_ptr(new Player(mWorld, mTileManager, mPathfinder, - sf::Vector2f(0.0f, 0.0f), Yaml("player.yaml"))); + generator.getPlayerSpawn(), Yaml("player.yaml"))); mWorld.insertCharacter(mPlayer); } diff --git a/source/generator/Generator.cpp b/source/generator/Generator.cpp index 364951e..4a178a2 100644 --- a/source/generator/Generator.cpp +++ b/source/generator/Generator.cpp @@ -9,10 +9,15 @@ #include #include +#include +#include + +#include + +#include #include "simplexnoise.h" #include "../sprites/TileManager.h" -#include "../util/Log.h" #include "../Pathfinder.h" /// For usage with simplexnoise.h @@ -39,7 +44,7 @@ Generator::Generator() { */ void Generator::generateTiles(TileManager& tm, Pathfinder& pathfinder, - const sf::IntRect& area) const { + const sf::IntRect& area) { // Check if width and height are power of two. assert(area.width && !(area.width & (area.width - 1))); assert(area.height && !(area.height & (area.height - 1))); @@ -76,6 +81,7 @@ Generator::generateTiles(TileManager& tm, Pathfinder& pathfinder, generateAreas(pathfinder, filtered, area, sf::Vector2f(area.left, area.top)); pathfinder.generatePortals(); + mGenerated = filtered; } /** @@ -180,3 +186,52 @@ Generator::generateAreas(Pathfinder& pathfinder, area.top + halfHeight, halfWidth, halfHeight), offset); } } + +/** + * Returns a valid position (floor) for the player to spawn at. + */ +sf::Vector2f +Generator::getPlayerSpawn() const { + sf::Vector2i spawn = findClosestFloor(sf::Vector2i(mGenerated.size() / 2, + mGenerated[0].size() / 2)); + return sf::Vector2f( + (spawn.x - mGenerated.size() / 2.0f) * TileManager::TILE_SIZE.x, + (spawn.y - mGenerated[0].size() / 2.0f) * TileManager::TILE_SIZE.y); +} + +/** + * Finds the point array index closest to position which has a floor tile. + */ +sf::Vector2i +Generator::findClosestFloor(const sf::Vector2i& position) const { + auto compare = [](const sf::Vector2i& a, const sf::Vector2i& b) { + return a.x < b.x || (a.x == b.x && a.y < b.y); + }; + std::map open(compare); + std::set closed(compare); + 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)); + while (!open.empty()) { + const sf::Vector2i& current = open.begin()->first; + open.erase(current); + closed.insert(current); + if (mGenerated[current.x][current.y] == TileManager::Type::FLOOR) + return current; + else { + if (closed.find(sf::Vector2i(current.x + 1, current.y)) == closed.end()) + open.insert(makePair(sf::Vector2i(current.x + 1, current.y))); + if (closed.find(sf::Vector2i(current.x, current.y + 1)) == closed.end()) + open.insert(makePair(sf::Vector2i(current.x, current.y + 1))); + if (closed.find(sf::Vector2i(current.x - 1, current.y)) == closed.end()) + open.insert(makePair(sf::Vector2i(current.x - 1, current.y))); + if (closed.find(sf::Vector2i(current.x, current.y - 1)) == closed.end()) + open.insert(makePair(sf::Vector2i(current.x, current.y - 1))); + } + } + assert(false); + return sf::Vector2i(); +} diff --git a/source/generator/Generator.h b/source/generator/Generator.h index aa4cfb3..ebc3bff 100644 --- a/source/generator/Generator.h +++ b/source/generator/Generator.h @@ -18,11 +18,11 @@ class Generator { public: explicit Generator(); void generateTiles(TileManager& tm, Pathfinder& pathfinder, - const sf::IntRect& area) const; - //void generateCharacters(World& world, const sf::IntRect& area) const; + const sf::IntRect& area); sf::Vector2f getPlayerSpawn() const; private: + sf::Vector2i findClosestFloor(const sf::Vector2i& position) const; static void fill(std::vector >& image, const sf::IntRect& area, TileManager::Type value); static void filterWalls(std::vector >& in, @@ -33,6 +33,9 @@ private: static void generateAreas(Pathfinder& pathfinder, std::vector >& tiles, const sf::IntRect& area, const sf::Vector2f& offset); + +private: + std::vector > mGenerated; }; #endif /* DG_GENERATOR_H_ */