First tile map properly working

This commit is contained in:
Maximilian Giller 2023-06-17 19:48:51 +02:00
parent 120fdb0a88
commit 27b6e1b324
35 changed files with 216 additions and 227 deletions

View file

@ -98,7 +98,7 @@ set(SOURCES
src/levels.hpp src/levels.hpp
src/sprites/tiling/tilemap.cpp src/sprites/tiling/tilemap.cpp
src/sprites/tiling/tilemap.hpp 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) src/sprites/tiling/tilemap_config.hpp src/sprites/tiling/tileset_config.hpp src/sprites/tiling/tileset.cpp src/sprites/tiling/tileset.hpp)
set(PHYSICS_00_SOURCES set(PHYSICS_00_SOURCES
src/prototypes/physics_00.cpp) src/prototypes/physics_00.cpp)

View file

@ -10,7 +10,7 @@ struct WorldCoordinates
WorldCoordinates(float x, float y, float z = 0) : x(x), y(y), z(z) WorldCoordinates(float x, float y, float z = 0) : x(x), y(y), z(z)
{} {}
WorldCoordinates(sf::Vector2f vector) : x(vector.x), y(vector.y), z(0) explicit WorldCoordinates(sf::Vector2f vector) : x(vector.x), y(vector.y), z(0)
{} {}
float x; float x;
@ -62,7 +62,7 @@ struct IsometricCoordinates
float y; float y;
float depth; // Bigger means further back. Can be used for accurate rendering order. float depth; // Bigger means further back. Can be used for accurate rendering order.
sf::Vector2f toScreen() const [[nodiscard]] sf::Vector2f toScreen() const
{ {
return {x, y}; return {x, y};
} }
@ -72,7 +72,7 @@ struct IsometricCoordinates
IsometricCoordinates(float x, float y, float depth = 0) : x(x), y(y), depth(depth) IsometricCoordinates(float x, float y, float depth = 0) : x(x), y(y), depth(depth)
{} {}
explicit IsometricCoordinates (sf::Vector2f vector) : x(vector.x), y(vector.y), depth(0) explicit IsometricCoordinates(sf::Vector2f vector) : x(vector.x), y(vector.y), depth(0)
{} {}
}; };
@ -85,6 +85,9 @@ struct GridCoordinates
GridCoordinates(float x, float y) : x(x), y(y) GridCoordinates(float x, float y) : x(x), y(y)
{} {}
GridCoordinates(int x, int y) : x(static_cast<float>(x)), y(static_cast<float>(y))
{}
}; };

View file

@ -23,15 +23,15 @@ GridCoordinates TranslatedCoordinates::grid() const {
return {referenceWordCoordinates.x - 0.5f, referenceWordCoordinates.y - 0.5f}; return {referenceWordCoordinates.x - 0.5f, referenceWordCoordinates.y - 0.5f};
} }
void TranslatedCoordinates::set(WorldCoordinates newWorldCoordinates) { void TranslatedCoordinates::setWorld(WorldCoordinates newWorldCoordinates) {
this->worldCoordinates = newWorldCoordinates; this->worldCoordinates = newWorldCoordinates;
} }
void TranslatedCoordinates::set(IsometricCoordinates newIsometricCoordinates) { void TranslatedCoordinates::setIsometric(IsometricCoordinates newIsometricCoordinates) {
this->worldCoordinates = CoordinateTransformer::isometricToWorld(newIsometricCoordinates); this->worldCoordinates = CoordinateTransformer::isometricToWorld(newIsometricCoordinates);
} }
void TranslatedCoordinates::set(const TranslatedCoordinates& newCoordinates) { void TranslatedCoordinates::setTranslated(const TranslatedCoordinates& newCoordinates) {
this->worldCoordinates = newCoordinates.world(); this->worldCoordinates = newCoordinates.world();
} }
@ -54,7 +54,7 @@ void TranslatedCoordinates::setParent(std::shared_ptr<TranslatedCoordinates> par
this->worldCoordinates = offset; this->worldCoordinates = offset;
} }
void TranslatedCoordinates::set(GridCoordinates newGridCoordinates) void TranslatedCoordinates::setGrid(GridCoordinates newGridCoordinates)
{ {
this->worldCoordinates = {newGridCoordinates.x + 0.5f, newGridCoordinates.y + 0.5f, 0}; this->worldCoordinates = {newGridCoordinates.x + 0.5f, newGridCoordinates.y + 0.5f, 0};
} }
@ -71,5 +71,5 @@ void TranslatedCoordinates::setScreenOffset(IsometricCoordinates offset)
TranslatedCoordinates::TranslatedCoordinates(GridCoordinates gridCoordinates) TranslatedCoordinates::TranslatedCoordinates(GridCoordinates gridCoordinates)
{ {
set(gridCoordinates); setGrid(gridCoordinates);
} }

View file

@ -17,13 +17,13 @@ public:
[[nodiscard]] GridCoordinates grid() const; [[nodiscard]] GridCoordinates grid() const;
void set(WorldCoordinates newWorldCoordinates); void setWorld(WorldCoordinates newWorldCoordinates);
void set(const TranslatedCoordinates& newCoordinates); void setTranslated(const TranslatedCoordinates& newCoordinates);
void set(IsometricCoordinates newIsometricCoordinates); void setIsometric(IsometricCoordinates newIsometricCoordinates);
void set(GridCoordinates newGridCoordinates); void setGrid(GridCoordinates newGridCoordinates);
void move(WorldCoordinates deltaWorldCoordinates); void move(WorldCoordinates deltaWorldCoordinates);

