246 lines
6.1 KiB
C++
246 lines
6.1 KiB
C++
#pragma once
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include <array>
|
|
|
|
#include "Mobs.h"
|
|
#include "Team.h"
|
|
|
|
namespace td {
|
|
namespace game {
|
|
|
|
struct ChunkCoord {
|
|
std::int16_t x, y;
|
|
|
|
friend bool operator==(const td::game::ChunkCoord& first, const td::game::ChunkCoord& other) {
|
|
return first.x == other.x && first.y == other.y;
|
|
}
|
|
};
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
namespace std {
|
|
template <>
|
|
struct hash<td::game::ChunkCoord> {
|
|
std::size_t operator()(const td::game::ChunkCoord& key) const noexcept {
|
|
return std::hash<std::int16_t>()(key.x << 16 | key.y);
|
|
}
|
|
};
|
|
}
|
|
|
|
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,*/
|
|
};
|
|
|
|
static constexpr Color BLACK{ 0, 0, 0 };
|
|
static constexpr Color WHITE{ 255, 255, 255 };
|
|
|
|
static constexpr Color RED{ 255, 0, 0 };
|
|
static constexpr Color GREEN{ 0, 255, 0 };
|
|
static constexpr Color BLUE{ 0, 0, 255 };
|
|
|
|
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<Tile> TilePtr;
|
|
typedef std::vector<std::uint16_t> ChunkPalette;
|
|
|
|
typedef std::shared_ptr<WalkableTile> WalkableTilePtr;
|
|
|
|
typedef std::uint32_t TileIndex;
|
|
|
|
//32 x 32 area
|
|
struct Chunk {
|
|
enum { ChunkWidth = 32, ChunkHeight = 32, ChunkSize = ChunkWidth * ChunkHeight };
|
|
typedef std::array<std::uint16_t, ChunkSize> ChunkData;
|
|
|
|
// 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<Chunk> ChunkPtr;
|
|
|
|
typedef std::array<Color, 2> TowerTileColorPalette;
|
|
|
|
typedef std::vector<TilePtr> TilePalette;
|
|
|
|
typedef std::vector<MobPtr> MobList;
|
|
|
|
typedef std::array<Color, 2> SpawnColorPalette;
|
|
|
|
typedef std::vector<TowerPtr> TowerList;
|
|
|
|
class WorldListener {
|
|
public:
|
|
WorldListener() {}
|
|
|
|
virtual void OnTowerAdd(TowerPtr tower) {}
|
|
virtual void OnTowerRemove(TowerPtr tower) {}
|
|
|
|
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) {}
|
|
|
|
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) {}
|
|
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) {}
|
|
};
|
|
|
|
typedef utils::ObjectNotifier<WorldListener> WorldNotifier;
|
|
|
|
class World : public WorldListener, public MobListener {
|
|
protected:
|
|
TowerTileColorPalette m_TowerPlacePalette;
|
|
Color m_WalkablePalette;
|
|
std::vector<Color> m_DecorationPalette;
|
|
Color m_Background;
|
|
|
|
std::unordered_map<ChunkCoord, ChunkPtr> m_Chunks;
|
|
|
|
SpawnColorPalette m_SpawnColorPalette;
|
|
|
|
TilePalette m_TilePalette;
|
|
|
|
MobList m_Mobs;
|
|
|
|
TowerList m_Towers;
|
|
|
|
Game* m_Game;
|
|
|
|
WorldNotifier m_WorldNotifier;
|
|
MobNotifier m_MobNotifier;
|
|
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);
|
|
TowerPtr RemoveTower(TowerID id);
|
|
|
|
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<Color>& GetDecorationPalette() const { return m_DecorationPalette; }
|
|
const Color& GetBackgroundColor() const { return m_Background; }
|
|
|
|
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 Vec2f& worldPos, PlayerID player) const;
|
|
bool CanPlaceBigTower(const Vec2f& worldPos, PlayerID player) const;
|
|
|
|
TowerPtr GetTower(const Vec2f& position) const; // returns null if no tower is here
|
|
|
|
const std::unordered_map<ChunkCoord, ChunkPtr>& GetChunks() const { return m_Chunks; }
|
|
|
|
const Color& GetSpawnColor(TeamColor color) const { return m_SpawnColorPalette[static_cast<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 TeamList& GetTeams() const;
|
|
|
|
const TowerList& GetTowers() const { return m_Towers; }
|
|
TowerPtr GetTowerById(TowerID tower);
|
|
|
|
const Player* GetPlayerById(PlayerID id) const;
|
|
|
|
WorldNotifier& GetWorldNotifier() { return m_WorldNotifier; }
|
|
MobNotifier& GetMobNotifier() { return m_MobNotifier; }
|
|
|
|
// WorldListener
|
|
|
|
virtual void OnArcherTowerShot(MobPtr target, ArcherTower* shooter) override;
|
|
virtual void OnArrowShot(MobPtr target, bool fire, Tower* shooter) override;
|
|
virtual void OnExplosion(utils::shape::Circle explosion, float centerDamage, Tower* shooter) override;
|
|
|
|
// MobListener
|
|
|
|
virtual void OnMobDamage(Mob* target, float damage, Tower* source) override;
|
|
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) override;
|
|
|
|
private:
|
|
void TickMobs(std::uint64_t delta);
|
|
void CleanDeadMobs();
|
|
};
|
|
|
|
} // namespace game
|
|
} // namespace td
|