and again
This commit is contained in:
@@ -176,6 +176,11 @@ Mat4f Look(const Vec3f& eye, const Vec3f& center, const Vec3f& up);
|
|||||||
|
|
||||||
Mat4f Inverse(const Mat4f& mat);
|
Mat4f Inverse(const Mat4f& mat);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T Lerp(T v0, T v1, T t) {
|
||||||
|
return (T(1) - t) * v0 + t * v1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace maths
|
} // namespace maths
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <sp/protocol/ConcreteMessage.h>
|
||||||
|
#include <sp/common/GenericHandler.h>
|
||||||
|
#include <sp/protocol/MessageFactory.h>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
using Vec2fp = Vec2<FpFloat>;
|
using Vec2fp = Vec2<FpFloat>;
|
||||||
|
|
||||||
@@ -65,152 +69,33 @@ const MobStats* GetMobStats(MobType type, std::uint8_t level);
|
|||||||
const TowerImmunities& GetMobTowerImmunities(MobType type, std::uint8_t level);
|
const TowerImmunities& GetMobTowerImmunities(MobType type, std::uint8_t level);
|
||||||
const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level);
|
const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level);
|
||||||
|
|
||||||
class Mob {
|
class MobHandler;
|
||||||
protected:
|
|
||||||
float m_Health;
|
|
||||||
|
|
||||||
private:
|
struct MobData {};
|
||||||
Vec2fp m_Position;
|
|
||||||
|
class Mob : public sp::MessageBase<MobType, MobHandler> {
|
||||||
|
public:
|
||||||
MobID m_ID;
|
MobID m_ID;
|
||||||
PlayerID m_Sender;
|
|
||||||
MobLevel m_Level;
|
MobLevel m_Level;
|
||||||
|
PlayerID m_Sender;
|
||||||
|
float m_Health;
|
||||||
|
Vec2fp m_Position;
|
||||||
Direction m_Direction;
|
Direction m_Direction;
|
||||||
std::vector<EffectDuration> m_Effects;
|
std::vector<EffectDuration> m_Effects;
|
||||||
const Tower* m_LastDamage; // the last tower that damaged the mob
|
const Tower* m_LastDamage; // the last tower that damaged the mob
|
||||||
float m_HitCooldown;
|
float m_HitCooldown;
|
||||||
|
|
||||||
// utils::Timer m_EffectFireTimer;
|
|
||||||
// utils::Timer m_EffectPoisonTimer;
|
|
||||||
// utils::Timer m_EffectHealTimer;
|
|
||||||
|
|
||||||
TeamCastle* m_CastleTarget;
|
TeamCastle* m_CastleTarget;
|
||||||
// utils::CooldownTimer m_AttackTimer;
|
// utils::CooldownTimer m_AttackTimer;
|
||||||
|
|
||||||
public:
|
MobPtr m_Next;
|
||||||
Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level), m_HitCooldown(0), m_CastleTarget(nullptr) {}
|
|
||||||
|
|
||||||
virtual ~Mob() {}
|
Mob() {}
|
||||||
|
|
||||||
virtual MobType GetType() const = 0;
|
Mob& operator=(const Mob& a_Other) = default;
|
||||||
|
|
||||||
virtual bool OnDeath(World* world) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec2fp& GetPosition() {
|
|
||||||
return m_Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
MobID GetMobID() const {
|
|
||||||
return m_ID;
|
|
||||||
}
|
|
||||||
const TowerImmunities& GetTowerImmunities() const {
|
|
||||||
return GetMobTowerImmunities(GetType(), m_Level);
|
|
||||||
}
|
|
||||||
const EffectImmunities& GetEffectImmunities() const {
|
|
||||||
return GetMobEffectImmunities(GetType(), m_Level);
|
|
||||||
}
|
|
||||||
PlayerID GetSender() const {
|
|
||||||
return m_Sender;
|
|
||||||
}
|
|
||||||
MobLevel GetLevel() const {
|
|
||||||
return m_Level;
|
|
||||||
}
|
|
||||||
const MobStats* GetStats() const {
|
|
||||||
return GetMobStats(GetType(), m_Level);
|
|
||||||
}
|
|
||||||
void SetHealth(float newHealth) {
|
|
||||||
m_Health = newHealth;
|
|
||||||
}
|
|
||||||
float GetHealth() const {
|
|
||||||
return m_Health;
|
|
||||||
}
|
|
||||||
bool IsDead() const {
|
|
||||||
return m_Health <= 0;
|
|
||||||
}
|
|
||||||
bool IsAlive() const {
|
|
||||||
return m_Health > 0;
|
|
||||||
}
|
|
||||||
const Tower* GetLastDamageTower() {
|
|
||||||
return m_LastDamage;
|
|
||||||
}
|
|
||||||
bool HasReachedEnemyCastle() {
|
|
||||||
return m_CastleTarget != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Damage(float dmg, const Tower* damager) {
|
|
||||||
m_Health = std::max(0.0f, m_Health - dmg);
|
|
||||||
m_LastDamage = damager;
|
|
||||||
m_HitCooldown = 0.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Heal(float heal) {
|
|
||||||
m_Health = std::min(static_cast<float>(GetStats()->m_MaxLife), m_Health + heal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetMobReachedCastle(TeamCastle* castle) {
|
|
||||||
m_CastleTarget = castle;
|
|
||||||
} // used when mob is in front of the castle
|
|
||||||
|
|
||||||
bool IsImmuneTo(TowerType type);
|
|
||||||
|
|
||||||
bool IsImmuneTo(EffectType type);
|
|
||||||
void AddEffect(EffectType type, float durationSec, Tower* tower);
|
|
||||||
bool HasEffect(EffectType type);
|
|
||||||
|
|
||||||
bool HasTakenDamage() {
|
|
||||||
return m_HitCooldown > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// // returns a float between 0 and 1 excluded
|
|
||||||
// float GetTileX() {
|
|
||||||
// return GetCenterX() - static_cast<float>(static_cast<std::int32_t>(GetCenterX()));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // returns a float between 0 and 1 excluded
|
|
||||||
// float GetTileY() {
|
|
||||||
// return GetCenterY() - static_cast<float>(static_cast<std::int32_t>(GetCenterY()));
|
|
||||||
// }
|
|
||||||
|
|
||||||
Direction GetDirection() const {
|
|
||||||
return m_Direction;
|
|
||||||
}
|
|
||||||
void SetDirection(Direction dir) {
|
|
||||||
m_Direction = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void InitMob() {
|
|
||||||
m_Health = static_cast<float>(GetStats()->m_MaxLife);
|
|
||||||
// SetSize(GetStats()->m_Size.x, GetStats()->m_Size.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void UpdateEffects(std::uint64_t delta, World* world);
|
|
||||||
void AttackCastle(std::uint64_t delta, World* world);
|
|
||||||
void Move(std::uint64_t delta, World* world);
|
|
||||||
void Walk(std::uint64_t delta, World* world);
|
|
||||||
void MoveBack(const TeamCastle& castle, World* world);
|
|
||||||
void ChangeDirection(const WalkableTile& tile, World* world);
|
|
||||||
bool IsTouchingCastle(const TeamCastle& castle) const;
|
|
||||||
EffectDuration& GetEffect(EffectType type);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<Mob> MobPtr;
|
template <MobType ID>
|
||||||
|
using ConcreteMob = sp::ConcreteMessage<MobData, Mob, ID>;
|
||||||
template <MobType MT>
|
|
||||||
class ConcreteMob : public Mob {
|
|
||||||
public:
|
|
||||||
ConcreteMob(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) {
|
|
||||||
InitMob();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~ConcreteMob() {}
|
|
||||||
|
|
||||||
virtual constexpr MobType GetType() const override {
|
|
||||||
return MT;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using Zombie = ConcreteMob<MobType::Zombie>;
|
using Zombie = ConcreteMob<MobType::Zombie>;
|
||||||
using Spider = ConcreteMob<MobType::Spider>;
|
using Spider = ConcreteMob<MobType::Spider>;
|
||||||
@@ -223,16 +108,17 @@ using Witch = ConcreteMob<MobType::Witch>;
|
|||||||
using Slime = ConcreteMob<MobType::Slime>;
|
using Slime = ConcreteMob<MobType::Slime>;
|
||||||
using Giant = ConcreteMob<MobType::Giant>;
|
using Giant = ConcreteMob<MobType::Giant>;
|
||||||
|
|
||||||
namespace MobFactory {
|
using AllMobs = std::tuple<Zombie, Spider, Skeleton, PigMan, Creeper, Silverfish, Blaze, Witch, Slime, Giant>;
|
||||||
|
|
||||||
MobPtr CreateMob(MobID id, MobType type, std::uint8_t level, PlayerID sender);
|
class MobHandler : public sp::GenericHandler<AllMobs> {};
|
||||||
std::string GetMobName(MobType type);
|
|
||||||
|
|
||||||
} // namespace MobFactory
|
using MobFactory = sp::MessageFactory<Mob, AllMobs>;
|
||||||
|
|
||||||
class MobListener {
|
class MobListener {
|
||||||
public:
|
public:
|
||||||
virtual void OnMobSpawn(Mob* mob) {}
|
virtual void OnMobSpawn(Mob* mob) {
|
||||||
|
MobHandler h;
|
||||||
|
}
|
||||||
virtual void OnMobDie(Mob* mob) {}
|
virtual void OnMobDie(Mob* mob) {}
|
||||||
|
|
||||||
virtual void OnMobDamage(Mob* target, float damage, Tower* damager) {}
|
virtual void OnMobDamage(Mob* target, float damage, Tower* damager) {}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class World {
|
|||||||
TilePalette m_TilePalette;
|
TilePalette m_TilePalette;
|
||||||
|
|
||||||
sim::WorldSnapshot m_CurrentState;
|
sim::WorldSnapshot m_CurrentState;
|
||||||
|
sim::WorldSnapshot m_NextState;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sim::WorldTicker m_Ticker;
|
sim::WorldTicker m_Ticker;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <sp/protocol/ConcreteMessage.h>
|
#include <sp/protocol/ConcreteMessage.h>
|
||||||
#include <sp/protocol/MessageDispatcher.h>
|
#include <sp/protocol/MessageDispatcher.h>
|
||||||
#include <sp/protocol/MessageFactory.h>
|
#include <sp/protocol/MessageFactory.h>
|
||||||
#include <sp/protocol/MessageHandler.h>
|
#include <sp/common/GenericHandler.h>
|
||||||
#include <td/Types.h>
|
#include <td/Types.h>
|
||||||
#include <td/common/NonCopyable.h>
|
#include <td/common/NonCopyable.h>
|
||||||
#include <td/protocol/command/CommandData.h>
|
#include <td/protocol/command/CommandData.h>
|
||||||
@@ -33,7 +33,7 @@ class CommandHandler;
|
|||||||
using CommandBase = sp::MessageBase<CommandID, CommandHandler>;
|
using CommandBase = sp::MessageBase<CommandID, CommandHandler>;
|
||||||
|
|
||||||
template <typename TData, CommandID ID>
|
template <typename TData, CommandID ID>
|
||||||
using CommandMessage = sp::ConcreteMessage<TData, CommandID, ID, CommandHandler>;
|
using CommandMessage = sp::ConcreteMessage<TData, CommandBase, ID>;
|
||||||
|
|
||||||
|
|
||||||
namespace commands {
|
namespace commands {
|
||||||
@@ -51,7 +51,7 @@ using UseItemCommand = CommandMessage<cdata::UseItem, CommandID::UseItem>;
|
|||||||
using AllCommands = std::tuple<commands::EndCommand, commands::PlaceTowerCommand, commands::PlayerJoinCommand,
|
using AllCommands = std::tuple<commands::EndCommand, commands::PlaceTowerCommand, commands::PlayerJoinCommand,
|
||||||
commands::SpawnTroopCommand, commands::TeamChangeCommand, commands::UpgradeTowerCommand, commands::UseItemCommand>;
|
commands::SpawnTroopCommand, commands::TeamChangeCommand, commands::UpgradeTowerCommand, commands::UseItemCommand>;
|
||||||
|
|
||||||
class CommandHandler : public sp::MessageHandler<AllCommands> {};
|
class CommandHandler : public sp::GenericHandler<AllCommands> {};
|
||||||
|
|
||||||
using CommandDispatcher = sp::MessageDispatcher<CommandBase>;
|
using CommandDispatcher = sp::MessageDispatcher<CommandBase>;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <sp/protocol/MessageBase.h>
|
#include <sp/protocol/MessageBase.h>
|
||||||
#include <sp/protocol/MessageDispatcher.h>
|
#include <sp/protocol/MessageDispatcher.h>
|
||||||
#include <sp/protocol/MessageFactory.h>
|
#include <sp/protocol/MessageFactory.h>
|
||||||
#include <sp/protocol/MessageHandler.h>
|
#include <sp/common/GenericHandler.h>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace protocol {
|
namespace protocol {
|
||||||
@@ -37,7 +37,7 @@ using PacketBase = sp::MessageBase<PacketID, PacketHandler>;
|
|||||||
|
|
||||||
|
|
||||||
template <typename TData, PacketID ID>
|
template <typename TData, PacketID ID>
|
||||||
using PacketMessage = sp::ConcreteMessage<TData, PacketID, ID, PacketHandler>;
|
using PacketMessage = sp::ConcreteMessage<TData, PacketBase, ID>;
|
||||||
|
|
||||||
|
|
||||||
namespace packets {
|
namespace packets {
|
||||||
@@ -61,7 +61,7 @@ using AllPackets = std::tuple<packets::BeginGamePacket, packets::ChatMessagePack
|
|||||||
packets::KeepAlivePacket, packets::LockStepsPacket, packets::LoggingSuccessPacket, packets::PlayerJoinPacket,
|
packets::KeepAlivePacket, packets::LockStepsPacket, packets::LoggingSuccessPacket, packets::PlayerJoinPacket,
|
||||||
packets::PlayerLeavePacket, packets::PlayerLoginPacket, packets::WorldHeaderPacket, packets::WorldDataPacket>;
|
packets::PlayerLeavePacket, packets::PlayerLoginPacket, packets::WorldHeaderPacket, packets::WorldDataPacket>;
|
||||||
|
|
||||||
class PacketHandler : public sp::MessageHandler<AllPackets> {};
|
class PacketHandler : public sp::GenericHandler<AllPackets> {};
|
||||||
|
|
||||||
using PacketDispatcher = sp::MessageDispatcher<PacketBase>;
|
using PacketDispatcher = sp::MessageDispatcher<PacketBase>;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ namespace render {
|
|||||||
|
|
||||||
class BasicRenderer {
|
class BasicRenderer {
|
||||||
public:
|
public:
|
||||||
virtual void Render() = 0;
|
virtual void Render(float a_Lerp) = 0;
|
||||||
|
virtual ~BasicRenderer() {}
|
||||||
|
|
||||||
void Render(const GL::VertexArray& a_Vao);
|
void Render(const GL::VertexArray& a_Vao);
|
||||||
};
|
};
|
||||||
@@ -24,6 +25,11 @@ class Renderer : public BasicRenderer {
|
|||||||
public:
|
public:
|
||||||
Renderer(Camera& a_Camera);
|
Renderer(Camera& a_Camera);
|
||||||
virtual ~Renderer() {}
|
virtual ~Renderer() {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
float Lerp(const T& a_Mob, float a_LerpFactor, const std::function<float(const T&)>& a_MemberGetter) {
|
||||||
|
return static_cast<float>(maths::Lerp(a_MemberGetter(a_Mob), a_MemberGetter(*a_Mob.m_Next), a_LerpFactor));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderPipeline {
|
class RenderPipeline {
|
||||||
@@ -32,7 +38,7 @@ class RenderPipeline {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
RenderPipeline();
|
RenderPipeline();
|
||||||
~RenderPipeline() = default;
|
virtual ~RenderPipeline() {}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
void AddRenderer(Args&&... args) {
|
void AddRenderer(Args&&... args) {
|
||||||
@@ -43,9 +49,9 @@ class RenderPipeline {
|
|||||||
m_Renderers.clear();
|
m_Renderers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render() {
|
void Render(float a_Lerp) {
|
||||||
for (auto& renderer : m_Renderers) {
|
for (auto& renderer : m_Renderers) {
|
||||||
renderer->Render();
|
renderer->Render(a_Lerp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class EntityRenderer : public Renderer<shader::EntityShader> {
|
|||||||
EntityRenderer(Camera& a_Camera, const game::World& a_World);
|
EntityRenderer(Camera& a_Camera, const game::World& a_World);
|
||||||
virtual ~EntityRenderer();
|
virtual ~EntityRenderer();
|
||||||
|
|
||||||
virtual void Render() override;
|
virtual void Render(float a_Lerp) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace render
|
} // namespace render
|
||||||
|
|||||||
@@ -10,14 +10,13 @@ namespace render {
|
|||||||
|
|
||||||
class WorldRenderer : public Renderer<shader::WorldShader> {
|
class WorldRenderer : public Renderer<shader::WorldShader> {
|
||||||
private:
|
private:
|
||||||
const game::World& m_World;
|
|
||||||
std::unique_ptr<GL::VertexArray> m_WorldVao;
|
std::unique_ptr<GL::VertexArray> m_WorldVao;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WorldRenderer(Camera& a_Camera, const game::World& a_World);
|
WorldRenderer(Camera& a_Camera, const game::World& a_World);
|
||||||
virtual ~WorldRenderer();
|
virtual ~WorldRenderer();
|
||||||
|
|
||||||
virtual void Render() override;
|
virtual void Render(float a_Lerp) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace render
|
} // namespace render
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class CommandApply : public protocol::CommandHandler {
|
|||||||
public:
|
public:
|
||||||
CommandApply(const game::World& a_World, WorldSnapshot& a_Snapshot);
|
CommandApply(const game::World& a_World, WorldSnapshot& a_Snapshot);
|
||||||
|
|
||||||
virtual void Handle(const protocol::cdata::SpawnTroop& a_SpawnTroop) override;
|
virtual void Handle(const protocol::commands::SpawnTroopCommand& a_SpawnTroop) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sim
|
} // namespace sim
|
||||||
|
|||||||
@@ -17,9 +17,18 @@ class RealTimeSimulation {
|
|||||||
std::size_t m_CurrentStep;
|
std::size_t m_CurrentStep;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* \param a_StepTime in ms
|
||||||
|
*/
|
||||||
RealTimeSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime);
|
RealTimeSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime);
|
||||||
|
|
||||||
void Update();
|
/**
|
||||||
|
* \return the progress [0-1] between two steps
|
||||||
|
*/
|
||||||
|
float Update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Step();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sim
|
} // namespace sim
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ class WorldTicker {
|
|||||||
WorldTicker();
|
WorldTicker();
|
||||||
|
|
||||||
WorldSnapshot NextStep(
|
WorldSnapshot NextStep(
|
||||||
const game::World& a_World, const WorldSnapshot& a_PreviousState, const protocol::LockStep& a_LockStep, FpFloat a_Delta);
|
const game::World& a_World, WorldSnapshot& a_PreviousState, const protocol::LockStep& a_LockStep, FpFloat a_Delta);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ApplySteps(const game::World& a_World, WorldSnapshot& a_State, const protocol::LockStep& a_LockStep);
|
void ApplySteps(const game::World& a_World, WorldSnapshot& a_State, const protocol::LockStep& a_LockStep);
|
||||||
void Tick(const game::World& a_World, WorldSnapshot& a_State, FpFloat a_Delta);
|
void Tick(const game::World& a_World, WorldSnapshot& a_State, FpFloat a_Delta);
|
||||||
WorldSnapshot CreateNext(const WorldSnapshot& a_PreviousState);
|
WorldSnapshot CreateNext(WorldSnapshot& a_PreviousState);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void AddSystem() {
|
void AddSystem() {
|
||||||
|
|||||||
16
src/main.cpp
16
src/main.cpp
@@ -20,11 +20,11 @@ class WorldApply : public td::protocol::PacketHandler {
|
|||||||
public:
|
public:
|
||||||
WorldApply(td::game::World& a_World) : m_World(a_World) {}
|
WorldApply(td::game::World& a_World) : m_World(a_World) {}
|
||||||
|
|
||||||
void Handle(const td::protocol::pdata::WorldHeader& a_Header) override {
|
void Handle(const td::protocol::packets::WorldHeaderPacket& a_Header) override {
|
||||||
m_World.LoadMap(a_Header);
|
m_World.LoadMap(*a_Header);
|
||||||
}
|
}
|
||||||
void Handle(const td::protocol::pdata::WorldData& a_Data) override {
|
void Handle(const td::protocol::packets::WorldDataPacket& a_Data) override {
|
||||||
m_World.LoadMap(a_Data);
|
m_World.LoadMap(*a_Data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -93,15 +93,15 @@ int main(int argc, char** argv) {
|
|||||||
renderer.AddRenderer<td::render::WorldRenderer>(cam, w);
|
renderer.AddRenderer<td::render::WorldRenderer>(cam, w);
|
||||||
renderer.AddRenderer<td::render::EntityRenderer>(cam, w);
|
renderer.AddRenderer<td::render::EntityRenderer>(cam, w);
|
||||||
|
|
||||||
cam.SetCamPos({77, 25, 13});
|
cam.SetCamPos({77, 5, 13});
|
||||||
cam.UpdatePerspective(display.GetAspectRatio());
|
cam.UpdatePerspective(display.GetAspectRatio());
|
||||||
|
|
||||||
td::sim::RealTimeSimulation simulation(w, std::move(gh), 1000);
|
td::sim::RealTimeSimulation simulation(w, std::move(gh), 2000);
|
||||||
|
|
||||||
while (!display.IsCloseRequested()) {
|
while (!display.IsCloseRequested()) {
|
||||||
display.PollEvents();
|
display.PollEvents();
|
||||||
simulation.Update();
|
float lerp = simulation.Update();
|
||||||
renderer.Render();
|
renderer.Render(lerp);
|
||||||
display.Update();
|
display.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,7 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
World::World() : m_CurrentState{.m_Teams{Team{TeamColor::Red}, Team{TeamColor::Blue}}} {
|
World::World() : m_CurrentState{.m_Teams{Team{TeamColor::Red}, Team{TeamColor::Blue}}}, m_NextState{.m_Teams{Team{TeamColor::Red}, Team{TeamColor::Blue}}} {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const Color* World::GetTileColor(TilePtr tile) const {
|
const Color* World::GetTileColor(TilePtr tile) const {
|
||||||
switch (tile->GetType()) {
|
switch (tile->GetType()) {
|
||||||
@@ -58,7 +56,8 @@ bool World::LoadMap(const protocol::pdata::WorldData& a_WorldData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void World::Tick(const protocol::LockStep& a_LockStep, FpFloat a_Delta) {
|
void World::Tick(const protocol::LockStep& a_LockStep, FpFloat a_Delta) {
|
||||||
m_CurrentState = m_Ticker.NextStep(*this, m_CurrentState, a_LockStep, a_Delta);
|
m_CurrentState = m_NextState;
|
||||||
|
m_NextState = m_Ticker.NextStep(*this, m_NextState, a_LockStep, a_Delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace game
|
} // namespace game
|
||||||
|
|||||||
@@ -13,16 +13,19 @@ EntityRenderer::EntityRenderer(Camera& a_Camera, const game::World& a_World) : R
|
|||||||
|
|
||||||
EntityRenderer::~EntityRenderer() {}
|
EntityRenderer::~EntityRenderer() {}
|
||||||
|
|
||||||
void EntityRenderer::Render() {
|
|
||||||
|
|
||||||
|
void EntityRenderer::Render(float a_Lerp) {
|
||||||
m_Shader->Start();
|
m_Shader->Start();
|
||||||
for (const auto& mob : m_World.GetMobList()) {
|
for (const auto& mob : m_World.GetMobList()) {
|
||||||
const auto mobCoords = mob->GetPosition();
|
|
||||||
float x = static_cast<float>(mobCoords.x);
|
float x = Lerp<game::Mob>(*mob, a_Lerp, [](const game::Mob& a_Mob) { return static_cast<float>(a_Mob.m_Position.x); });
|
||||||
float z = static_cast<float>(mobCoords.y);
|
float z = Lerp<game::Mob>(*mob, a_Lerp, [](const game::Mob& a_Mob) { return static_cast<float>(a_Mob.m_Position.y); });
|
||||||
|
|
||||||
m_Shader->SetModelPos({x, 1, z});
|
m_Shader->SetModelPos({x, 1, z});
|
||||||
Renderer::Render(*m_EntityVao);
|
Renderer::Render(*m_EntityVao);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace render
|
} // namespace render
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
namespace render {
|
namespace render {
|
||||||
|
|
||||||
WorldRenderer::WorldRenderer(Camera& a_Camera, const game::World& a_World) : Renderer(a_Camera), m_World(a_World) {
|
WorldRenderer::WorldRenderer(Camera& a_Camera, const game::World& a_World) : Renderer(a_Camera) {
|
||||||
m_WorldVao = std::make_unique<GL::VertexArray>(std::move(WorldLoader::LoadWorldModel(&a_World)));
|
m_WorldVao = std::make_unique<GL::VertexArray>(WorldLoader::LoadWorldModel(&a_World));
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldRenderer::~WorldRenderer() {}
|
WorldRenderer::~WorldRenderer() {}
|
||||||
|
|
||||||
void WorldRenderer::Render() {
|
void WorldRenderer::Render(float a_Lerp) {
|
||||||
m_Shader->Start();
|
m_Shader->Start();
|
||||||
Renderer::Render(*m_WorldVao);
|
Renderer::Render(*m_WorldVao);
|
||||||
ImGui::ShowDemoWindow();
|
ImGui::ShowDemoWindow();
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ namespace sim {
|
|||||||
|
|
||||||
CommandApply::CommandApply(const game::World& a_World, WorldSnapshot& a_Snapshot) : m_World(a_World), m_Snapshot(a_Snapshot) {}
|
CommandApply::CommandApply(const game::World& a_World, WorldSnapshot& a_Snapshot) : m_World(a_World), m_Snapshot(a_Snapshot) {}
|
||||||
|
|
||||||
void CommandApply::Handle(const protocol::cdata::SpawnTroop& a_SpawnTroop) {
|
void CommandApply::Handle(const protocol::commands::SpawnTroopCommand& a_SpawnTroop) {
|
||||||
auto zombie = std::make_shared<game::Zombie>(0, *a_SpawnTroop.m_Level, a_SpawnTroop.m_Sender);
|
auto zombie = std::make_shared<game::Zombie>();
|
||||||
zombie->GetPosition() = a_SpawnTroop.m_Position;
|
zombie->m_Position = a_SpawnTroop->m_Position;
|
||||||
m_Snapshot.m_Mobs.push_back(zombie);
|
m_Snapshot.m_Mobs.push_back(zombie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,16 +16,24 @@ RealTimeSimulation::RealTimeSimulation(game::World& a_World, GameHistory&& a_His
|
|||||||
m_History(std::move(a_History)),
|
m_History(std::move(a_History)),
|
||||||
m_CurrentTime(0),
|
m_CurrentTime(0),
|
||||||
m_LastTime(GetTime()),
|
m_LastTime(GetTime()),
|
||||||
m_CurrentStep(0) {}
|
m_CurrentStep(0) {
|
||||||
|
Step();
|
||||||
|
}
|
||||||
|
|
||||||
void RealTimeSimulation::Update() {
|
float RealTimeSimulation::Update() {
|
||||||
|
// TODO: handle freezes (m_CurrentTime > 2 * m_StepTime)
|
||||||
m_CurrentTime += GetTime() - m_LastTime;
|
m_CurrentTime += GetTime() - m_LastTime;
|
||||||
m_LastTime = GetTime();
|
m_LastTime = GetTime();
|
||||||
if (m_CurrentTime > m_StepTime) {
|
if (m_CurrentTime > m_StepTime) {
|
||||||
m_World.Tick(m_History[m_CurrentStep], FpFloat(m_StepTime) / FpFloat(1000));
|
Step();
|
||||||
m_CurrentStep++;
|
|
||||||
m_CurrentTime -= m_StepTime;
|
m_CurrentTime -= m_StepTime;
|
||||||
}
|
}
|
||||||
|
return (float) m_CurrentTime / (float) m_StepTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RealTimeSimulation::Step() {
|
||||||
|
m_World.Tick(m_History[m_CurrentStep], FpFloat(m_StepTime) / FpFloat(1000));
|
||||||
|
m_CurrentStep++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sim
|
} // namespace sim
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ WorldTicker::WorldTicker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WorldSnapshot WorldTicker::NextStep(
|
WorldSnapshot WorldTicker::NextStep(
|
||||||
const game::World& a_World, const WorldSnapshot& a_PreviousState, const protocol::LockStep& a_LockStep, FpFloat a_Delta) {
|
const game::World& a_World, WorldSnapshot& a_PreviousState, const protocol::LockStep& a_LockStep, FpFloat a_Delta) {
|
||||||
WorldSnapshot next = CreateNext(a_PreviousState);
|
WorldSnapshot next = CreateNext(a_PreviousState);
|
||||||
ApplySteps(a_World, next, a_LockStep);
|
ApplySteps(a_World, next, a_LockStep); // maybe swap with tick ?
|
||||||
Tick(a_World, next, a_Delta);
|
Tick(a_World, next, a_Delta);
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@@ -33,8 +33,21 @@ void WorldTicker::Tick(const game::World& a_World, WorldSnapshot& a_State, FpFlo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldSnapshot WorldTicker::CreateNext(const WorldSnapshot& a_PreviousState) {
|
WorldSnapshot WorldTicker::CreateNext(WorldSnapshot& a_PreviousState) {
|
||||||
return a_PreviousState;
|
static game::MobFactory mobFactory;
|
||||||
|
|
||||||
|
WorldSnapshot next {
|
||||||
|
.m_Towers = a_PreviousState.m_Towers,
|
||||||
|
.m_Teams = a_PreviousState.m_Teams
|
||||||
|
};
|
||||||
|
next.m_Mobs.reserve(a_PreviousState.m_Mobs.size());
|
||||||
|
for (auto& mob : a_PreviousState.m_Mobs) {
|
||||||
|
game::MobPtr newMob = std::shared_ptr<game::Mob>(mobFactory.CreateMessage(mob->GetId()).release());
|
||||||
|
*newMob = *mob;
|
||||||
|
mob->m_Next = newMob;
|
||||||
|
next.m_Mobs.push_back(newMob);
|
||||||
|
}
|
||||||
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sim
|
} // namespace sim
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace sim {
|
|||||||
|
|
||||||
void EntityMove::Tick(const game::World& a_World, WorldSnapshot& a_State, FpFloat a_Delta) {
|
void EntityMove::Tick(const game::World& a_World, WorldSnapshot& a_State, FpFloat a_Delta) {
|
||||||
for (auto& mob : a_State.m_Mobs) {
|
for (auto& mob : a_State.m_Mobs) {
|
||||||
mob->GetPosition().x += a_Delta;
|
mob->m_Position.x += a_Delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user