View file

@ -98,7 +98,7 @@ void TrackingView::followTrackables()
auto trackingPoint = getTrackingArea().getCenter(); auto trackingPoint = getTrackingArea().getCenter();
if (DEVELOPER_MODE) if (DEVELOPER_MODE)
{ {
marker->coordinates->set(IsometricCoordinates(trackingPoint)); marker->coordinates->setIsometric(IsometricCoordinates(trackingPoint));
} }
// Calculate distance to target to check how to handle it // Calculate distance to target to check how to handle it

View file

@ -7,8 +7,8 @@
struct TrackingViewOptions struct TrackingViewOptions
{ {
/** /**
* Value >1 to set pixel radius. * Value >1 to setWorld pixel radius.
* Value between 0 and 1 to set relative radius based on smallest half-axis-size. * Value between 0 and 1 to setWorld relative radius based on smallest half-axis-size.
*/ */
float freeMoveThreshold = DEF_TV_FREE_MOVE_THRESHOLD; float freeMoveThreshold = DEF_TV_FREE_MOVE_THRESHOLD;
@ -22,24 +22,24 @@ struct TrackingViewOptions
float softResizeSpeed = DEF_TV_SOFT_RESIZE_SPEED; float softResizeSpeed = DEF_TV_SOFT_RESIZE_SPEED;
/** /**
* If set to 0, view will not be limited. * If setWorld to 0, view will not be limited.
*/ */
sf::Vector2f minViewSize = DEF_TV_MIN_VIEW_SIZE; sf::Vector2f minViewSize = DEF_TV_MIN_VIEW_SIZE;
/** /**
* If set to 0, view will not be limited. * If setWorld to 0, view will not be limited.
*/ */
sf::Vector2f maxViewSize = DEF_TV_MAX_VIEW_SIZE; sf::Vector2f maxViewSize = DEF_TV_MAX_VIEW_SIZE;
/** /**
* Will be added to tracked area size twice, as padding for each side. * Will be added to tracked area size twice, as padding for each side.
* Value >1 to set pixel padding. * Value >1 to setWorld pixel padding.
* Value between 0 and 1 to set relative padding. * Value between 0 and 1 to setWorld relative padding.
*/ */
sf::Vector2f viewSizePadding = DEF_TV_VIEW_SIZE_PADDING; sf::Vector2f viewSizePadding = DEF_TV_VIEW_SIZE_PADDING;
/** /**
* If set to true, view will add all new players automatically and remove them accordingly, based on PlayerCollection. * If setWorld to true, view will add all new players automatically and remove them accordingly, based on PlayerCollection.
*/ */
bool addPlayersDynamically = DEF_TV_ADD_PLAYERS_DYNAMICALLY; bool addPlayersDynamically = DEF_TV_ADD_PLAYERS_DYNAMICALLY;
}; };

View file

