diff --git a/source/Game.cpp b/source/Game.cpp index 956f847..7865883 100644 --- a/source/Game.cpp +++ b/source/Game.cpp @@ -27,7 +27,7 @@ Game::Game(sf::RenderWindow& window) : mWindow.setKeyRepeatEnabled(true); Generator generator; - generator.generateTiles(mTileManager, sf::IntRect(-20, -20, 40, 40)); + generator.generateTiles(mTileManager, sf::IntRect(-16, -16, 32, 32)); mPlayer = std::shared_ptr(new Player(mWorld, mTileManager, sf::Vector2f(0.0f, 0.0f), Yaml("player.yaml"))); mWorld.insertCharacter(mPlayer); diff --git a/source/generator/Generator.cpp b/source/generator/Generator.cpp index 03c35ed..8b48390 100644 --- a/source/generator/Generator.cpp +++ b/source/generator/Generator.cpp @@ -7,10 +7,12 @@ #include "Generator.h" +#include #include #include "simplexnoise.h" #include "../sprites/TileManager.h" +#include "../util/Log.h" /// For usage with simplexnoise.h uint8_t perm[512]; @@ -33,23 +35,27 @@ Generator::Generator() { * True means wall, false means floor. * * @param tm TileManager instance to set tiles in. - * @param area Size and position of area to generate tiles for. + * @param area Size and position of area to generate tiles for. Must be + * power of two. */ void Generator::generateTiles(TileManager& tm, const sf::IntRect& area) const { + // 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))); + std::vector > noise(area.width, std::vector(area.height)); std::vector > filtered(area.width, std::vector(area.height, false)); - for (int x = area.left; x < area.left+area.width; x++) { - for (int y = area.top; y < area.top+area.height; y++) { + for (int x = area.left; x < area.left + area.width; x++) { + for (int y = area.top; y < area.top + area.height; y++) { noise[x-area.left][y-area.top] = (scaled_octave_noise_2d(2, 2, 0.0015f, 0.5f, -0.5f, x, y) + scaled_octave_noise_2d(3, 3, 0.01f, -1, 1, x, y)) < 0.05f; } } - for (int x = 0; x < (int) noise.size(); x+=5) { for (int y = 0; y < (int) noise[x].size(); y+=5) { filterWalls(noise, filtered, x, y, 10, 5, 0); @@ -57,12 +63,11 @@ Generator::generateTiles(TileManager& tm, const sf::IntRect& area) const { filterWalls(noise, filtered, x, y, 50, 5, 20); } } - - for (int x = area.left; x < area.left+area.width; x++) { - for (int y = area.top; y < area.top+area.height; y++) { - tm.insertTile(TileManager::TilePosition(x, y), - (filtered[x-area.left][y-area.top]) - ? TileManager::Type::WALL : TileManager::Type::FLOOR); + for (int x = area.left; x < area.left + area.width; x++) { + for (int y = area.top; y < area.top + area.height; y++) { + (filtered[x-area.left][y-area.top]) + ? tm.insertTile(TileManager::TilePosition(x, y), TileManager::Type::WALL) + : tm.insertTile(TileManager::TilePosition(x, y), TileManager::Type::FLOOR); } } } @@ -87,12 +92,27 @@ Generator::fill(std::vector >& image, } /** - * Finds rectangles of specific size in in and puts them into out. + * Returns the number of walls (fields with value true) in the area in tiles. * - * True means wall, false means floor. + * @param area The area to count in. + * @param tiles Array of tile values (walls). + */ +int Generator::countWalls(const sf::IntRect& area, + std::vector >& tiles) { + int count = 0; + for (int x = area.left; x < area.left + area.width; x++) { + for (int y = area.top; y < area.top + area.height; y++) + count += (int) tiles[x][y]; + } + return count; +} + +/** + * Finds rectangles of specific size inside vector in and + * puts them into vector out. * - * @param[in] in Rectangular map of walls. - * @param[out] out Rectangular map of walls. + * @param[in] in Rectangular map of tiles. + * @param[out] out Rectangular map of tiles. * @param x Position to check from (top left corner for rectangle). * @param y Position to check from (top left corner for rectangle). * @param longside Length of the longer side of the rectangle. @@ -110,26 +130,11 @@ Generator::filterWalls(std::vector >& in, return; // Filter in horizontal direction. - if (x % longside == 0 && y % shortside == 0) { - int count = 0; - for (int x2 = x; x2 < x + longside; x2++) { - for (int y2 = y; y2 < y + shortside; y2++) { - count += (int) in[x2][y2]; - } - } - if (count >= shortside * longside - subtract) - fill(out, sf::IntRect(x, y, longside, shortside), true); - } - + if (countWalls(sf::IntRect(x, y, longside, shortside), in) >= + shortside * longside - subtract) + fill(out, sf::IntRect(x, y, longside, shortside), true); // Filter in vertical direction. - if (x % shortside == 0 && y % longside == 0) { - int count = 0; - for (int x2 = x; x2 < x + shortside; x2++) { - for (int y2 = y; y2 < y + longside; y2++) - count += (int) in[x2][y2]; - } - if (count >= shortside * longside - subtract) - fill(out, sf::IntRect(x, y, shortside, longside), true); - } + if (countWalls(sf::IntRect(x, y, shortside, longside), in) >= + shortside * longside - subtract) + fill(out, sf::IntRect(x, y, shortside, longside), true); } - diff --git a/source/generator/Generator.h b/source/generator/Generator.h index f5c72d6..495dc76 100644 --- a/source/generator/Generator.h +++ b/source/generator/Generator.h @@ -25,6 +25,8 @@ private: static void filterWalls(std::vector >& in, std::vector >& out, int x, int y, int longside, int shortside, int subtract); + static int countWalls(const sf::IntRect& area, + std::vector >& tiles); }; #endif /* DG_GENERATOR_H_ */