#pragma once #include #include #include #include #include #include #include "Mobs.h" #include "Team.h" namespace td { namespace game { typedef std::pair ChunkCoord; } } namespace std { template <> struct hash { std::size_t operator()(const td::game::ChunkCoord& key) const { // Compute individual hash values for first, // second and third and combine them using XOR // and bit shifting: return ((std::hash()(key.first) ^ (std::hash()(key.second) << 1)) >> 1); } }; } namespace td { namespace protocol { class WorldBeginDataPacket; class WorldDataPacket; } namespace game { class Game; enum class TileType : std::uint8_t { None = 0, Tower, Walk, Decoration, /*Heal, Lava, Bedrock, Freeze, Ice,*/ }; struct Color { std::uint8_t r, g, b; }; struct Tile { virtual TileType getType() const = 0; }; struct TowerTile : Tile { std::uint8_t color_palette_ref; TeamColor team_owner; virtual TileType getType() const { return TileType::Tower; } }; struct WalkableTile : Tile { Direction direction; virtual TileType getType() const { return TileType::Walk; } }; struct DecorationTile : Tile { std::uint16_t color_palette_ref; virtual TileType getType() const { return TileType::Decoration; } }; typedef std::shared_ptr TilePtr; typedef std::vector ChunkPalette; typedef std::shared_ptr WalkableTilePtr; typedef std::array ChunkData; typedef std::uint32_t TileIndex; //32 x 32 area struct Chunk { enum { ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight }; // stores index of tile palette ChunkData tiles{ 0 }; ChunkPalette palette; TileIndex getTileIndex(std::uint16_t tileNumber) const { TileIndex chunkPaletteIndex = tiles.at(tileNumber); if (chunkPaletteIndex == 0) // index 0 means empty tile index 1 = first tile return 0; return palette.at(chunkPaletteIndex); } }; typedef std::shared_ptr ChunkPtr; typedef std::array TowerTileColorPalette; typedef std::vector TilePalette; typedef std::vector MobList; typedef std::array SpawnColorPalette; typedef std::vector TowerList; class World { protected: TowerTileColorPalette m_TowerPlacePalette; Color m_WalkablePalette; std::vector m_DecorationPalette; std::unordered_map m_Chunks; SpawnColorPalette m_SpawnColorPalette; TilePalette m_TilePalette; MobList m_Mobs; TowerList m_Towers; Game* m_Game; public: World(Game* game); bool loadMap(const protocol::WorldBeginDataPacket* worldHeader); bool loadMap(const protocol::WorldDataPacket* worldData); bool loadMapFromFile(const std::string& fileName); bool saveMap(const std::string& fileName) const; void tick(std::uint64_t delta); void spawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir); TowerPtr placeTowerAt(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder); TilePtr getTile(std::int32_t x, std::int32_t y) const; const TowerTileColorPalette& getTowerTileColorPalette() const { return m_TowerPlacePalette; } const Color& getWalkableTileColor() const { return m_WalkablePalette; } const std::vector& getDecorationPalette() const { return m_DecorationPalette; } const TilePalette& getTilePalette() const { return m_TilePalette; } TilePtr getTilePtr(TileIndex index) const { if (index == 0) return nullptr; return m_TilePalette.at(index - 1); } bool CanPlaceLittleTower(const glm::vec2& worldPos, PlayerID player) const; bool CanPlaceBigTower(const glm::vec2& worldPos, PlayerID player) const; TowerPtr getTower(const glm::vec2& position) const; // returns null if no tower is here const std::unordered_map& getChunks() const { return m_Chunks; } const Color& getSpawnColor(TeamColor color) const { return m_SpawnColorPalette[(std::size_t)color]; } const SpawnColorPalette& getSpawnColors() const { return m_SpawnColorPalette; } const MobList& getMobList() const { return m_Mobs; } MobList& getMobList() { return m_Mobs; } const Color* getTileColor(TilePtr tile) const; Team& getRedTeam(); const Team& getRedTeam() const; Team& getBlueTeam(); const Team& getBlueTeam() const; Team& getTeam(TeamColor team); const Team& getTeam(TeamColor team) const; const TowerList& getTowers() const { return m_Towers; }; // Archer Tower virtual void OnArrowShot(MobPtr target, Tower* shooter); private: void moveMobs(std::uint64_t delta); void tickMobs(std::uint64_t delta); void cleanDeadMobs(); }; } // namespace game } // namespace td