@ -5,7 +5,7 @@ std::shared_ptr<Collectable> CollectableFactory::createFromInLevelConfig(const C
auto collectableConfig = config.collectableConfig; auto collectableConfig = config.collectableConfig;
auto collectable = std::make_shared<Collectable>(); auto collectable = std::make_shared<Collectable>();
collectable->coordinates->set(config.position); collectable->coordinates->setGrid(config.position);
collectable->setSprite(collectableConfig.spriteName); collectable->setSprite(collectableConfig.spriteName);
return collectable; return collectable;

View file

@ -8,28 +8,28 @@
#include "../collectables/collectable_in_level.hpp" #include "../collectables/collectable_in_level.hpp"
#include <vector> #include <vector>
#include "../../sprites/tiling/tilemap_config.hpp" #include "../../sprites/tiling/tilemap_config.hpp"
#include "../../sprites/sprite_factory.hpp"
struct LevelConfig struct LevelConfig
{ {
std::string name; std::string name;
sf::Vector2f worldMapSize = {}; sf::Vector2i worldMapSize = {};
TileMapConfig tileMapConfig = {}; TileMapConfig tileMapConfig = {};
std::vector<GridCoordinates> playerSpawnPoints = {}; std::vector<GridCoordinates> playerSpawnPoints = {};
std::vector<CollectableInLevel> collectables = {}; std::vector<CollectableInLevel> collectables = {};
LevelConfig(std::string name, LevelConfig(std::string name,
const std::string &tileMapName,
const std::vector<GridCoordinates> &playerSpawnPoints, const std::vector<GridCoordinates> &playerSpawnPoints,
const std::vector<CollectableInLevel> &collectables = {}) const std::vector<CollectableInLevel> &collectables,
const TileMapConfig &tileMapConfig)
: name(std::move(name)), : name(std::move(name)),
worldMapSize(worldMapSize), playerSpawnPoints(playerSpawnPoints),
playerSpawnPoints(playerSpawnPoints) tileMapConfig(tileMapConfig)
{ {
tileMapConfig = TileMapConfig(tileMapName, {});
worldMapSize = tileMapConfig.getSize(); worldMapSize = tileMapConfig.getSize();
// Remove invalid collectables // Remove invalid collectables
for (auto &collectable : collectables) for (auto &collectable: collectables)
{ {
if (collectable.isValid()) if (collectable.isValid())
{ {

View file

@ -20,6 +20,8 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig)
PlayerCollection::getInstance()->clear(); PlayerCollection::getInstance()->clear();
// Add basic game objects // Add basic game objects
game->addGameObject(SpriteFactory::createTileMap(levelConfig.tileMapConfig));
if (DEVELOPER_MODE) if (DEVELOPER_MODE)
{ {
game->addGameObject(std::make_shared<GridDebugLayer>(0, 50, 0, 50)); game->addGameObject(std::make_shared<GridDebugLayer>(0, 50, 0, 50));
@ -43,12 +45,6 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig)
// Add physics simulations // Add physics simulations
game->addGameObject(MapSimulation::getInstance()); game->addGameObject(MapSimulation::getInstance());
// For every depth, add a hole depth simulation
for (int depth = 0; depth < maxDepth; depth++)
{
auto depthCollection = collectablesCollection->getDepthCollection(depth);
game->addGameObject(std::make_shared<HoleDepthSimulation>(depthCollection));
}
LOG(INFO) << "Finished loading level '" << levelConfig.name << "'."; LOG(INFO) << "Finished loading level '" << levelConfig.name << "'.";
} }

View file

@ -20,7 +20,7 @@ void MapPlayer::updateSimulationPosition()
void MapPlayer::updatePlayerPosition() const void MapPlayer::updatePlayerPosition() const
{ {
b2Vec2 playerPosition = body->GetPosition(); b2Vec2 playerPosition = body->GetPosition();
player->coordinates->set(sf::Vector2f(playerPosition.x, playerPosition.y)); player->coordinates->setWorld({playerPosition.x, playerPosition.y});
} }
void MapPlayer::updateShape() void MapPlayer::updateShape()
@ -28,7 +28,8 @@ void MapPlayer::updateShape()
shapeRadius = player->getWorldRadius(); shapeRadius = player->getWorldRadius();
b2Fixture *oldFixture = body->GetFixtureList(); b2Fixture *oldFixture = body->GetFixtureList();
if (oldFixture != nullptr) { if (oldFixture != nullptr)
{
body->DestroyFixture(oldFixture); body->DestroyFixture(oldFixture);
} }

View file

@ -33,7 +33,7 @@ void MapSimulation::physicsUpdate()
} }
} }
void MapSimulation::resetMap(sf::Vector2f worldMapSize) void MapSimulation::resetMap(sf::Vector2<int> worldMapSize)
{ {
// Clear all players // Clear all players
for (auto &mapPlayer: mapPlayersById) for (auto &mapPlayer: mapPlayersById)

View file

@ -16,7 +16,7 @@ public:
void physicsUpdate() override; void physicsUpdate() override;
void resetMap(sf::Vector2f worldMapSize); void resetMap(sf::Vector2<int> worldMapSize);
static std::shared_ptr<MapSimulation> getInstance(); static std::shared_ptr<MapSimulation> getInstance();

View file

@ -8,7 +8,7 @@ Player::Player(std::shared_ptr<InputIdentity> assignedInput, const std::string &
: spawnPosition(initCoordinates) : spawnPosition(initCoordinates)
{ {
playerId = playerCreationCounter++; playerId = playerCreationCounter++;
coordinates->set(spawnPosition); coordinates->setTranslated(spawnPosition);
input = std::move(assignedInput); input = std::move(assignedInput);
@ -94,8 +94,3 @@ void Player::setWorldRadius(float newWorldRadius)
skinSprite->setSize(newSize); skinSprite->setSize(newSize);
skinSprite->coordinates->setScreenOffset(IsometricCoordinates(-newSize / 2.f)); skinSprite->coordinates->setScreenOffset(IsometricCoordinates(-newSize / 2.f));
} }
Player::~Player()
{
LOG(INFO) << "Player " << playerId << " destroyed.";
}

View file

@ -13,8 +13,6 @@ public:
Player(std::shared_ptr<InputIdentity> assignedInput, const std::string &skinRessourceName, Player(std::shared_ptr<InputIdentity> assignedInput, const std::string &skinRessourceName,
GridCoordinates initCoordinates); GridCoordinates initCoordinates);
~Player();
void update() override; void update() override;
[[nodiscard]] sf::Vector2f getTrackablePosition() const override; [[nodiscard]] sf::Vector2f getTrackablePosition() const override;

View file

@ -8,9 +8,19 @@
#define INITIAL_LEVEL "default" #define INITIAL_LEVEL "default"
std::map<std::string, LevelConfig> const all_levels = { std::map<std::string, LevelConfig> const all_levels = {
{"default", LevelConfig("Default", "grass", {{0, 0}}, { {"default", LevelConfig("Default", {{0, 0}}, {
CollectableInLevel("box", {5, 5}) CollectableInLevel("box", {5, 5})},
})} TileMapConfig("iso-tiles", {{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 0, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 1, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4}})
)}
}; };
#endif //HOLESOME_LEVELS_HPP #endif //HOLESOME_LEVELS_HPP

View file

@ -694,7 +694,7 @@ class ConfigurationTypeHelper : base::StaticClass {
/// This bool represent whether or not to exit iterating through configurations. /// This bool represent whether or not to exit iterating through configurations.
static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function<bool(void)>& fn); static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function<bool(void)>& fn);
}; };
/// @brief Flags used while writing logs. This flags are set by user /// @brief Flags used while writing logs. This flags are setWorld by user
enum class LoggingFlag : base::type::EnumType { enum class LoggingFlag : base::type::EnumType {
/// @brief Makes sure we have new line for each container log entry /// @brief Makes sure we have new line for each container log entry
NewLineForContainer = 1, NewLineForContainer = 1,
@ -1701,7 +1701,7 @@ class Configuration : public Loggable {
} }
/// @brief Set string based configuration value /// @brief Set string based configuration value
/// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values /// @param value Value to setWorld. Values have to be std::string; For boolean values use "true", "false", for any integral values
/// use them in quotes. They will be parsed when configuring /// use them in quotes. They will be parsed when configuring
inline void setValue(const std::string& value) { inline void setValue(const std::string& value) {
m_value = value; m_value = value;
@ -1735,9 +1735,9 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @brief Default constructor with empty repository /// @brief Default constructor with empty repository
Configurations(void); Configurations(void);
/// @brief Constructor used to set configurations using configuration file. /// @brief Constructor used to setWorld configurations using configuration file.
/// @param configurationFile Full path to configuration file /// @param configurationFile Full path to configuration file
/// @param useDefaultsForRemaining Lets you set the remaining configurations to default. /// @param useDefaultsForRemaining Lets you setWorld the remaining configurations to default.
/// @param base If provided, this configuration will be based off existing repository that this argument is pointing to. /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to.
/// @see parseFromFile(const std::string&, Configurations* base) /// @see parseFromFile(const std::string&, Configurations* base)
/// @see setRemainingToDefault() /// @see setRemainingToDefault()
@ -1750,7 +1750,7 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @brief Parses configuration from file. /// @brief Parses configuration from file.
/// @param configurationFile Full path to configuration file /// @param configurationFile Full path to configuration file
/// @param base Configurations to base new configuration repository off. This value is used when you want to use /// @param base Configurations to base new configuration repository off. This value is used when you want to use
/// existing Configurations to base all the values and then set rest of configuration via configuration file. /// existing Configurations to base all the values and then setWorld rest of configuration via configuration file.
/// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you
/// do not proceed without successful parse. /// do not proceed without successful parse.
bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr); bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr);
@ -1760,7 +1760,7 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary
/// new line characters are provided. /// new line characters are provided.
/// @param base Configurations to base new configuration repository off. This value is used when you want to use /// @param base Configurations to base new configuration repository off. This value is used when you want to use
/// existing Configurations to base all the values and then set rest of configuration via configuration text. /// existing Configurations to base all the values and then setWorld rest of configuration via configuration text.
/// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you
/// do not proceed without successful parse. /// do not proceed without successful parse.
bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr); bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr);
@ -1783,9 +1783,9 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @brief Sets value of configuration for specified level. /// @brief Sets value of configuration for specified level.
/// ///
/// @detail Any existing configuration for specified level will be replaced. Also note that configuration types /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types
/// ConfigurationType::SubsecondPrecision and ConfigurationType::PerformanceTracking will be ignored if not set for /// ConfigurationType::SubsecondPrecision and ConfigurationType::PerformanceTracking will be ignored if not setWorld for
/// Level::Global because these configurations are not dependant on level. /// Level::Global because these configurations are not dependant on level.
/// @param level Level to set configuration for (el::Level). /// @param level Level to setWorld configuration for (el::Level).
/// @param configurationType Type of configuration (el::ConfigurationType) /// @param configurationType Type of configuration (el::ConfigurationType)
/// @param value A string based value. Regardless of what the data type of configuration is, it will always be string /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string
/// from users' point of view. This is then parsed later to be used internally. /// from users' point of view. This is then parsed later to be used internally.
@ -1795,7 +1795,7 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
void set(Level level, ConfigurationType configurationType, const std::string& value); void set(Level level, ConfigurationType configurationType, const std::string& value);
/// @brief Sets single configuration based on other single configuration. /// @brief Sets single configuration based on other single configuration.
/// @see set(Level level, ConfigurationType configurationType, const std::string& value) /// @see setWorld(Level level, ConfigurationType configurationType, const std::string& value)
void set(Configuration* conf); void set(Configuration* conf);
inline Configuration* get(Level level, ConfigurationType configurationType) { inline Configuration* get(Level level, ConfigurationType configurationType) {
@ -1806,7 +1806,7 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @brief Sets configuration for all levels. /// @brief Sets configuration for all levels.
/// @param configurationType Type of configuration /// @param configurationType Type of configuration
/// @param value String based value /// @param value String based value
/// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) /// @see Configurations::setWorld(Level level, ConfigurationType configurationType, const std::string& value)
inline void setGlobally(ConfigurationType configurationType, const std::string& value) { inline void setGlobally(ConfigurationType configurationType, const std::string& value) {
setGlobally(configurationType, value, false); setGlobally(configurationType, value, false);
} }
@ -1819,7 +1819,7 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @brief Gets configuration file used in parsing this configurations. /// @brief Gets configuration file used in parsing this configurations.
/// ///
/// @detail If this repository was set manually or by text this returns empty string. /// @detail If this repository was setWorld manually or by text this returns empty string.
inline const std::string& configurationFile(void) const { inline const std::string& configurationFile(void) const {
return m_configurationFile; return m_configurationFile;
} }
@ -1827,11 +1827,11 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @brief Sets configurations to "factory based" configurations. /// @brief Sets configurations to "factory based" configurations.
void setToDefault(void); void setToDefault(void);
/// @brief Lets you set the remaining configurations to default. /// @brief Lets you setWorld the remaining configurations to default.
/// ///
/// @detail By remaining, it means that the level/type a configuration does not exist for. /// @detail By remaining, it means that the level/type a configuration does not exist for.
/// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets
/// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e, /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is setWorld to default i.e,
/// true. If you dont do this explicitly (either by calling this function or by using second param in Constructor /// true. If you dont do this explicitly (either by calling this function or by using second param in Constructor
/// and try to access a value, an error is thrown /// and try to access a value, an error is thrown
void setRemainingToDefault(void); void setRemainingToDefault(void);
@ -1846,7 +1846,7 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @param configurationFile Full path to configuration file /// @param configurationFile Full path to configuration file
/// @param sender Sender configurations pointer. Usually 'this' is used from calling class /// @param sender Sender configurations pointer. Usually 'this' is used from calling class
/// @param base Configurations to base new configuration repository off. This value is used when you want to use /// @param base Configurations to base new configuration repository off. This value is used when you want to use
/// existing Configurations to base all the values and then set rest of configuration via configuration file. /// existing Configurations to base all the values and then setWorld rest of configuration via configuration file.
/// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you
/// do not proceed without successful parse. /// do not proceed without successful parse.
static bool parseFromFile(const std::string& configurationFile, Configurations* sender, static bool parseFromFile(const std::string& configurationFile, Configurations* sender,
@ -1860,7 +1860,7 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @param configurationsString the configuration in plain text format /// @param configurationsString the configuration in plain text format
/// @param sender Sender configurations pointer. Usually 'this' is used from calling class /// @param sender Sender configurations pointer. Usually 'this' is used from calling class
/// @param base Configurations to base new configuration repository off. This value is used when you want to use /// @param base Configurations to base new configuration repository off. This value is used when you want to use
/// existing Configurations to base all the values and then set rest of configuration via configuration text. /// existing Configurations to base all the values and then setWorld rest of configuration via configuration text.
/// @return True if successfully parsed, false otherwise. /// @return True if successfully parsed, false otherwise.
static bool parseFromText(const std::string& configurationsString, Configurations* sender, static bool parseFromText(const std::string& configurationsString, Configurations* sender,
Configurations* base = nullptr); Configurations* base = nullptr);
@ -1883,7 +1883,7 @@ class Configurations : public base::utils::RegistryWithPred<Configuration, Confi
/// @brief Unsafely sets configuration if does not already exist /// @brief Unsafely sets configuration if does not already exist
void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value); void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value);
/// @brief Thread unsafe set /// @brief Thread unsafe setWorld
void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value); void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value);
/// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true
@ -3839,7 +3839,7 @@ class Loggers : base::StaticClass {
static std::vector<std::string>* populateAllLoggerIds(std::vector<std::string>* targetList); static std::vector<std::string>* populateAllLoggerIds(std::vector<std::string>* targetList);
/// @brief Sets configurations from global configuration file. /// @brief Sets configurations from global configuration file.
static void configureFromGlobal(const char* globalConfigurationFilePath); static void configureFromGlobal(const char* globalConfigurationFilePath);
/// @brief Configures loggers using command line arg. Ensure you have already set command line args, /// @brief Configures loggers using command line arg. Ensure you have already setWorld command line args,
/// @return False if invalid argument or argument with no value provided, true if attempted to configure logger. /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger.
/// If true is returned that does not mean it has been configured successfully, it only means that it /// If true is returned that does not mean it has been configured successfully, it only means that it
/// has attempted to configure logger using configuration file provided in argument /// has attempted to configure logger using configuration file provided in argument

View file

@ -44,3 +44,8 @@ sf::Vector2f AnimatedSprite::getSize() const
auto textureSize = sprites[currentFrame].getTextureRect(); auto textureSize = sprites[currentFrame].getTextureRect();
return {textureSize.width * scale.x, textureSize.height * scale.y}; return {textureSize.width * scale.x, textureSize.height * scale.y};
} }
sf::Sprite AnimatedSprite::getSprite() const
{
return sprites[currentFrame];
}

View file

@ -9,7 +9,7 @@
class AnimatedSprite : public GameObject, public Sprite class AnimatedSprite : public GameObject, public Sprite
{ {
public: public:
AnimatedSprite(const std::vector<sf::Sprite>& sprites, const sf::Vector2f& size = sf::Vector2f(0, 0)); explicit AnimatedSprite(const std::vector<sf::Sprite>& sprites, const sf::Vector2f& size = sf::Vector2f(0, 0));
void update() override; void update() override;
@ -19,7 +19,9 @@ public:
void setSize(const sf::Vector2f &size) override; void setSize(const sf::Vector2f &size) override;
sf::Vector2f getSize() const override; [[nodiscard]] sf::Vector2f getSize() const override;
sf::Sprite getSprite() const override;
private: private:
int currentFrame = 0; int currentFrame = 0;

View file

@ -37,3 +37,8 @@ sf::Vector2f SingleSprite::getSize() const
auto textureSize = sprite.getTextureRect(); auto textureSize = sprite.getTextureRect();
return {textureSize.width * sprite.getScale().x, textureSize.height * sprite.getScale().y}; return {textureSize.width * sprite.getScale().x, textureSize.height * sprite.getScale().y};
} }
sf::Sprite SingleSprite::getSprite() const
{
return sprite;
}

View file

@ -19,6 +19,8 @@ public:
sf::Vector2f getSize() const override; sf::Vector2f getSize() const override;
sf::Sprite getSprite() const override;
private: private:
sf::Sprite sprite; sf::Sprite sprite;
}; };

