From fe7cfdec72e0e9c630893da1f34c8f71c89d21b0 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Sun, 26 Sep 2021 18:19:00 +0200 Subject: [PATCH] feat: add basic towers rendering --- include/game/Player.h | 4 +- include/game/Towers.h | 42 +++++++++++---------- include/game/World.h | 8 +++- include/game/client/ClientGame.h | 1 + include/game/client/WorldClient.h | 1 - include/game/server/ServerGame.h | 2 + include/game/server/ServerWorld.h | 3 ++ include/protocol/Protocol.h | 6 ++- include/render/VertexCache.h | 34 +++++++++++++++++ include/render/WorldRenderer.h | 6 ++- include/render/loader/WorldLoader.h | 6 +++ src/game/Team.cpp | 1 - src/game/Towers.cpp | 28 +++++++------- src/game/World.cpp | 5 ++- src/game/client/ClientGame.cpp | 7 +++- src/game/client/WorldClient.cpp | 7 +--- src/game/server/ServerConnexion.cpp | 6 +-- src/game/server/ServerGame.cpp | 4 +- src/game/server/ServerWorld.cpp | 6 +++ src/render/VertexCache.cpp | 57 +++++++++++++++++++++++++++++ src/render/WorldRenderer.cpp | 20 ++++++++-- src/render/loader/WorldLoader.cpp | 34 +++++++++++++++++ 22 files changed, 230 insertions(+), 58 deletions(-) create mode 100644 include/render/VertexCache.h create mode 100644 src/render/VertexCache.cpp diff --git a/include/game/Player.h b/include/game/Player.h index d22702c..b831aeb 100644 --- a/include/game/Player.h +++ b/include/game/Player.h @@ -10,7 +10,7 @@ namespace game { class Player { private: - game::TeamColor m_TeamColor = game::TeamColor::None; + game::TeamColor m_TeamColor; std::uint32_t m_Gold = 0; std::int32_t m_EXP = 0; @@ -19,7 +19,7 @@ private: std::uint8_t m_GoldPerSecond = 5; public: - Player(std::uint8_t id = 0) : m_ID(id) {} + Player(std::uint8_t id = 0) : m_TeamColor(game::TeamColor::None), m_ID(id) {} const std::string& getName() const { return m_Name; } void setName(const std::string& name) { m_Name = name; } diff --git a/include/game/Towers.h b/include/game/Towers.h index 73653ee..3671e6d 100644 --- a/include/game/Towers.h +++ b/include/game/Towers.h @@ -77,8 +77,11 @@ public: const TowerStats* getTowerStats(TowerType type, TowerLevel level); +typedef std::uint16_t TowerID; + class Tower { private: + TowerID m_ID; TowerType m_Type; std::uint16_t m_X, m_Y; TowerLevel m_Level{}; @@ -86,9 +89,9 @@ private: protected: utils::Timer m_Timer; public: // converting seconds to millis - Tower(TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : m_Type(type), m_X(x), m_Y(y), m_Builder(builder), - m_Timer(getStats()->getDamageRate()) { - + Tower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : m_ID(id), m_Type(type), m_X(x), m_Y(y), m_Builder(builder), + m_Timer(getStats()->getDamageRate()) { + } virtual TowerType getType() const = 0; @@ -100,6 +103,7 @@ public: // conve m_Level.setPath(path); } + std::uint16_t getID() const { return m_ID; } std::uint16_t getX() const { return m_X; } std::uint16_t getY() const { return m_Y; } const TowerLevel& getLevel() const { return m_Level; } @@ -109,10 +113,10 @@ public: // conve typedef std::shared_ptr TowerPtr; -namespace TowerFactory{ +namespace TowerFactory { + +TowerPtr createTower(TowerType type, TowerID id, std::int32_t x, std::int32_t y, PlayerID builder); -TowerPtr createTower(TowerType type, std::int32_t x, std::int32_t y, PlayerID builder); - } // namespace TowerFactory @@ -136,7 +140,7 @@ const TowerInfo& getTowerInfo(TowerType type); class LittleTower : public Tower { public: - LittleTower(TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(type, x, y, builder) {} + LittleTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {} virtual TowerSize getSize() const { return TowerSize::Little; } @@ -146,7 +150,7 @@ public: class ArcherTower : public LittleTower { public: - ArcherTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(getType(), x, y, builder) {} + ArcherTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Archer; } virtual void tick(std::uint64_t delta); @@ -154,7 +158,7 @@ public: class IceTower : public LittleTower { public: - IceTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(getType(), x, y, builder) {} + IceTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Ice; } virtual void tick(std::uint64_t delta); @@ -162,7 +166,7 @@ public: class MageTower : public LittleTower { public: - MageTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(getType(), x, y, builder) {} + MageTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Mage; } virtual void tick(std::uint64_t delta); @@ -170,7 +174,7 @@ public: class PoisonTower : public LittleTower { public: - PoisonTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(getType(), x, y, builder) {} + PoisonTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Poison; } virtual void tick(std::uint64_t delta); @@ -178,7 +182,7 @@ public: class QuakeTower : public LittleTower { public: - QuakeTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(getType(), x, y, builder) {} + QuakeTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Quake; } virtual void tick(std::uint64_t delta); @@ -186,7 +190,7 @@ public: class ArtilleryTower : public LittleTower { public: - ArtilleryTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(getType(), x, y, builder) {} + ArtilleryTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Artillery; } virtual void tick(std::uint64_t delta); @@ -194,7 +198,7 @@ public: class SorcererTower : public LittleTower { public: - SorcererTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(getType(), x, y, builder) {} + SorcererTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Sorcerer; } virtual void tick(std::uint64_t delta); @@ -202,7 +206,7 @@ public: class ZeusTower : public LittleTower { public: - ZeusTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(getType(), x, y, builder) {} + ZeusTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : LittleTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Zeus; } virtual void tick(std::uint64_t delta); @@ -212,7 +216,7 @@ public: class BigTower : public Tower { public: - BigTower(TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(type, x, y, builder) {} + BigTower(TowerID id, TowerType type, std::uint16_t x, std::uint16_t y, PlayerID builder) : Tower(id, type, x, y, builder) {} virtual TowerSize getSize() const { return TowerSize::Big; } @@ -222,7 +226,7 @@ public: class TurretTower : public BigTower { public: - TurretTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(getType(), x, y, builder) {} + TurretTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Turret; } virtual void tick(std::uint64_t delta); @@ -230,7 +234,7 @@ public: class NecromancerTower : public BigTower { public: - NecromancerTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(getType(), x, y, builder) {} + NecromancerTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Necromancer; } virtual void tick(std::uint64_t delta); @@ -238,7 +242,7 @@ public: class LeachTower : public BigTower { public: - LeachTower(std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(getType(), x, y, builder) {} + LeachTower(TowerID id, std::uint16_t x, std::uint16_t y, PlayerID builder) : BigTower(id, getType(), x, y, builder) {} virtual TowerType getType() const { return TowerType::Leach; } virtual void tick(std::uint64_t delta); diff --git a/include/game/World.h b/include/game/World.h index 09deaf6..5961e63 100644 --- a/include/game/World.h +++ b/include/game/World.h @@ -111,6 +111,8 @@ typedef std::vector MobList; typedef std::array SpawnColorPalette; +typedef std::vector TowerList; + class World { protected: TowerTileColorPalette m_TowerPlacePalette; @@ -125,7 +127,7 @@ protected: MobList m_Mobs; - std::vector m_Towers; + TowerList m_Towers; Game* m_Game; public: @@ -141,7 +143,7 @@ public: void spawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID sender, float x, float y, Direction dir); - void placeTowerAt(TowerType type, std::int32_t x, std::int32_t y, PlayerID builder); + 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; @@ -178,6 +180,8 @@ public: Team& getTeam(TeamColor team); const Team& getTeam(TeamColor team) const; + + const TowerList& getTowers() const { return m_Towers; }; private: void moveMobs(std::uint64_t delta); }; diff --git a/include/game/client/ClientGame.h b/include/game/client/ClientGame.h index 97a972c..6ce81a8 100644 --- a/include/game/client/ClientGame.h +++ b/include/game/client/ClientGame.h @@ -49,6 +49,7 @@ public: virtual void HandlePacket(protocol::UpdateMoneyPacket* packet); virtual void HandlePacket(protocol::DisconnectPacket* packet); virtual void HandlePacket(protocol::WorldDataPacket* packet); + virtual void HandlePacket(protocol::WorldAddTowerPacket* packet); }; } // namespace client diff --git a/include/game/client/WorldClient.h b/include/game/client/WorldClient.h index eb23691..8d7e2ad 100644 --- a/include/game/client/WorldClient.h +++ b/include/game/client/WorldClient.h @@ -16,7 +16,6 @@ public: virtual void HandlePacket(protocol::WorldBeginDataPacket* packet); virtual void HandlePacket(protocol::WorldDataPacket* packet); - virtual void HandlePacket(protocol::WorldAddTowerPacket* packet); virtual void HandlePacket(protocol::SpawnMobPacket* packet); }; diff --git a/include/game/server/ServerGame.h b/include/game/server/ServerGame.h index f32cc1a..8604c15 100644 --- a/include/game/server/ServerGame.h +++ b/include/game/server/ServerGame.h @@ -18,6 +18,8 @@ public: ServerGame(Server* server); ~ServerGame() {} + ServerWorld* getServerWorld() { return &m_ServerWorld; } + virtual void tick(std::uint64_t delta); void startGame(); private: diff --git a/include/game/server/ServerWorld.h b/include/game/server/ServerWorld.h index f3e9094..81c7208 100644 --- a/include/game/server/ServerWorld.h +++ b/include/game/server/ServerWorld.h @@ -11,10 +11,13 @@ class ServerGame; class ServerWorld : public game::World { private: game::MobID m_CurrentMobID; + game::TowerID m_CurrentTowerID; Server* m_Server; public: ServerWorld(Server* server, ServerGame* game); + void spawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count); + game::TowerPtr placeTowerAt(game::TowerType type, std::int32_t x, std::int32_t y, game::PlayerID builder); }; } // namespace server diff --git a/include/protocol/Protocol.h b/include/protocol/Protocol.h index da181ca..830ab27 100644 --- a/include/protocol/Protocol.h +++ b/include/protocol/Protocol.h @@ -405,19 +405,21 @@ public: class WorldAddTowerPacket : public Packet { private: + game::TowerID m_TowerID; std::int32_t m_TowerX, m_TowerY; game::TowerType m_TowerType; game::PlayerID m_Builder; public: WorldAddTowerPacket() {} - WorldAddTowerPacket(std::int32_t x, std::int32_t y, game::TowerType type, game::PlayerID player) : - m_TowerX(x), m_TowerY(y), m_TowerType(type), m_Builder(player) {} + WorldAddTowerPacket(game::TowerID id, std::int32_t x, std::int32_t y, game::TowerType type, game::PlayerID player) : + m_TowerID(id), m_TowerX(x), m_TowerY(y), m_TowerType(type), m_Builder(player) {} virtual ~WorldAddTowerPacket() {} virtual DataBuffer Serialize() const; virtual void Deserialize(DataBuffer& data); virtual void Dispatch(PacketHandler* handler); + game::TowerID getTowerID() const { return m_TowerID; } std::int32_t getTowerX() const { return m_TowerX; } std::int32_t getTowerY() const { return m_TowerY; } game::TowerType getTowerType() const { return m_TowerType; } diff --git a/include/render/VertexCache.h b/include/render/VertexCache.h new file mode 100644 index 0000000..5f1862a --- /dev/null +++ b/include/render/VertexCache.h @@ -0,0 +1,34 @@ +#include +#include +#include + +#include "render/loader/GLLoader.h" + + +namespace td { +namespace render { + + +class VertexCache { + +typedef std::vector Vector; +typedef std::pair ElementsIndex; +typedef std::pair DataIndex; + +private: + Vector m_Positions; + Vector m_Colors; + std::unordered_map m_Indexes; + std::unique_ptr m_VertexArray; +public: + void addData(std::uint64_t index, std::vector positions, std::vector colors); + void removeData(std::uint64_t index); + void clear(); + void updateVertexArray(); + + const GL::VertexArray& getVertexArray() const { return *m_VertexArray; } + bool isEmpty() const { return m_VertexArray == nullptr; } +}; + +} // namespace render +} // namespace td diff --git a/include/render/WorldRenderer.h b/include/render/WorldRenderer.h index e34e80d..cf6b92d 100644 --- a/include/render/WorldRenderer.h +++ b/include/render/WorldRenderer.h @@ -1,8 +1,8 @@ #pragma once #include "game/World.h" -#include "render/loader/GLLoader.h" #include "render/Renderer.h" +#include "render/VertexCache.h" #include @@ -29,12 +29,16 @@ private: float m_Zoom = 1; float m_CamSensibility = 1; bool m_TowerPlacePopupOpened = false; + VertexCache m_TowersCache; public: WorldRenderer(game::World* world, client::ClientGame* client); ~WorldRenderer(); void loadModels(); + void addTower(game::TowerPtr tower); + void removeTower(game::TowerPtr tower); + void update(); void render(); diff --git a/include/render/loader/WorldLoader.h b/include/render/loader/WorldLoader.h index 59ed145..acf4af4 100644 --- a/include/render/loader/WorldLoader.h +++ b/include/render/loader/WorldLoader.h @@ -8,9 +8,15 @@ namespace render { namespace WorldLoader { +struct RenderData{ + std::vector positions; + std::vector colors; +}; + GL::VertexArray loadMobModel(); GL::VertexArray loadWorldModel(const td::game::World* world); GL::VertexArray loadTileSelectModel(); +RenderData loadTowerModel(game::TowerPtr tower); } // namespace WorldLoader diff --git a/src/game/Team.cpp b/src/game/Team.cpp index 702fb49..38c38db 100644 --- a/src/game/Team.cpp +++ b/src/game/Team.cpp @@ -7,7 +7,6 @@ Team::Team(TeamColor color) : m_Color(color) {} void Team::addPlayer(Player* newPlayer) { m_Players.push_back(newPlayer); - newPlayer->setTeamColor(m_Color); } void Team::removePlayer(const Player* player) { diff --git a/src/game/Towers.cpp b/src/game/Towers.cpp index 9a26c8b..20095c7 100644 --- a/src/game/Towers.cpp +++ b/src/game/Towers.cpp @@ -135,24 +135,24 @@ const TowerInfo& getTowerInfo(TowerType type) { namespace TowerFactory { -using TowerCreator = std::function(std::int32_t, std::int32_t, PlayerID)>; +using TowerCreator = std::function(TowerID, std::int32_t, std::int32_t, PlayerID)>; static const std::map towerFactory = { - {TowerType::Archer, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Artillery, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Ice, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Mage, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Poison, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Quake, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Sorcerer, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Zeus, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Leach, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Necromancer, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, - {TowerType::Turret, [](std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(x, y, builder);} }, + {TowerType::Archer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Artillery, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Ice, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Mage, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Poison, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Quake, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Sorcerer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Zeus, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Leach, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Necromancer, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, + {TowerType::Turret, [](TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) -> TowerPtr {return std::make_shared(id, x, y , builder);} }, }; -TowerPtr createTower(TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) { - return towerFactory.at(type)(x, y, builder); +TowerPtr createTower(TowerType type, TowerID id, std::int32_t x, std::int32_t y, PlayerID builder) { + return towerFactory.at(type)(id, x, y, builder); } } // namespace TowerFactory diff --git a/src/game/World.cpp b/src/game/World.cpp index cdedead..a9e8f1e 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -334,9 +334,10 @@ void World::spawnMobAt(MobID id, MobType type, std::uint8_t level, PlayerID send m_Mobs.push_back(mob); } -void World::placeTowerAt(TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) { - TowerPtr tower = TowerFactory::createTower(type, x, y, builder); +TowerPtr World::placeTowerAt(TowerID id, TowerType type, std::int32_t x, std::int32_t y, PlayerID builder) { + TowerPtr tower = TowerFactory::createTower(type, id, x, y, builder); m_Towers.push_back(tower); + return tower; } void World::moveMobs(std::uint64_t delta) { diff --git a/src/game/client/ClientGame.cpp b/src/game/client/ClientGame.cpp index cb6ce39..0c53049 100644 --- a/src/game/client/ClientGame.cpp +++ b/src/game/client/ClientGame.cpp @@ -21,6 +21,7 @@ m_WorldRenderer(&m_WorldClient, this) { GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateMoney, this); GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this); GetDispatcher()->RegisterHandler(protocol::PacketType::WorldData, this); + GetDispatcher()->RegisterHandler(protocol::PacketType::WorldAddTower, this); } ClientGame::~ClientGame() { @@ -71,11 +72,11 @@ void ClientGame::HandlePacket(protocol::UpdatePlayerTeamPacket* packet) { getTeam(packet->getSelectedTeam()).addPlayer(player); } else if (packet->getSelectedTeam() == game::TeamColor::None) { // leave a team getTeam(player->getTeamColor()).removePlayer(player); - player->setTeamColor(game::TeamColor::None); } else { // change team getTeam(player->getTeamColor()).removePlayer(player); getTeam(packet->getSelectedTeam()).addPlayer(player); } + player->setTeamColor(packet->getSelectedTeam()); } void ClientGame::HandlePacket(protocol::UpdateGameStatePacket* packet) { @@ -116,5 +117,9 @@ void ClientGame::PlaceTower(game::TowerType type, const glm::vec2& position) { m_Client->getConnexion().sendPacket(&packet); } +void ClientGame::HandlePacket(protocol::WorldAddTowerPacket* packet){ + m_WorldRenderer.addTower(m_WorldClient.placeTowerAt(packet->getTowerID(), packet->getTowerType(), packet->getTowerX(), packet->getTowerY(), packet->getBuilder())); +} + } // namespace client } // namespace td diff --git a/src/game/client/WorldClient.cpp b/src/game/client/WorldClient.cpp index 01c083e..b681190 100644 --- a/src/game/client/WorldClient.cpp +++ b/src/game/client/WorldClient.cpp @@ -3,13 +3,14 @@ #include "game/client/ClientGame.h" #include "render/WorldRenderer.h" +#include + namespace td { namespace client { WorldClient::WorldClient(ClientGame* game) : game::World(game), protocol::PacketHandler(game->GetDispatcher()), m_Game(game) { GetDispatcher()->RegisterHandler(protocol::PacketType::WorldBeginData, this); GetDispatcher()->RegisterHandler(protocol::PacketType::WorldData, this); - GetDispatcher()->RegisterHandler(protocol::PacketType::WorldAddTower, this); GetDispatcher()->RegisterHandler(protocol::PacketType::SpawnMob, this); } @@ -21,10 +22,6 @@ void WorldClient::HandlePacket(protocol::WorldDataPacket* packet) { loadMap(packet); } -void WorldClient::HandlePacket(protocol::WorldAddTowerPacket* packet) { - placeTowerAt(packet->getTowerType(), packet->getTowerX(), packet->getTowerY(), packet->getBuilder()); -} - void WorldClient::HandlePacket(protocol::SpawnMobPacket* packet) { spawnMobAt(packet->getMobID(), packet->getMobType(), packet->getMobLevel(), packet->getSender(), packet->getMobX(), packet->getMobY(), packet->getMobDirection()); diff --git a/src/game/server/ServerConnexion.cpp b/src/game/server/ServerConnexion.cpp index d2be271..1a00f21 100644 --- a/src/game/server/ServerConnexion.cpp +++ b/src/game/server/ServerConnexion.cpp @@ -146,7 +146,7 @@ void ServerConnexion::initConnection() { void ServerConnexion::HandlePacket(protocol::PlaceTowerPacket* packet) { game::TowerType towerType = packet->getTowerType(); const game::TowerInfo& towerInfo = game::getTowerInfo(towerType); - game::World* world = m_Server->getGame().getWorld(); + server::ServerWorld* world = m_Server->getGame().getServerWorld(); if (towerInfo.isBigTower()) { if (!world->CanPlaceBigTower({ packet->getTowerX(), packet->getTowerY() }, m_ID)) return; @@ -155,9 +155,9 @@ void ServerConnexion::HandlePacket(protocol::PlaceTowerPacket* packet) { return; } - world->placeTowerAt(towerType, packet->getTowerX(), packet->getTowerY(), m_ID); + game::TowerPtr tower = world->placeTowerAt(towerType, packet->getTowerX(), packet->getTowerY(), m_ID); - protocol::WorldAddTowerPacket addTowerPacket(packet->getTowerX(), packet->getTowerY(), packet->getTowerType(), m_ID); + protocol::WorldAddTowerPacket addTowerPacket(tower->getID(), packet->getTowerX(), packet->getTowerY(), packet->getTowerType(), m_ID); m_Server->broadcastPacket(&addTowerPacket); } diff --git a/src/game/server/ServerGame.cpp b/src/game/server/ServerGame.cpp index 52b1f82..c207161 100644 --- a/src/game/server/ServerGame.cpp +++ b/src/game/server/ServerGame.cpp @@ -37,14 +37,16 @@ void ServerGame::updateGoldMines() { } void ServerGame::balanceTeams() { - for (auto playerInfo : m_Players) { + for (auto& playerInfo : Game::m_Players) { game::Player& player = playerInfo.second; if (player.getTeamColor() == game::TeamColor::None) { game::Team& redTeam = getRedTeam(); game::Team& blueTeam = getBlueTeam(); if (blueTeam.getPlayerCount() > redTeam.getPlayerCount()) { + player.setTeamColor(game::TeamColor::Red); redTeam.addPlayer(&player); } else { + player.setTeamColor(game::TeamColor::Blue); blueTeam.addPlayer(&player); } protocol::UpdatePlayerTeamPacket packet(player.getID(), player.getTeamColor()); diff --git a/src/game/server/ServerWorld.cpp b/src/game/server/ServerWorld.cpp index 22f10a6..304b873 100644 --- a/src/game/server/ServerWorld.cpp +++ b/src/game/server/ServerWorld.cpp @@ -46,5 +46,11 @@ void ServerWorld::spawnMobs(game::MobType type, std::uint8_t level, game::Player } } +game::TowerPtr ServerWorld::placeTowerAt(game::TowerType type, std::int32_t x, std::int32_t y, game::PlayerID builder){ + game::TowerPtr tower = World::placeTowerAt(m_CurrentTowerID, type, x, y, builder); + m_CurrentTowerID++; + return tower; +} + } // namespace server } // namespace td diff --git a/src/render/VertexCache.cpp b/src/render/VertexCache.cpp new file mode 100644 index 0000000..89ba843 --- /dev/null +++ b/src/render/VertexCache.cpp @@ -0,0 +1,57 @@ +#include "render/VertexCache.h" +#include "render/loader/GLLoader.h" + +namespace td { +namespace render { + +void VertexCache::addData(std::uint64_t index, std::vector positions, std::vector colors){ + ElementsIndex positionsIndexes; + positionsIndexes.first = m_Positions.end(); + m_Positions.insert(m_Positions.end(), positions.begin(), positions.end()); + positionsIndexes.second = m_Positions.end() - 1; + + ElementsIndex colorsIndexes; + colorsIndexes.first = m_Colors.end(); + m_Colors.insert(m_Colors.end(), colors.begin(), colors.end()); + colorsIndexes.second = m_Colors.end() - 1; + + m_Indexes.insert({index, {positionsIndexes, colorsIndexes}}); +} + +void VertexCache::removeData(std::uint64_t index){ + auto it = m_Indexes.find(index); + if(it != m_Indexes.end()){ + DataIndex indexes = it->second; + ElementsIndex positionsIndexes = indexes.first; + ElementsIndex colorsIndexes = indexes.second; + + m_Positions.erase(positionsIndexes.first, positionsIndexes.second); + m_Colors.erase(colorsIndexes.first, colorsIndexes.second); + + m_Indexes.erase(it); + } +} + +void VertexCache::clear(){ + m_Positions.clear(); + m_Colors.clear(); + m_Indexes.clear(); +} + +void VertexCache::updateVertexArray(){ + m_VertexArray = std::make_unique(m_Colors.size()); // one color per vertex + + GL::VertexBuffer positionsBuffer(m_Positions, 2); + positionsBuffer.addVertexAttribPointer(0, 2, 0); + + GL::VertexBuffer colorsBuffer(m_Colors, 1); + colorsBuffer.addVertexAttribPointer(1, 1, 0); + + m_VertexArray->bind(); + m_VertexArray->bindVertexBuffer(positionsBuffer); + m_VertexArray->bindVertexBuffer(colorsBuffer); + m_VertexArray->unbind(); +} + +} // namespace render +} // namespace td diff --git a/src/render/WorldRenderer.cpp b/src/render/WorldRenderer.cpp index 67676f4..6f49587 100644 --- a/src/render/WorldRenderer.cpp +++ b/src/render/WorldRenderer.cpp @@ -62,6 +62,11 @@ void WorldRenderer::renderMobs() const { } void WorldRenderer::renderTowers() const { + if(!m_TowersCache.isEmpty()) + m_Renderer->renderVAO(m_TowersCache.getVertexArray()); +} + +void WorldRenderer::renderTileSelect() const { Renderer::Model tileSelectModel; tileSelectModel.vao = m_SelectTileVao.get(); tileSelectModel.positon = { (int)m_CursorPos.x, (int)m_CursorPos.y }; @@ -69,10 +74,6 @@ void WorldRenderer::renderTowers() const { m_Renderer->renderModel(tileSelectModel); } -void WorldRenderer::renderTileSelect() const { - -} - void WorldRenderer::render() { if (m_WorldVao == nullptr) return; @@ -151,6 +152,17 @@ void WorldRenderer::detectClick() { } } +void WorldRenderer::addTower(game::TowerPtr tower){ + const WorldLoader::RenderData& renderData = WorldLoader::loadTowerModel(tower); + m_TowersCache.addData(tower->getID(), renderData.positions, renderData.colors); + m_TowersCache.updateVertexArray(); +} + +void WorldRenderer::removeTower(game::TowerPtr tower){ + m_TowersCache.removeData(tower->getID()); + m_TowersCache.updateVertexArray(); +} + glm::vec2 WorldRenderer::getCursorWorldPos() const { ImGuiIO& io = ImGui::GetIO(); return m_Renderer->getCursorWorldPos({ io.MousePos.x, io.MousePos.y }, Display::getAspectRatio(), m_Zoom, Display::getWindowWidth(), Display::getWindowHeight()); diff --git a/src/render/loader/WorldLoader.cpp b/src/render/loader/WorldLoader.cpp index 7216cda..dccadfd 100644 --- a/src/render/loader/WorldLoader.cpp +++ b/src/render/loader/WorldLoader.cpp @@ -188,6 +188,40 @@ GL::VertexArray loadTileSelectModel() { return tileSelectVao; } +RenderData loadTowerModel(game::TowerPtr tower){ + RenderData renderData; + + float towerX = tower->getX() - 1; + float towerDX = tower->getX() + 2; + + float towerY = tower->getY() - 1; + float towerDY = tower->getY() + 2; + std::vector positions = { + towerX, towerY, + towerDX, towerY, + towerX, towerDY, + + towerDX, towerY, + towerX, towerDY, + towerDX, towerDY + }; + + renderData.positions = positions; + + std::uint8_t towerType = static_cast(tower->getType()); + std::uint8_t r = 10 * towerType + 40, g = 5 * towerType + 30, b = 10 * towerType + 20; + + float colorFloat; + int color = r << 24 | g << 16 | b << 8 | 255; + memcpy(&colorFloat, &color, sizeof(int)); + + std::vector colors(6, colorFloat); + renderData.colors = colors; + + return renderData; +} + + } // namespace WorldLoader