diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bf2beb..4a267cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,11 @@ set(SOURCES src/game/collectables/collection/collectables_collection.cpp src/game/collectables/collection/collectables_collection.hpp src/game/collectables/collection/collectables_depth_collection.cpp - src/game/collectables/collection/collectables_depth_collection.hpp src/game/collectables/collectable_in_level.hpp src/game/collectables/collectable_factory.cpp src/game/collectables/collectable_factory.hpp src/game/player/player_collection.cpp src/game/player/player_collection.hpp src/sprites/tilemap/tilemap.cpp src/sprites/tilemap/tilemap.hpp src/sprites/tilemap/tilemap_config.hpp) + src/game/collectables/collection/collectables_depth_collection.hpp src/game/collectables/collectable_in_level.hpp src/game/collectables/collectable_factory.cpp src/game/collectables/collectable_factory.hpp src/game/player/player_collection.cpp src/game/player/player_collection.hpp + src/levels.hpp + src/sprites/tiling/tilemap.cpp + src/sprites/tiling/tilemap.hpp + src/sprites/tiling/tilemap_config.hpp src/tilemaps.hpp src/sprites/tiling/tileset_config.hpp src/sprites/tiling/tileset.cpp src/sprites/tiling/tileset.hpp) set(PHYSICS_00_SOURCES src/prototypes/physics_00.cpp) diff --git a/assets/grass_plus.png b/assets/grass_plus.png new file mode 100644 index 0000000..2b6fb6a Binary files /dev/null and b/assets/grass_plus.png differ diff --git a/src/game/level/level_config.hpp b/src/game/level/level_config.hpp index db2bcc5..2d35897 100644 --- a/src/game/level/level_config.hpp +++ b/src/game/level/level_config.hpp @@ -7,22 +7,27 @@ #include "../../logging/easylogging++.h" #include "../collectables/collectable_in_level.hpp" #include +#include "../../sprites/tiling/tilemap_config.hpp" struct LevelConfig { std::string name; sf::Vector2f worldMapSize = {}; + TileMapConfig tileMapConfig = {}; std::vector playerSpawnPoints = {}; std::vector collectables = {}; LevelConfig(std::string name, - const sf::Vector2f &worldMapSize, + const std::string &tileMapName, const std::vector &playerSpawnPoints, const std::vector &collectables = {}) : name(std::move(name)), worldMapSize(worldMapSize), playerSpawnPoints(playerSpawnPoints) { + tileMapConfig = TileMapConfig(tileMapName, {}); + worldMapSize = tileMapConfig.getSize(); + // Remove invalid collectables for (auto &collectable : collectables) { diff --git a/src/levels.hpp b/src/levels.hpp index 9d37d2f..4cfc376 100644 --- a/src/levels.hpp +++ b/src/levels.hpp @@ -8,7 +8,7 @@ #define INITIAL_LEVEL "default" std::map const all_levels = { - {"default", LevelConfig("Default", {25, 25}, {{0, 0}}, { + {"default", LevelConfig("Default", "grass", {{0, 0}}, { CollectableInLevel("box", {5, 5}) })} }; diff --git a/src/sprites/sprite_factory.cpp b/src/sprites/sprite_factory.cpp index 551d9c4..777d6cf 100644 --- a/src/sprites/sprite_factory.cpp +++ b/src/sprites/sprite_factory.cpp @@ -95,3 +95,53 @@ std::shared_ptr SpriteFactory::createSheet(const std::string& name) LOG(INFO) << "Creating sheet " << name; return std::make_shared(texture, config.columns, config.rows); } + +std::shared_ptr SpriteFactory::createTileMap(const std::string &name) +{ + // Get config + auto tilemap_config = all_tilemaps.find(name); + + if (tilemap_config == all_tilemaps.end()) + { + LOG(ERROR) << "Tilemap " << name << " not found. Could not create tilemap."; + return nullptr; + } + + // Construct tilemap + auto config = tilemap_config->second; + std::shared_ptr tileSet = createTileSet(config.tileSheet); + if (sheet == nullptr) + { + LOG(ERROR) << "Sheet " << config.sheetName << " not found. Could not create tilemap."; + return nullptr; + } + + LOG(INFO) << "Creating tilemap " << name; + auto tilemap = std::make_shared(sheet, config.tileSize, config.tileCount); + tilemap->setTilemap(config.tilemap); + return tilemap; +} + +std::shared_ptr SpriteFactory::createTileSet(const std::string &name) +{ + // Get config + auto tileset_config = all_tilesets.find(name); + + if (tileset_config == all_tilesets.end()) + { + LOG(ERROR) << "Tileset " << name << " not found. Could not create tileset."; + return nullptr; + } + + // Construct tileset + auto config = tileset_config->second; + auto sheet = createSheet(config.sheetName); + if (sheet == nullptr) + { + LOG(ERROR) << "Sheet " << config.sheetName << " not found. Could not create tileset."; + return nullptr; + } + + LOG(INFO) << "Creating tileset " << name; + return std::make_shared(sheet, config.tileIndices); +} diff --git a/src/sprites/sprite_factory.hpp b/src/sprites/sprite_factory.hpp index b6f55ad..d351941 100644 --- a/src/sprites/sprite_factory.hpp +++ b/src/sprites/sprite_factory.hpp @@ -8,6 +8,8 @@ #include "animated_sprite.hpp" #include "sprite_sheet.hpp" #include "../logging/easylogging++.h" +#include "tiling/tilemap.hpp" +#include "tiling/tileset.hpp" class SpriteFactory { @@ -15,6 +17,8 @@ public: static std::shared_ptr createSingleSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0)); static std::shared_ptr createAnimatedSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0)); static std::shared_ptr createSheet(const std::string& name); + static std::shared_ptr createTileMap(const std::string& name); + std::shared_ptr createTileSet(const std::string &name); }; diff --git a/src/sprites/sprite_sheet.cpp b/src/sprites/sprite_sheet.cpp index ef2c308..a044761 100644 --- a/src/sprites/sprite_sheet.cpp +++ b/src/sprites/sprite_sheet.cpp @@ -3,6 +3,10 @@ SpriteSheet::SpriteSheet(const std::shared_ptr& texture, int columns, int rows) { + this->texture = texture; + this->columns = columns; + this->rows = rows; + // Extract sprites from texture sprites = std::vector(); int spriteWidth = texture->getSize().x / columns; @@ -47,3 +51,18 @@ std::shared_ptr SpriteSheet::getAnimation(int startingSequenceIn } return std::make_shared(animation); } + +int SpriteSheet::getRows() const +{ + return rows; +} + +int SpriteSheet::getColumns() const +{ + return columns; +} + +std::shared_ptr SpriteSheet::getTexture() const +{ + return texture; +} diff --git a/src/sprites/sprite_sheet.hpp b/src/sprites/sprite_sheet.hpp index ff4b0f9..02959b2 100644 --- a/src/sprites/sprite_sheet.hpp +++ b/src/sprites/sprite_sheet.hpp @@ -17,7 +17,15 @@ public: std::shared_ptr getAnimation(int startingSequenceIndex, int numberOfFrames) const; + std::shared_ptr getTexture() const; + + int getColumns() const; + int getRows() const; + private: + int columns; + int rows; + std::shared_ptr texture; std::vector sprites; }; diff --git a/src/sprites/tiling/tilemap.cpp b/src/sprites/tiling/tilemap.cpp new file mode 100644 index 0000000..44dc87a --- /dev/null +++ b/src/sprites/tiling/tilemap.cpp @@ -0,0 +1,57 @@ +#include "tilemap.hpp" + +TileMap::TileMap(std::shared_ptr tileSet, std::vector> tiles) +{ + // resize the vertex array to fit the level size + vertices.setPrimitiveType(sf::Quads); + + unsigned int size = tiles.size(); + vertices.resize(size * size * 4); + + // populate the vertex array, with one quad per tile + for (unsigned int y = 0; y < size; ++y) + for (unsigned int x = 0; x < size; ++x) + { + // get the current tile number + int tileNumber = tiles[size - 1 - y][x]; + + // TODO + // Follow: https://www.sfml-dev.org/tutorials/2.5/graphics-vertex-array.php#example-tile-map + // find its position in the tileset texture + int tu = tileNumber % (tileset.getSize().y / tileSize.y); + int tv = tileNumber / (tileset.getSize().y / tileSize.y); + + // get a pointer to the current tile's quad + sf::Vertex *quad = &vertices[(y + x * width) * 4]; + + // define its 4 corners + quad[0].position = sf::Vector2f(y * tileSize.y, x * tileSize.y); + quad[1].position = sf::Vector2f((y + 1) * tileSize.y, x * tileSize.y); + quad[2].position = sf::Vector2f((y + 1) * tileSize.y, (x + 1) * tileSize.y); + quad[3].position = sf::Vector2f(y * tileSize.y, (x + 1) * tileSize.y); + + // define its 4 texture coordinates + quad[0].texCoords = sf::Vector2f(tu * tileSize.y, tv * tileSize.y); + quad[1].texCoords = sf::Vector2f((tu + 1) * tileSize.y, tv * tileSize.y); + quad[2].texCoords = sf::Vector2f((tu + 1) * tileSize.y, (tv + 1) * tileSize.y); + quad[3].texCoords = sf::Vector2f(tu * tileSize.y, (tv + 1) * tileSize.y); + } +} + +void TileMap::draw(sf::RenderWindow *window) +{ + window->draw(*this); +} + +void TileMap::draw(sf::RenderTarget &target, sf::RenderStates states) const +{ + // apply the transform + // TODO? NEEDED? +// states.transform *= getTransform(); + + // apply the tileset texture + states.texture = &tileMapTexture; + + // draw the vertex array + target.draw(vertices, states); +} diff --git a/src/sprites/tiling/tilemap.hpp b/src/sprites/tiling/tilemap.hpp new file mode 100644 index 0000000..ac33d5f --- /dev/null +++ b/src/sprites/tiling/tilemap.hpp @@ -0,0 +1,26 @@ +#ifndef HOLESOME_TILEMAP_HPP +#define HOLESOME_TILEMAP_HPP + + +#include +#include +#include +#include "../../game/game_object.h" +#include "tileset.hpp" + +class TileMap : public GameObject, public sf::Drawable +{ +public: + TileMap(std::shared_ptr tileSet, std::vector> tiles); + + void draw(sf::RenderWindow *window) override; + + void draw(sf::RenderTarget &target, sf::RenderStates states) const override; + +private: + sf::VertexArray vertices; + sf::Texture tileMapTexture; +}; + + +#endif //HOLESOME_TILEMAP_HPP diff --git a/src/sprites/tiling/tilemap_config.hpp b/src/sprites/tiling/tilemap_config.hpp new file mode 100644 index 0000000..017a62b --- /dev/null +++ b/src/sprites/tiling/tilemap_config.hpp @@ -0,0 +1,45 @@ +#ifndef HOLESOME_TILEMAP_CONFIG_HPP +#define HOLESOME_TILEMAP_CONFIG_HPP + +#include +#include +#include +#include +#include + +struct TileMapConfig +{ + std::string tileSheet; + + std::vector backgroundTileSelection = {}; + + std::vector> tiles = {}; + + TileMapConfig(std::string tileSheet, std::vector> tiles, + std::vector backgroundTileSelection = {}) + { + this->tileSheet = std::move(tileSheet); + this->backgroundTileSelection = std::move(backgroundTileSelection); + this->tiles = std::move(tiles); + + // Make sure all rows are the same length and that the map is square + int size = tiles.size(); + for (auto &row : tiles) + { + if (row.size() != size) + { + throw std::runtime_error("Tile map is not square"); + } + } + } + + TileMapConfig() = default; + + sf::Vector2f getSize() const + { + int size = tiles.size(); + return {static_cast(size), static_cast(size)}; + } +}; + +#endif //HOLESOME_TILEMAP_CONFIG_HPP diff --git a/src/sprites/tiling/tileset.cpp b/src/sprites/tiling/tileset.cpp new file mode 100644 index 0000000..55ec019 --- /dev/null +++ b/src/sprites/tiling/tileset.cpp @@ -0,0 +1,6 @@ +#include "tileset.hpp" + +TileSet::TileSet(const std::shared_ptr& sheet, const std::vector& tileIndices) +{ + +} diff --git a/src/sprites/tiling/tileset.hpp b/src/sprites/tiling/tileset.hpp new file mode 100644 index 0000000..38a12c7 --- /dev/null +++ b/src/sprites/tiling/tileset.hpp @@ -0,0 +1,14 @@ +#ifndef HOLESOME_TILESET_HPP +#define HOLESOME_TILESET_HPP + + +#include "../sprite_sheet.hpp" + +class TileSet +{ +public: + TileSet(const std::shared_ptr& sheet, const std::vector& tileIndices); +}; + + +#endif //HOLESOME_TILESET_HPP diff --git a/src/sprites/tiling/tileset_config.hpp b/src/sprites/tiling/tileset_config.hpp new file mode 100644 index 0000000..e30faa3 --- /dev/null +++ b/src/sprites/tiling/tileset_config.hpp @@ -0,0 +1,21 @@ +#ifndef HOLESOME_TILESET_CONFIG_HPP +#define HOLESOME_TILESET_CONFIG_HPP + +#include +#include + +struct TileSetConfig +{ + std::string sheetName; + std::vector tileIndices = {}; + + TileSetConfig() = default; + + TileSetConfig(std::string sheetName, std::vector tileIndices) + { + this->sheetName = std::move(sheetName); + this->tileIndices = std::move(tileIndices); + } +}; + +#endif //HOLESOME_TILESET_CONFIG_HPP diff --git a/src/texture_config.h b/src/texture_config.h index 739614b..efb7e85 100644 --- a/src/texture_config.h +++ b/src/texture_config.h @@ -6,6 +6,7 @@ #include "sprites/configs/animation_config.hpp" #include "sprites/configs/sheet_config.hpp" #include "sprites/configs/sprite_config.hpp" +#include "sprites/tiling/tileset_config.hpp" #define PLAYER_SKIN "ring" @@ -15,9 +16,10 @@ */ std::map const all_textures = { {"numbers", "assets/numbers.png"}, - {"64", "assets/64.png"}, - {"edge", "assets/edge.png"}, - {"ring", "assets/ring.png"}, + {"64", "assets/64.png"}, + {"edge", "assets/edge.png"}, + {"ring", "assets/ring.png"}, + {"grasses", "assets/grass_plus.png"}, {"hole", "assets/hole.png"} }; @@ -26,7 +28,8 @@ std::map const all_textures = { * The key is the name of the sheet, the value is the sheet config. */ std::map const all_sheets = { - {"numbers", SheetConfig("numbers", 4, 2)} + {"numbers", SheetConfig("numbers", 4, 2)}, + {"grasses", SheetConfig("grasses", 25, 14)} }; /** @@ -48,4 +51,8 @@ std::map const all_sprites = { {"hole", SpriteConfig("hole")} }; +std::map const all_tilesets = { + {"grass", TileSetConfig("grasses", {58})} +}; + #endif //HOLESOME_TEXTURE_CONFIG_H diff --git a/src/tilemaps.hpp b/src/tilemaps.hpp new file mode 100644 index 0000000..139d72d --- /dev/null +++ b/src/tilemaps.hpp @@ -0,0 +1,21 @@ +#ifndef HOLESOME_TILEMAPS_HPP +#define HOLESOME_TILEMAPS_HPP + +#include +#include +#include "sprites/tiling/tilemap_config.hpp" + +std::map const all_tilemaps = { + {"grass", TileMapConfig("grass", {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},})} +}; + +#endif //HOLESOME_TILEMAPS_HPP