View file

@ -3,16 +3,26 @@
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <vector> #include <vector>
#include <memory>
#include <SFML/Graphics/Sprite.hpp> #include <SFML/Graphics/Sprite.hpp>
class Sprite class Sprite
{ {
public: public:
virtual void setSize(const sf::Vector2f &size) virtual void setSize(const sf::Vector2f &size)
{} {
throw std::runtime_error("Sprite::setSize() not implemented");
}
virtual sf::Vector2f getSize() const [[nodiscard]] virtual sf::Vector2f getSize() const
{ return {0, 0}; } {
throw std::runtime_error("Sprite::getSize() not implemented");
}
[[nodiscard]] virtual sf::Sprite getSprite() const
{
throw std::runtime_error("Sprite::getSprite() not implemented");
}
}; };
#endif //HOLESOME_SPRITE_HPP #endif //HOLESOME_SPRITE_HPP

View file

@ -2,7 +2,7 @@
#include "../texture_config.h" #include "../texture_config.h"
#include "texture_manager.hpp" #include "texture_manager.hpp"
std::shared_ptr<SingleSprite> SpriteFactory::createSingleSprite(const std::string& name, sf::Vector2f size) std::shared_ptr<SingleSprite> SpriteFactory::createSingleSprite(const std::string &name, sf::Vector2f size)
{ {
// Get sprite config // Get sprite config
auto sprite_config = all_sprites.find(name); auto sprite_config = all_sprites.find(name);
@ -44,7 +44,7 @@ std::shared_ptr<SingleSprite> SpriteFactory::createSingleSprite(const std::strin
return sprite; return sprite;
} }
std::shared_ptr<AnimatedSprite> SpriteFactory::createAnimatedSprite(const std::string& name, sf::Vector2f size) std::shared_ptr<AnimatedSprite> SpriteFactory::createAnimatedSprite(const std::string &name, sf::Vector2f size)
{ {
// Get animation config // Get animation config
auto animation_config = all_animations.find(name); auto animation_config = all_animations.find(name);
@ -72,7 +72,7 @@ std::shared_ptr<AnimatedSprite> SpriteFactory::createAnimatedSprite(const std::s
return animation; return animation;
} }
std::shared_ptr<SpriteSheet> SpriteFactory::createSheet(const std::string& name) std::shared_ptr<SpriteSheet> SpriteFactory::createSheet(const std::string &name)
{ {
// Get config // Get config
auto sheet_config = all_sheets.find(name); auto sheet_config = all_sheets.find(name);
@ -96,32 +96,6 @@ std::shared_ptr<SpriteSheet> SpriteFactory::createSheet(const std::string& name)
return std::make_shared<SpriteSheet>(texture, config.columns, config.rows); return std::make_shared<SpriteSheet>(texture, config.columns, config.rows);
} }
std::shared_ptr<TileMap> 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> 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<TileMap>(sheet, config.tileSize, config.tileCount);
tilemap->setTilemap(config.tilemap);
return tilemap;
}
std::shared_ptr<TileSet> SpriteFactory::createTileSet(const std::string &name) std::shared_ptr<TileSet> SpriteFactory::createTileSet(const std::string &name)
{ {
// Get config // Get config
@ -145,3 +119,20 @@ std::shared_ptr<TileSet> SpriteFactory::createTileSet(const std::string &name)
LOG(INFO) << "Creating tileset " << name; LOG(INFO) << "Creating tileset " << name;
return std::make_shared<TileSet>(sheet, config.tileIndices); return std::make_shared<TileSet>(sheet, config.tileIndices);
} }
std::shared_ptr<SingleSprite> SpriteFactory::copySingleSprite(const std::shared_ptr<SingleSprite>& sprite)
{
return std::make_shared<SingleSprite>(sprite->getSprite(), sprite->getSize());
}
std::shared_ptr<TileMap> SpriteFactory::createTileMap(TileMapConfig config)
{
auto tileSet = createTileSet(config.tileSet);
if (tileSet == nullptr)
{
LOG(ERROR) << "Tileset " << config.tileSet << " not found. Could not create tilemap.";
return nullptr;
}
return std::make_shared<TileMap>(tileSet, config.tiles);
}

View file

@ -10,6 +10,7 @@
#include "../logging/easylogging++.h" #include "../logging/easylogging++.h"
#include "tiling/tilemap.hpp" #include "tiling/tilemap.hpp"
#include "tiling/tileset.hpp" #include "tiling/tileset.hpp"
#include "tiling/tilemap_config.hpp"
class SpriteFactory class SpriteFactory
{ {
@ -17,8 +18,9 @@ public:
static std::shared_ptr<SingleSprite> createSingleSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0)); static std::shared_ptr<SingleSprite> createSingleSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0));
static std::shared_ptr<AnimatedSprite> createAnimatedSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0)); static std::shared_ptr<AnimatedSprite> createAnimatedSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0));
static std::shared_ptr<SpriteSheet> createSheet(const std::string& name); static std::shared_ptr<SpriteSheet> createSheet(const std::string& name);
static std::shared_ptr<TileMap> createTileMap(const std::string& name); static std::shared_ptr<TileSet> createTileSet(const std::string &name);
std::shared_ptr<TileSet> createTileSet(const std::string &name); static std::shared_ptr<SingleSprite> copySingleSprite(const std::shared_ptr<SingleSprite>& sprite);
static std::shared_ptr<TileMap> createTileMap(TileMapConfig config);
}; };

