diff --git a/include/td/game/Mobs.h b/include/td/game/Mobs.h index 3a9fe37..3b299a2 100644 --- a/include/td/game/Mobs.h +++ b/include/td/game/Mobs.h @@ -6,8 +6,8 @@ #include #include -#include #include +#include namespace td { namespace game { @@ -42,8 +42,7 @@ typedef std::uint8_t MobLevel; typedef std::vector TowerImmunities; typedef std::vector EffectImmunities; -class MobStats { -private: +struct MobStats { float m_Damage; float m_Speed; Vec2f m_Size; @@ -51,27 +50,12 @@ private: std::uint16_t m_ExpCost; std::uint16_t m_MaxLife; std::uint16_t m_ExpReward; -public: - MobStats(float damage, float speed, Vec2f size, std::uint16_t moneyCost, - std::uint16_t expCost, std::uint16_t expReward, - std::uint16_t maxLife) : m_Damage(damage), m_Speed(speed), - m_Size(size), m_MoneyCost(moneyCost), m_ExpCost(expCost), - m_MaxLife(maxLife), m_ExpReward(expReward) { - } - - float GetDamage() const { return m_Damage; } - float GetMovementSpeed() const { return m_Speed; } - const Vec2f& GetSize() const { return m_Size; } - std::uint16_t GetMoneyCost() const { return m_MoneyCost; } - std::uint16_t GetExpCost() const { return m_ExpCost; } - std::uint16_t GetExpReward() const { return m_ExpReward; } - std::uint16_t GetMaxLife() const { return m_MaxLife; } }; struct EffectDuration { EffectType type; - float duration; // in seconds - Tower* tower; // the tower that gived the effect + float duration; // in seconds + Tower* tower; // the tower that gived the effect }; const MobStats* GetMobStats(MobType type, std::uint8_t level); @@ -79,15 +63,16 @@ const TowerImmunities& GetMobTowerImmunities(MobType type, std::uint8_t level); const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level); class Mob : public utils::shape::Rectangle { -protected: + protected: float m_Health; -private: + + private: MobID m_ID; PlayerID m_Sender; MobLevel m_Level; Direction m_Direction; std::vector 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; // utils::Timer m_EffectFireTimer; @@ -97,30 +82,55 @@ private: TeamCastle* m_CastleTarget; // utils::CooldownTimer m_AttackTimer; -public: - Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level), - m_HitCooldown(0), m_CastleTarget(nullptr) { + public: + Mob(MobID id, MobLevel level, PlayerID sender) : m_Sender(sender), m_Level(level), m_HitCooldown(0), m_CastleTarget(nullptr) {} - } + virtual ~Mob() {} virtual MobType GetType() const = 0; - virtual void Tick(std::uint64_t delta, World* world); + virtual void Tick(std::uint64_t delta, World* world) {} - virtual bool OnDeath(World* world) { return true; } + virtual bool OnDeath(World* world) { + return true; + } - 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; } + 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); @@ -129,10 +139,12 @@ public: } void Heal(float heal) { - m_Health = std::min(static_cast(GetStats()->GetMaxLife()), m_Health + heal); + m_Health = std::min(static_cast(GetStats()->m_MaxLife), m_Health + heal); } - void SetMobReachedCastle(TeamCastle* castle) { m_CastleTarget = castle; } // used when mob is in front of the castle + void SetMobReachedCastle(TeamCastle* castle) { + m_CastleTarget = castle; + } // used when mob is in front of the castle bool IsImmuneTo(TowerType type); @@ -140,19 +152,34 @@ public: void AddEffect(EffectType type, float durationSec, Tower* tower); bool HasEffect(EffectType type); - bool HasTakenDamage() { return m_HitCooldown > 0; } - - float GetTileX() { return GetCenterX() - static_cast(static_cast(GetCenterX())); } // returns a float between 0 and 1 excluded - float GetTileY() { return GetCenterY() - static_cast(static_cast(GetCenterY())); } // returns a float between 0 and 1 excluded - - Direction GetDirection() const { return m_Direction; } - void SetDirection(Direction dir) { m_Direction = dir; } -protected: - void InitMob() { - m_Health = static_cast(GetStats()->GetMaxLife()); - SetSize(GetStats()->GetSize().x, GetStats()->GetSize().y); + bool HasTakenDamage() { + return m_HitCooldown > 0; } -private: + + // returns a float between 0 and 1 excluded + float GetTileX() { + return GetCenterX() - static_cast(static_cast(GetCenterX())); + } + + // returns a float between 0 and 1 excluded + float GetTileY() { + return GetCenterY() - static_cast(static_cast(GetCenterY())); + } + + Direction GetDirection() const { + return m_Direction; + } + void SetDirection(Direction dir) { + m_Direction = dir; + } + + protected: + void InitMob() { + m_Health = static_cast(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); @@ -165,85 +192,42 @@ private: typedef std::shared_ptr MobPtr; -class Zombie : public Mob { -public: - Zombie(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } +template +class ConcreteMob : public Mob { + public: + ConcreteMob(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { + InitMob(); + } - virtual MobType GetType() const { return MobType::Zombie; } + virtual ~ConcreteMob() {} + + virtual void Tick(std::uint64_t delta, World* world) {} + + virtual constexpr MobType GetType() const { + return MT; + } }; -class Spider : public Mob { -public: - Spider(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Spider; } -}; - -class Skeleton : public Mob { -public: - Skeleton(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Skeleton; } -}; - -class PigMan : public Mob { -public: - PigMan(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Pigman; } -}; - -class Creeper : public Mob { -public: - Creeper(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Creeper; } -}; - -class Silverfish : public Mob { -public: - Silverfish(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Silverfish; } -}; - -class Blaze : public Mob { -public: - Blaze(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Blaze; } -}; - -class Witch : public Mob { -public: - Witch(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Witch; } -}; - -class Slime : public Mob { -public: - Slime(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Slime; } -}; - -class Giant : public Mob { -public: - Giant(MobID id, std::uint8_t level, PlayerID sender) : Mob(id, level, sender) { InitMob(); } - - virtual MobType GetType() const { return MobType::Giant; } -}; +using Zombie = ConcreteMob; +using Spider = ConcreteMob; +using Skeleton = ConcreteMob; +using PigMan = ConcreteMob; +using Creeper = ConcreteMob; +using Silverfish = ConcreteMob; +using Blaze = ConcreteMob; +using Witch = ConcreteMob; +using Slime = ConcreteMob; +using Giant = ConcreteMob; namespace MobFactory { MobPtr CreateMob(MobID id, MobType type, std::uint8_t level, PlayerID sender); std::string GetMobName(MobType type); -} +} // namespace MobFactory class MobListener { -public: + public: virtual void OnMobSpawn(Mob* mob) {} virtual void OnMobDie(Mob* mob) {} @@ -255,6 +239,5 @@ public: // typedef utils::ObjectNotifier MobNotifier; -} // namespace game -} // namespace td - +} // namespace game +} // namespace td diff --git a/include/td/render/renderer/EntityRenderer.h b/include/td/render/renderer/EntityRenderer.h new file mode 100644 index 0000000..4f6562c --- /dev/null +++ b/include/td/render/renderer/EntityRenderer.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +namespace td { +namespace render { + +class EntityRenderer : public Renderer { + private: + const game::World& m_World; + std::unique_ptr m_EntityVao; + + public: + EntityRenderer(Camera& a_Camera, const game::World& a_World); + virtual ~EntityRenderer(); + + virtual void Render() override; +}; + +} // namespace render +} // namespace td diff --git a/include/td/render/shader/EntityShader.h b/include/td/render/shader/EntityShader.h index 765d908..1c7c948 100644 --- a/include/td/render/shader/EntityShader.h +++ b/include/td/render/shader/EntityShader.h @@ -1,14 +1,12 @@ #pragma once -#include +#include namespace td { namespace shader { -class EntityShader : public ShaderProgram { +class EntityShader : public CameraShaderProgram { private: - unsigned int m_LocationProjectionMatrix = 0; - unsigned int m_LocationViewMatrix = 0; unsigned int m_LocationPosition = 0; unsigned int m_LocationColorEffect = 0; @@ -18,11 +16,7 @@ class EntityShader : public ShaderProgram { public: EntityShader(); - void LoadShader(); - void SetColorEffect(const Vec3f& color); - void SetProjectionMatrix(const Mat4f& proj) const; - void SetViewMatrix(const Mat4f& view) const; void SetModelPos(const Vec3f& pos) const; }; diff --git a/src/main.cpp b/src/main.cpp index e17c847..281f48c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,9 @@ #include #include + #include +#include namespace td { namespace game { @@ -202,8 +204,13 @@ int main(int argc, char** argv) { td::render::Camera cam; + auto mob = std::make_shared(0, 0, 0); + mob->SetCenter({77, 13}); + w.GetMobList().push_back(mob); + td::render::RenderPipeline renderer; renderer.AddRenderer(cam, w); + renderer.AddRenderer(cam, w); cam.SetCamPos({77, 25, 13}); cam.UpdatePerspective(display.GetAspectRatio()); diff --git a/src/td/game/Mobs.cpp b/src/td/game/Mobs.cpp new file mode 100644 index 0000000..1cae4a7 --- /dev/null +++ b/src/td/game/Mobs.cpp @@ -0,0 +1,24 @@ +#include + +namespace td { +namespace game { + + +const MobStats* GetMobStats(MobType type, std::uint8_t level) { + static MobStats stats; + return &stats; +} + +const TowerImmunities& GetMobTowerImmunities(MobType type, std::uint8_t level) { + static TowerImmunities ti; + return ti; +} + +const EffectImmunities& GetMobEffectImmunities(MobType type, std::uint8_t level) { + static EffectImmunities ei; + return ei; +} + + +} // namespace game +} // namespace td diff --git a/src/td/render/loader/WorldLoader.cpp b/src/td/render/loader/WorldLoader.cpp index 9854c4c..cf1beee 100644 --- a/src/td/render/loader/WorldLoader.cpp +++ b/src/td/render/loader/WorldLoader.cpp @@ -159,9 +159,9 @@ GL::VertexArray LoadTileSelectModel() { colorVBO.AddVertexAttribPointer(1, 1, 0); std::vector indexes(positions.size() / 3, 0); - for (size_t i = 0; i < indexes.size(); i++) { - indexes[i] = i + 1; - } + // for (size_t i = 0; i < indexes.size(); i++) { + // indexes[i] = i + 1; + // } GL::ElementBuffer indexVBO(indexes); GL::VertexArray tileSelectVao(std::move(indexVBO)); @@ -211,6 +211,36 @@ RenderData LoadTowerModel(game::TowerPtr tower) { } + +GL::VertexArray LoadMobModel() { + std::vector positions = { + -0.5, 0, -0.5, + -0.5, 0, 0.5, + 0.5, 0, -0.5, + + 0.5, 0, -0.5, + -0.5, 0, 0.5, + 0.5, 0, 0.5 + }; + + std::vector indexes(positions.size() / 3, 0); + // for (size_t i = 0; i < indexes.size(); i++) { + // indexes[i] = i + 1; + // } + GL::ElementBuffer indexVBO(indexes); + + GL::VertexBuffer positionVBO(positions, POSITION_VERTEX_SIZE); + positionVBO.AddVertexAttribPointer(0, POSITION_VERTEX_SIZE, 0); + + GL::VertexArray mobVao(std::move(indexVBO)); // each pos = 1 color + mobVao.Bind(); + mobVao.BindVertexBuffer(std::move(positionVBO)); + mobVao.Unbind(); + return mobVao; +} + + + } // namespace WorldLoader diff --git a/src/td/render/renderer/EntityRenderer.cpp b/src/td/render/renderer/EntityRenderer.cpp new file mode 100644 index 0000000..1c8dac4 --- /dev/null +++ b/src/td/render/renderer/EntityRenderer.cpp @@ -0,0 +1,26 @@ +#include + +#include + +namespace td { +namespace render { + +EntityRenderer::EntityRenderer(Camera& a_Camera, const game::World& a_World) : Renderer(a_Camera), m_World(a_World) { + m_EntityVao = std::make_unique(std::move(WorldLoader::LoadMobModel())); + m_Shader->Start(); + m_Shader->SetColorEffect({1, 0, 1}); +} + +EntityRenderer::~EntityRenderer() {} + +void EntityRenderer::Render() { + m_Shader->Start(); + for (const auto& mob : m_World.GetMobList()) { + const auto mobCoords = mob->GetCenter(); + m_Shader->SetModelPos({mobCoords.GetX(), 1, mobCoords.GetY()}); + Renderer::Render(*m_EntityVao); + } +} + +} // namespace render +} // namespace td diff --git a/src/td/render/shader/EntityShader.cpp b/src/td/render/shader/EntityShader.cpp index 4b4dd06..3080487 100644 --- a/src/td/render/shader/EntityShader.cpp +++ b/src/td/render/shader/EntityShader.cpp @@ -53,16 +53,12 @@ static const char vertexSource[] = R"( #version 330 layout(location = 0) in vec3 position; -layout(location = 1) in vec2 textureCoords; uniform mat4 viewMatrix; uniform mat4 projectionMatrix; uniform vec3 modelPosition; -out vec2 pass_textureCoords; - void main(void){ - pass_textureCoords = textureCoords; gl_Position = projectionMatrix * viewMatrix * vec4(position + modelPosition, 1.0); } )"; @@ -70,16 +66,13 @@ void main(void){ static const char fragmentSource[] = R"( #version 330 -in vec2 pass_textureCoords; - out vec4 out_color; uniform vec3 ColorEffect; -uniform sampler2D textureSampler; void main(void){ - vec4 color = vec4(ColorEffect, 1.0) * texture(textureSampler, pass_textureCoords); + vec4 color = vec4(ColorEffect, 1.0); if (color.a <= 0.1) discard; @@ -90,31 +83,21 @@ void main(void){ )"; #endif -EntityShader::EntityShader() : ShaderProgram() {} - -void EntityShader::LoadShader() { +EntityShader::EntityShader() : CameraShaderProgram() { ShaderProgram::LoadProgram(vertexSource, fragmentSource); } + void EntityShader::GetAllUniformLocation() { + CameraShaderProgram::GetAllUniformLocation(); m_LocationColorEffect = static_cast(GetUniformLocation("ColorEffect")); - m_LocationViewMatrix = static_cast(GetUniformLocation("viewMatrix")); m_LocationPosition = static_cast(GetUniformLocation("modelPosition")); - m_LocationProjectionMatrix = static_cast(GetUniformLocation("projectionMatrix")); } void EntityShader::SetColorEffect(const Vec3f& color) { LoadVector(m_LocationColorEffect, color); } -void EntityShader::SetProjectionMatrix(const Mat4f& proj) const { - LoadMat4(m_LocationProjectionMatrix, proj); -} - -void EntityShader::SetViewMatrix(const Mat4f& view) const { - LoadMat4(m_LocationViewMatrix, view); -} - void EntityShader::SetModelPos(const Vec3f& pos) const { LoadVector(m_LocationPosition, pos); }