Merge branch 'experimental' into dev
This commit is contained in:
46
include/td/game/Game.h
Normal file
46
include/td/game/Game.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/game/World.h>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
enum class GameState : std::uint8_t {
|
||||
Lobby,
|
||||
Game,
|
||||
EndGame,
|
||||
Disconnected,
|
||||
Closed
|
||||
};
|
||||
|
||||
typedef std::map<std::uint8_t, Player> PlayerList;
|
||||
|
||||
|
||||
class Game {
|
||||
protected:
|
||||
World* m_World;
|
||||
|
||||
GameState m_GameState = GameState::Lobby;
|
||||
PlayerList m_Players;
|
||||
public:
|
||||
Game(World* world);
|
||||
virtual ~Game();
|
||||
|
||||
virtual void Tick(std::uint64_t delta);
|
||||
|
||||
GameState GetGameState() const { return m_GameState; }
|
||||
void SetGameState(GameState gameState) { m_GameState = gameState; };
|
||||
|
||||
const World* GetWorld() const { return m_World; }
|
||||
World* GetWorld() { return m_World; }
|
||||
|
||||
const PlayerList& GetPlayers() const { return m_Players; }
|
||||
PlayerList& GetPlayers() { return m_Players; }
|
||||
|
||||
const Player* GetPlayerById(PlayerID id) const;
|
||||
Player* GetPlayerById(PlayerID id);
|
||||
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
@@ -1,31 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <td/protocol/command/Commands.h>
|
||||
#include <td/protocol/packet/Packets.h>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
class GameHistory {
|
||||
private:
|
||||
using HistorySizeType = StepsType;
|
||||
|
||||
std::vector<std::optional<protocol::LockStep>> m_History;
|
||||
|
||||
public:
|
||||
GameHistory();
|
||||
|
||||
void SetLockStep(HistorySizeType a_Index, protocol::LockStep&& a_LockStep);
|
||||
|
||||
const protocol::LockStep& GetLockStep(HistorySizeType a_Index) const;
|
||||
|
||||
bool HasLockStep(HistorySizeType a_Index) const;
|
||||
|
||||
void FromPacket(td::protocol::pdata::LockSteps&& a_Steps);
|
||||
|
||||
td::protocol::packets::LockSteps ToPacket(HistorySizeType a_StartIndex);
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
132
include/td/game/Mobs.h
Normal file
132
include/td/game/Mobs.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/game/Towers.h>
|
||||
|
||||
#include <td/Maths.h>
|
||||
#include <td/Types.h>
|
||||
#include <td/game/Team.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <sp/protocol/ConcreteMessage.h>
|
||||
#include <sp/common/GenericHandler.h>
|
||||
#include <sp/protocol/MessageFactory.h>
|
||||
|
||||
namespace td {
|
||||
using Vec2fp = Vec2<FpFloat>;
|
||||
|
||||
namespace game {
|
||||
|
||||
enum class EffectType : std::uint8_t {
|
||||
Slowness = 0,
|
||||
Stun,
|
||||
Fire,
|
||||
Poison,
|
||||
Heal,
|
||||
};
|
||||
|
||||
enum class MobType : std::uint8_t {
|
||||
Zombie = 0,
|
||||
Spider,
|
||||
Skeleton,
|
||||
Pigman,
|
||||
Creeper,
|
||||
Silverfish,
|
||||
Blaze,
|
||||
Witch,
|
||||
Slime,
|
||||
Giant,
|
||||
|
||||
MOB_COUNT
|
||||
};
|
||||
|
||||
typedef std::uint32_t MobID;
|
||||
typedef std::uint8_t MobLevel;
|
||||
typedef std::vector<TowerType> TowerImmunities;
|
||||
typedef std::vector<EffectType> EffectImmunities;
|
||||
|
||||
struct MobStats {
|
||||
float m_Damage;
|
||||
float m_Speed;
|
||||
Vec2f m_Size;
|
||||
std::uint16_t m_MoneyCost;
|
||||
std::uint16_t m_ExpCost;
|
||||
std::uint16_t m_MaxLife;
|
||||
std::uint16_t m_ExpReward;
|
||||
};
|
||||
|
||||
struct EffectDuration {
|
||||
EffectType type;
|
||||
float duration; // in seconds
|
||||
Tower* tower; // the tower that gived the effect
|
||||
};
|
||||
|
||||
const MobStats* GetMobStats(MobType type, std::uint8_t level);
|
||||
const TowerImmunities& GetMobTowerImmunities(MobType type, std::uint8_t level);
|
||||
const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level);
|
||||
|
||||
class MobHandler;
|
||||
|
||||
struct MobData {};
|
||||
|
||||
class Mob : public sp::MessageBase<MobType, MobHandler> {
|
||||
public:
|
||||
MobID m_ID;
|
||||
MobLevel m_Level;
|
||||
PlayerID m_Sender;
|
||||
float m_Health;
|
||||
Vec2fp m_Position;
|
||||
Direction m_Direction;
|
||||
std::vector<EffectDuration> m_Effects;
|
||||
const Tower* m_LastDamage; // the last tower that damaged the mob
|
||||
float m_HitCooldown;
|
||||
TeamCastle* m_CastleTarget;
|
||||
// utils::CooldownTimer m_AttackTimer;
|
||||
|
||||
MobPtr m_Next;
|
||||
|
||||
Mob() {}
|
||||
|
||||
Mob& operator=(const Mob& a_Other) = default;
|
||||
};
|
||||
|
||||
template <MobType ID>
|
||||
using ConcreteMob = sp::ConcreteMessage<MobData, Mob, ID>;
|
||||
|
||||
using Zombie = ConcreteMob<MobType::Zombie>;
|
||||
using Spider = ConcreteMob<MobType::Spider>;
|
||||
using Skeleton = ConcreteMob<MobType::Skeleton>;
|
||||
using PigMan = ConcreteMob<MobType::Pigman>;
|
||||
using Creeper = ConcreteMob<MobType::Creeper>;
|
||||
using Silverfish = ConcreteMob<MobType::Silverfish>;
|
||||
using Blaze = ConcreteMob<MobType::Blaze>;
|
||||
using Witch = ConcreteMob<MobType::Witch>;
|
||||
using Slime = ConcreteMob<MobType::Slime>;
|
||||
using Giant = ConcreteMob<MobType::Giant>;
|
||||
|
||||
using AllMobs = std::tuple<Zombie, Spider, Skeleton, PigMan, Creeper, Silverfish, Blaze, Witch, Slime, Giant>;
|
||||
|
||||
class MobHandler : public sp::GenericHandler<AllMobs> {};
|
||||
|
||||
using MobFactory = sp::MessageFactory<Mob, AllMobs>;
|
||||
|
||||
class MobListener {
|
||||
public:
|
||||
virtual void OnMobSpawn(Mob* mob) {
|
||||
MobHandler h;
|
||||
}
|
||||
virtual void OnMobDie(Mob* mob) {}
|
||||
|
||||
virtual void OnMobDamage(Mob* target, float damage, Tower* damager) {}
|
||||
|
||||
virtual void OnMobTouchCastle(Mob* damager, TeamCastle* enemyCastle) {}
|
||||
virtual void OnMobCastleDamage(Mob* damager, TeamCastle* enemyCastle, float damage) {}
|
||||
};
|
||||
|
||||
using MobList = std::vector<MobPtr>;
|
||||
|
||||
// typedef utils::ObjectNotifier<MobListener> MobNotifier;
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
102
include/td/game/Team.h
Normal file
102
include/td/game/Team.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/Types.h>
|
||||
|
||||
#include <td/misc/Shapes.h>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
class Player;
|
||||
|
||||
class Spawn : public utils::shape::Rectangle {
|
||||
private:
|
||||
Direction m_Direction;
|
||||
public:
|
||||
Spawn() : m_Direction(Direction::PositiveX) {
|
||||
SetWidth(5);
|
||||
SetHeight(5);
|
||||
}
|
||||
|
||||
Direction GetDirection() const { return m_Direction; }
|
||||
|
||||
void SetDirection(Direction direction) { m_Direction = direction; }
|
||||
};
|
||||
|
||||
class Team;
|
||||
|
||||
class TeamCastle : public utils::shape::Rectangle {
|
||||
private:
|
||||
float m_Life;
|
||||
public:
|
||||
static constexpr int CastleMaxLife = 1000;
|
||||
|
||||
TeamCastle() : m_Life(CastleMaxLife) {
|
||||
SetWidth(5);
|
||||
SetHeight(5);
|
||||
}
|
||||
|
||||
float GetLife() const { return m_Life; }
|
||||
|
||||
void SetLife(float life) { m_Life = life; }
|
||||
void Damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); }
|
||||
|
||||
void SetShape(utils::shape::Rectangle rect) {
|
||||
SetCenter(rect.GetCenter());
|
||||
SetSize(rect.GetSize());
|
||||
}
|
||||
};
|
||||
|
||||
class Team {
|
||||
private:
|
||||
std::vector<Player*> m_Players;
|
||||
TeamColor m_Color;
|
||||
Spawn m_Spawn;
|
||||
TeamCastle m_TeamCastle;
|
||||
public:
|
||||
Team(TeamColor color) : m_Color(color) {}
|
||||
|
||||
void AddPlayer(Player* newPlayer);
|
||||
void RemovePlayer(const Player* player);
|
||||
|
||||
TeamColor GetColor() const;
|
||||
|
||||
const Spawn& GetSpawn() const { return m_Spawn; }
|
||||
Spawn& GetSpawn() { return m_Spawn; }
|
||||
|
||||
const TeamCastle& GetCastle() const { return m_TeamCastle; }
|
||||
TeamCastle& GetCastle() { return m_TeamCastle; }
|
||||
|
||||
std::uint8_t GetPlayerCount() const;
|
||||
};
|
||||
|
||||
struct TeamList {
|
||||
std::array<Team, 2> m_Teams;
|
||||
|
||||
TeamList() : m_Teams{Team{TeamColor::Red}, Team{TeamColor::Blue}}{
|
||||
|
||||
}
|
||||
|
||||
Team& operator[](std::size_t a_Index) {
|
||||
return m_Teams[a_Index];
|
||||
}
|
||||
|
||||
Team& operator[](TeamColor a_Index) {
|
||||
return m_Teams[static_cast<std::size_t>(a_Index)];
|
||||
}
|
||||
|
||||
const Team& operator[](std::size_t a_Index) const {
|
||||
return m_Teams[a_Index];
|
||||
}
|
||||
|
||||
const Team& operator[](TeamColor a_Index) const {
|
||||
return m_Teams[static_cast<std::size_t>(a_Index)];
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
147
include/td/game/Towers.h
Normal file
147
include/td/game/Towers.h
Normal file
@@ -0,0 +1,147 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <td/misc/Shapes.h>
|
||||
|
||||
#include <td/Types.h>
|
||||
|
||||
#include <sp/common/GenericHandler.h>
|
||||
#include <sp/protocol/ConcreteMessage.h>
|
||||
#include <sp/protocol/MessageFactory.h>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
class World;
|
||||
class Mob;
|
||||
|
||||
typedef std::shared_ptr<Mob> MobPtr;
|
||||
|
||||
enum class TowerSize : std::uint8_t {
|
||||
Little = 3, // 3x3
|
||||
Big = 5, // 5x5
|
||||
};
|
||||
|
||||
enum class TowerPath : std::uint8_t {
|
||||
Top = 0,
|
||||
Base, // Base Path
|
||||
Bottom
|
||||
};
|
||||
|
||||
class TowerStats {
|
||||
private:
|
||||
float m_Rate;
|
||||
float m_Damage;
|
||||
std::uint8_t m_Range;
|
||||
|
||||
public:
|
||||
TowerStats(float rate, float damage, std::uint8_t range) : m_Rate(rate), m_Damage(damage), m_Range(range) {}
|
||||
|
||||
float GetDamageRate() const {
|
||||
return m_Rate;
|
||||
}
|
||||
float GetDamage() const {
|
||||
return m_Damage;
|
||||
}
|
||||
std::uint8_t GetRange() const {
|
||||
return m_Range;
|
||||
}
|
||||
};
|
||||
|
||||
class TowerLevel {
|
||||
private:
|
||||
// 1, 2, 3, 4
|
||||
std::uint8_t m_Level : 3;
|
||||
// 0 : base path 1 : top path (if there is bottom path) 2 : bottom path (if there is top path)
|
||||
TowerPath m_Path : 2;
|
||||
|
||||
public:
|
||||
TowerLevel() : m_Level(1), m_Path(TowerPath::Base) {}
|
||||
TowerLevel(std::uint8_t level, TowerPath path) : m_Level(level), m_Path(path) {}
|
||||
|
||||
std::uint8_t GetLevel() const {
|
||||
return m_Level;
|
||||
}
|
||||
TowerPath GetPath() const {
|
||||
return m_Path;
|
||||
}
|
||||
|
||||
void SetLevel(std::uint8_t level) {
|
||||
m_Level = level;
|
||||
}
|
||||
void SetPath(TowerPath path) {
|
||||
m_Path = path;
|
||||
}
|
||||
|
||||
// operator to sort maps
|
||||
friend bool operator<(const TowerLevel& level, const TowerLevel& other) {
|
||||
return level.GetLevel() + static_cast<std::uint8_t>(level.GetPath()) * 4 <
|
||||
other.GetLevel() + static_cast<std::uint8_t>(other.GetPath()) * 4;
|
||||
}
|
||||
};
|
||||
|
||||
using TowerID = std::uint16_t;
|
||||
|
||||
class TowerHandler;
|
||||
|
||||
class Tower : public utils::shape::Circle, public sp::MessageBase<TowerType, TowerHandler> {
|
||||
public:
|
||||
TowerID m_ID;
|
||||
TowerLevel m_Level{};
|
||||
PlayerID m_Builder;
|
||||
|
||||
public:
|
||||
Tower() : m_ID(0), m_Level({}), m_Builder(0) {}
|
||||
|
||||
virtual TowerType GetType() const = 0;
|
||||
virtual TowerSize GetSize() const = 0;
|
||||
virtual void Tick(std::uint64_t delta, World* world) = 0;
|
||||
};
|
||||
|
||||
struct TowerData {};
|
||||
|
||||
template <TowerType Type, TowerSize Size>
|
||||
class ConcreteTower : public sp::ConcreteMessage<TowerData, Tower, Type, false> {
|
||||
public:
|
||||
using HandlerType = typename sp::ConcreteMessage<TowerData, Tower, Type, false>::HandlerType;
|
||||
|
||||
virtual TowerSize GetSize() const override {
|
||||
return Size;
|
||||
}
|
||||
|
||||
virtual TowerType GetType() const override {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void Tick(std::uint64_t delta, World* world) override {}
|
||||
|
||||
virtual void Dispatch(HandlerType& handler) const override {
|
||||
handler.Handle(*this);
|
||||
}
|
||||
};
|
||||
|
||||
using TowerPtr = std::shared_ptr<Tower>;
|
||||
|
||||
using ArcherTower = ConcreteTower<TowerType::Archer, TowerSize::Little>;
|
||||
using ArtilleryTower = ConcreteTower<TowerType::Artillery, TowerSize::Little>;
|
||||
using IceTower = ConcreteTower<TowerType::Ice, TowerSize::Little>;
|
||||
using LeachTower = ConcreteTower<TowerType::Leach, TowerSize::Big>;
|
||||
using MageTower = ConcreteTower<TowerType::Mage, TowerSize::Little>;
|
||||
using NecromancerTower = ConcreteTower<TowerType::Necromancer, TowerSize::Big>;
|
||||
using PoisonTower = ConcreteTower<TowerType::Poison, TowerSize::Little>;
|
||||
using QuakeTower = ConcreteTower<TowerType::Quake, TowerSize::Little>;
|
||||
using SorcererTower = ConcreteTower<TowerType::Sorcerer, TowerSize::Little>;
|
||||
using TurretTower = ConcreteTower<TowerType::Turret, TowerSize::Big>;
|
||||
using ZeusTower = ConcreteTower<TowerType::Zeus, TowerSize::Little>;
|
||||
|
||||
using AllTowers = std::tuple<ArcherTower, ArtilleryTower, IceTower, LeachTower, MageTower, NecromancerTower, PoisonTower, QuakeTower,
|
||||
SorcererTower, TurretTower, ZeusTower>;
|
||||
|
||||
using TowerFactory = sp::MessageFactory<Tower, AllTowers>;
|
||||
|
||||
class TowerHandler : public sp::GenericHandler<AllTowers> {};
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
@@ -1,27 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/game/GameHistory.h>
|
||||
#include <td/game/WorldState.h>
|
||||
#include <vector>
|
||||
#include <td/simulation/WorldTicker.h>
|
||||
#include <td/game/WorldTypes.h>
|
||||
#include <td/protocol/packet/Packets.h>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
class World {
|
||||
private:
|
||||
std::vector<WorldState> m_WorldStates;
|
||||
GameHistory m_GameHistory;
|
||||
protected:
|
||||
TowerTileColorPalette m_TowerPlacePalette;
|
||||
Color m_WalkablePalette;
|
||||
std::vector<Color> m_DecorationPalette;
|
||||
Color m_Background;
|
||||
|
||||
float m_OffsetTime;
|
||||
ChunkList m_Chunks;
|
||||
|
||||
SpawnColorPalette m_SpawnColorPalette;
|
||||
|
||||
TilePalette m_TilePalette;
|
||||
|
||||
std::shared_ptr<sim::WorldSnapshot> m_CurrentState;
|
||||
std::shared_ptr<sim::WorldSnapshot> m_NextState;
|
||||
|
||||
private:
|
||||
sim::WorldTicker m_Ticker;
|
||||
|
||||
public:
|
||||
World();
|
||||
|
||||
void Tick(float a_Delta);
|
||||
bool LoadMap(const protocol::pdata::WorldHeader& worldHeader);
|
||||
bool LoadMap(const protocol::pdata::WorldData& worldData);
|
||||
|
||||
bool LoadMapFromFile(const std::string& fileName);
|
||||
bool SaveMap(const std::string& fileName) const;
|
||||
|
||||
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 TilePtr(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 ChunkList& 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_CurrentState->m_Mobs;
|
||||
}
|
||||
MobList& GetMobList() {
|
||||
return m_CurrentState->m_Mobs;
|
||||
}
|
||||
|
||||
const Color* GetTileColor(const TilePtr& tile) const;
|
||||
|
||||
Team& GetRedTeam() {
|
||||
return m_CurrentState->m_Teams[TeamColor::Red];
|
||||
}
|
||||
const Team& GetRedTeam() const {
|
||||
return m_CurrentState->m_Teams[TeamColor::Red];
|
||||
}
|
||||
|
||||
Team& GetBlueTeam() {
|
||||
return m_CurrentState->m_Teams[TeamColor::Blue];
|
||||
}
|
||||
const Team& GetBlueTeam() const {
|
||||
return m_CurrentState->m_Teams[TeamColor::Red];
|
||||
}
|
||||
|
||||
Team& GetTeam(TeamColor team) {
|
||||
return m_CurrentState->m_Teams[team];
|
||||
}
|
||||
const Team& GetTeam(TeamColor team) const {
|
||||
return m_CurrentState->m_Teams[team];
|
||||
}
|
||||
|
||||
const TeamList& GetTeams() const {
|
||||
return m_CurrentState->m_Teams;
|
||||
}
|
||||
|
||||
const TowerList& GetTowers() const {
|
||||
return m_CurrentState->m_Towers;
|
||||
}
|
||||
|
||||
TowerPtr GetTowerById(TowerID tower);
|
||||
|
||||
const Player* GetPlayerById(PlayerID id) const;
|
||||
|
||||
const std::shared_ptr<sim::WorldSnapshot>& Tick(const protocol::LockStep& a_LockStep, FpFloat a_Delta);
|
||||
|
||||
void ResetSnapshots(std::shared_ptr<sim::WorldSnapshot>& a_Current, std::shared_ptr<sim::WorldSnapshot>& a_Next);
|
||||
|
||||
private:
|
||||
std::uint16_t GetCursorPos();
|
||||
void TickMobs(std::uint64_t delta);
|
||||
void CleanDeadMobs();
|
||||
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
} // namespace td
|
||||
@@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/protocol/command/Commands.h>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
class WorldState {
|
||||
private:
|
||||
// list of players, mobs, towers, castles
|
||||
public:
|
||||
WorldState() {}
|
||||
|
||||
WorldState GetNextState(const protocol::LockStep& a_Step);
|
||||
|
||||
private:
|
||||
void Tick(float a_Delta);
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
117
include/td/game/WorldTypes.h
Normal file
117
include/td/game/WorldTypes.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/Maths.h>
|
||||
#include <td/game/Team.h>
|
||||
#include <td/game/Towers.h>
|
||||
|
||||
#include <sp/io/SerializableMessage.h>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
using ChunkCoord = Vec2<std::int16_t>;
|
||||
|
||||
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};
|
||||
|
||||
class TileHandler;
|
||||
|
||||
using Tile = sp::MessageBase<TileType, TileHandler>;
|
||||
|
||||
template <TileType ID, typename TileData>
|
||||
using ConcreteTile = sp::ConcreteMessage<TileData, Tile, ID>;
|
||||
|
||||
namespace data {
|
||||
struct EmptyData {};
|
||||
|
||||
struct TowerTileData {
|
||||
std::uint8_t m_ColorPaletteRef;
|
||||
TeamColor m_TeamOwner;
|
||||
};
|
||||
|
||||
struct WalkableTileData {
|
||||
Direction m_Direction;
|
||||
};
|
||||
|
||||
struct DecorationTileData {
|
||||
std::uint16_t m_ColorPaletteRef;
|
||||
};
|
||||
} // namespace data
|
||||
|
||||
using EmptyTile = ConcreteTile<TileType::None, data::EmptyData>;
|
||||
using TowerTile = ConcreteTile<TileType::Tower, data::TowerTileData>;
|
||||
using WalkableTile = ConcreteTile<TileType::Walk, data::WalkableTileData>;
|
||||
using DecorationTile = ConcreteTile<TileType::Decoration, data::DecorationTileData>;
|
||||
|
||||
using AllTiles = std::tuple<EmptyTile, TowerTile, WalkableTile, DecorationTile>;
|
||||
|
||||
using TileFactory = sp::MessageFactory<Tile, AllTiles>;
|
||||
|
||||
class TileHandler : public sp::GenericHandler<AllTiles> {};
|
||||
|
||||
using TilePtr = sp::SerializableMessage<TileFactory>;
|
||||
|
||||
// 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 };
|
||||
using ChunkData = std::array<std::uint16_t, ChunkSize>;
|
||||
using ChunkPackedData = std::vector<uint64_t>;
|
||||
|
||||
// stores index of tile palette
|
||||
ChunkPalette m_Palette;
|
||||
ChunkPackedData m_Data;
|
||||
|
||||
TileIndex GetTileIndex(std::uint16_t tileNumber) const;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Chunk> ChunkPtr;
|
||||
|
||||
typedef std::array<Color, 2> TowerTileColorPalette;
|
||||
|
||||
typedef std::vector<TilePtr> TilePalette;
|
||||
|
||||
typedef std::array<Color, 2> SpawnColorPalette;
|
||||
|
||||
typedef std::vector<TowerPtr> TowerList;
|
||||
|
||||
using ChunkList = std::unordered_map<ChunkCoord, ChunkPtr>;
|
||||
|
||||
} // namespace game
|
||||
|
||||
} // namespace td
|
||||
|
||||
|
||||
|
||||
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 std
|
||||
Reference in New Issue
Block a user