View file

@ -1 +0,0 @@
#include "tilemap.hpp"

View file

@ -1,13 +0,0 @@
#ifndef HOLESOME_TILEMAP_HPP
#define HOLESOME_TILEMAP_HPP
#include "../../game/game_object.h"
class Tilemap : public GameObject
{
};
#endif //HOLESOME_TILEMAP_HPP

View file

@ -1,12 +0,0 @@
#ifndef HOLESOME_TILEMAP_CONFIG_HPP
#define HOLESOME_TILEMAP_CONFIG_HPP
#include <vector>
#include <string>
struct TilemapConfig {
std::string tileSheetName;
std::vector<std::vector<int>> tiles;
};
#endif //HOLESOME_TILEMAP_CONFIG_HPP

View file

@ -1,57 +1,35 @@
#include "tilemap.hpp" #include "tilemap.hpp"
#include "../sprite_factory.hpp"
TileMap::TileMap(std::shared_ptr<TileSet> tileSet, std::vector<std::vector<int>> tiles) TileMap::TileMap(const std::shared_ptr<TileSet> &tileSet, std::vector<std::vector<int>> tiles)
{ {
// resize the vertex array to fit the level size
vertices.setPrimitiveType(sf::Quads);
unsigned int size = tiles.size(); unsigned int size = tiles.size();
vertices.resize(size * size * 4); for (int i = 2 * (size - 1); i >= 0 ; i--)
{
// populate the vertex array, with one quad per tile int x, y;
for (unsigned int y = 0; y < size; ++y) if (i < size) {
for (unsigned int x = 0; x < size; ++x) x = i;
{ y = 0;
// get the current tile number } else {
int tileNumber = tiles[size - 1 - y][x]; x = size - 1;
y = i - size + 1;
// 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);
} }
for (; x >= 0 && y < size; x--, y++)
{
auto tileId = tiles[size - 1 - y][x];
auto sprite = tileSet->getTile(tileId);
createTileAtGridPosition(sprite, {x, y});
}
}
} }
void TileMap::draw(sf::RenderWindow *window) void TileMap::createTileAtGridPosition(const std::shared_ptr<SingleSprite> &sprite, GridCoordinates coordinates)
{ {
window->draw(*this); auto tile = SpriteFactory::copySingleSprite(sprite);
}
// Move to tile diagonal top left, since center of that tile is correct position for sprite corner
void TileMap::draw(sf::RenderTarget &target, sf::RenderStates states) const coordinates.y += 1;
{
// apply the transform addChildScreenOffset(tile, TranslatedCoordinates(coordinates).isometric());
// TODO? NEEDED?
// states.transform *= getTransform();
// apply the tileset texture
states.texture = &tileMapTexture;
// draw the vertex array
target.draw(vertices, states);
} }

View file

@ -8,18 +8,12 @@
#include "../../game/game_object.h" #include "../../game/game_object.h"
#include "tileset.hpp" #include "tileset.hpp"
class TileMap : public GameObject, public sf::Drawable class TileMap : public GameObject
{ {
public: public:
TileMap(std::shared_ptr<TileSet> tileSet, std::vector<std::vector<int>> tiles); TileMap(const std::shared_ptr<TileSet>& tileSet, std::vector<std::vector<int>> tiles);
void draw(sf::RenderWindow *window) override; void createTileAtGridPosition(const std::shared_ptr<SingleSprite>& sprite, GridCoordinates coordinates);
void draw(sf::RenderTarget &target, sf::RenderStates states) const override;
private:
sf::VertexArray vertices;
sf::Texture tileMapTexture;
}; };

View file

@ -9,22 +9,18 @@
struct TileMapConfig struct TileMapConfig
{ {
std::string tileSheet; std::string tileSet;
std::vector<int> backgroundTileSelection = {};
std::vector<std::vector<int>> tiles = {}; std::vector<std::vector<int>> tiles = {};
TileMapConfig(std::string tileSheet, std::vector<std::vector<int>> tiles, TileMapConfig(std::string tileSheet, const std::vector<std::vector<int>> &tiles)
std::vector<int> backgroundTileSelection = {})
{ {
this->tileSheet = std::move(tileSheet); this->tileSet = std::move(tileSheet);
this->backgroundTileSelection = std::move(backgroundTileSelection); this->tiles = tiles;
this->tiles = std::move(tiles);
// Make sure all rows are the same length and that the map is square // Make sure all rows are the same length and that the map is square
int size = tiles.size(); unsigned int size = tiles.size();
for (auto &row : tiles) for (auto &row: tiles)
{ {
if (row.size() != size) if (row.size() != size)
{ {
@ -35,10 +31,10 @@ struct TileMapConfig
TileMapConfig() = default; TileMapConfig() = default;
sf::Vector2f getSize() const [[nodiscard]] sf::Vector2<int> getSize() const
{ {
int size = tiles.size(); int size = tiles.size();
return {static_cast<float>(size), static_cast<float>(size)}; return {size, size};
} }
}; };

View file

@ -1,6 +1,26 @@
#include "tileset.hpp" #include "tileset.hpp"
TileSet::TileSet(const std::shared_ptr<SpriteSheet>& sheet, const std::vector<int>& tileIndices) TileSet::TileSet(const std::shared_ptr<SpriteSheet> &sheet, const std::vector<int> &tileIndices)
{ {
float tileWidth = TranslatedCoordinates(WorldCoordinates{1, 0}).isometric().x -
TranslatedCoordinates(WorldCoordinates{0, 1}).isometric().x;
sf::Vector2f tileSize = sf::Vector2f(1, 1) * tileWidth;
// Load desired tiles from sheet
for (auto index: tileIndices)
{
auto sprite = sheet->getSprite(index);
sprite->setSize(tileSize);
tiles.push_back(sprite);
}
}
std::shared_ptr<SingleSprite> TileSet::getTile(int index) const
{
if (index < 0 || index >= tiles.size())
{
throw std::runtime_error("Tile index out of range");
}
return tiles[index];
} }

View file

@ -3,11 +3,17 @@
#include "../sprite_sheet.hpp" #include "../sprite_sheet.hpp"
#include "../versatile_sprite.hpp"
class TileSet class TileSet
{ {
public: public:
TileSet(const std::shared_ptr<SpriteSheet>& sheet, const std::vector<int>& tileIndices); TileSet(const std::shared_ptr<SpriteSheet>& sheet, const std::vector<int>& tileIndices);
[[nodiscard]] std::shared_ptr<SingleSprite> getTile(int index) const;
private:
std::vector<std::shared_ptr<SingleSprite>> tiles;
}; };

View file

@ -47,3 +47,17 @@ sf::Vector2f VersatileSprite::getSize() const
return Sprite::getSize(); return Sprite::getSize();
} }
} }
sf::Sprite VersatileSprite::getSprite() const
{
if (singleSprite != nullptr)
{
return singleSprite->getSprite();
} else if (animatedSprite != nullptr)
{
return animatedSprite->getSprite();
} else
{
return {};
}
}

View file

@ -12,11 +12,13 @@
class VersatileSprite : public GameObject, public Sprite class VersatileSprite : public GameObject, public Sprite
{ {
public: public:
VersatileSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0)); explicit VersatileSprite(const std::string& name, sf::Vector2f size = sf::Vector2f(0, 0));
void setSize(const sf::Vector2f &size) override; void setSize(const sf::Vector2f &size) override;
sf::Vector2f getSize() const override; [[nodiscard]] sf::Vector2f getSize() const override;
sf::Sprite getSprite() const override;
private: private:
std::shared_ptr<SingleSprite> singleSprite = nullptr; std::shared_ptr<SingleSprite> singleSprite = nullptr;

View file

@ -20,7 +20,8 @@ std::map<std::string, std::string> const all_textures = {
{"edge", "assets/edge.png"}, {"edge", "assets/edge.png"},
{"ring", "assets/ring.png"}, {"ring", "assets/ring.png"},
{"grasses", "assets/grass_plus.png"}, {"grasses", "assets/grass_plus.png"},
{"hole", "assets/hole.png"} {"hole", "assets/hole.png"},
{"iso-tiles", "assets/isometric-tiles.png"}
}; };
/** /**
@ -28,8 +29,9 @@ std::map<std::string, std::string> const all_textures = {
* The key is the name of the sheet, the value is the sheet config. * The key is the name of the sheet, the value is the sheet config.
*/ */
std::map<std::string, SheetConfig> const all_sheets = { std::map<std::string, SheetConfig> const all_sheets = {
{"numbers", SheetConfig("numbers", 4, 2)}, {"numbers", SheetConfig("numbers", 4, 2)},
{"grasses", SheetConfig("grasses", 25, 14)} {"grasses", SheetConfig("grasses", 25, 14)},
{"iso-tiles", SheetConfig("iso-tiles", 6, 2)}
}; };
/** /**
@ -45,14 +47,18 @@ std::map<std::string, AnimationConfig> const all_animations = {
* The key is the name of the singleSprite, the value is the singleSprite config. * The key is the name of the singleSprite, the value is the singleSprite config.
*/ */
std::map<std::string, SpriteConfig> const all_sprites = { std::map<std::string, SpriteConfig> const all_sprites = {
{"64", SpriteConfig("64")}, {"64", SpriteConfig("64")},
{"edge", SpriteConfig("edge")}, {"edge", SpriteConfig("edge")},
{"ring", SpriteConfig("ring")}, {"ring", SpriteConfig("ring")},
{"hole", SpriteConfig("hole")} {"hole", SpriteConfig("hole")}
}; };
/**
* All tilesets used in the game.
* The key is the name of the tileset, the value is the tileset config.
*/
std::map<std::string, TileSetConfig> const all_tilesets = { std::map<std::string, TileSetConfig> const all_tilesets = {
{"grass", TileSetConfig("grasses", {58})} {"iso-tiles", TileSetConfig("iso-tiles", {0, 1, 2, 3, 4, 5})}
}; };
#endif //HOLESOME_TEXTURE_CONFIG_H #endif //HOLESOME_TEXTURE_CONFIG_H

View file

@ -1,21 +0,0 @@
#ifndef HOLESOME_TILEMAPS_HPP
#define HOLESOME_TILEMAPS_HPP
#include <map>
#include <string>
#include "sprites/tiling/tilemap_config.hpp"
std::map<std::string, TileMapConfig> 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