feat: remove tower

This commit is contained in:
2021-12-08 15:34:20 +01:00
parent 78cf2d0f18
commit e4a9c5f763
16 changed files with 88 additions and 38 deletions

View File

@@ -168,6 +168,7 @@ public:
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;

View File

@@ -44,6 +44,7 @@ public:
void sendMobs(const std::vector<protocol::MobSend>& mobSends);
void placeTower(game::TowerType type, const glm::vec2& position);
void upgradeTower(game::TowerID tower, game::TowerLevel level);
void removeTower(game::TowerID tower);
};
} // namespace client

View File

@@ -19,6 +19,7 @@ public:
virtual void HandlePacket(const protocol::SpawnMobPacket* packet);
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet);
virtual void HandlePacket(const protocol::WorldAddTowerPacket* packet);
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet);
};

View File

@@ -40,6 +40,7 @@ public:
virtual void HandlePacket(const protocol::PlaceTowerPacket* packet);
virtual void HandlePacket(const protocol::SendMobsPacket* packet);
virtual void HandlePacket(const protocol::UpgradeTowerPacket* packet);
virtual void HandlePacket(const protocol::RemoveTowerPacket* packet);
std::uint8_t getID() const { return m_ID; }
const game::Player* getPlayer() const { return m_Player; }

View File

@@ -35,7 +35,7 @@ public:
virtual void HandlePacket(const SpawnMobPacket* packet) {}
virtual void HandlePacket(const PlaceTowerPacket* packet) {}
virtual void HandlePacket(const WorldAddTowerPacket* packet) {}
virtual void HandlePacket(const WorldRemoveTowerPacket* packet) {}
virtual void HandlePacket(const RemoveTowerPacket* packet) {}
virtual void HandlePacket(const SendMobsPacket* packet) {}
virtual void HandlePacket(const UpgradeTowerPacket* packet) {}
};

View File

@@ -33,12 +33,12 @@ enum class PacketType : std::uint8_t {
UpdatePlayerTeam,
ServerTps,
WorldAddTower,
WorldRemoveTower,
// client <--> server
KeepAlive,
Disconnect,
UpgradeTower,
RemoveTower,
};
struct WorldHeader {
@@ -477,13 +477,13 @@ public:
virtual PacketType getType() const { return PacketType::WorldAddTower; }
};
class WorldRemoveTowerPacket : public Packet {
class RemoveTowerPacket : public Packet {
private:
game::TowerID m_TowerID;
public:
WorldRemoveTowerPacket() {}
WorldRemoveTowerPacket(game::TowerID id) : m_TowerID(id) {}
virtual ~WorldRemoveTowerPacket() {}
RemoveTowerPacket() {}
RemoveTowerPacket(game::TowerID id) : m_TowerID(id) {}
virtual ~RemoveTowerPacket() {}
virtual DataBuffer Serialize() const;
virtual void Deserialize(DataBuffer& data);
@@ -491,7 +491,7 @@ public:
game::TowerID getTowerID() const { return m_TowerID; }
virtual PacketType getType() const { return PacketType::WorldRemoveTower; }
virtual PacketType getType() const { return PacketType::RemoveTower; }
};
class UpgradeTowerPacket : public Packet {

View File

@@ -12,15 +12,19 @@ namespace render {
class VertexCache {
typedef std::vector<float> Vector;
typedef std::pair<Vector::iterator, Vector::iterator> ElementsIndex;
typedef std::pair<ElementsIndex, ElementsIndex> DataIndex;
struct DataIndex {
Vector position;
Vector color;
};
private:
Vector m_Positions;
Vector m_Colors;
std::size_t m_VertexCount;
std::unordered_map<std::uint64_t, DataIndex> m_Indexes;
std::unique_ptr<GL::VertexArray> m_VertexArray;
public:
VertexCache() : m_VertexCount(0) {}
void addData(std::uint64_t index, std::vector<float> positions, std::vector<float> colors);
void removeData(std::uint64_t index);
void clear();

View File

@@ -71,6 +71,7 @@ private:
void renderMobTooltip() const;
void detectClick();
void detectMobHovering() const;
void removeTower();
glm::vec2 getCursorWorldPos() const;
glm::vec2 getClickWorldPos() const;

View File

@@ -122,6 +122,17 @@ TowerPtr World::placeTowerAt(TowerID id, TowerType type, std::int32_t x, std::in
return tower;
}
TowerPtr World::removeTower(TowerID towerId) {
auto it = std::find_if(m_Towers.begin(), m_Towers.end(), [towerId](TowerPtr tower) { return tower->getID() == towerId;});
if (it == m_Towers.end()) return nullptr;
TowerPtr tower = *it;
m_Towers.erase(it);
return tower;
}
void World::tickMobs(std::uint64_t delta) {
for (MobPtr mob : m_Mobs) {
mob->tick(delta);

View File

@@ -64,5 +64,10 @@ void Client::upgradeTower(game::TowerID tower, game::TowerLevel level) {
m_Connexion.sendPacket(&packet);
}
void Client::removeTower(game::TowerID tower) {
protocol::RemoveTowerPacket packet(tower);
m_Connexion.sendPacket(&packet);
}
} // namespace client
} // namespace td

View File

@@ -12,6 +12,7 @@ WorldClient::WorldClient(ClientGame* game) : game::World(game), protocol::Packet
GetDispatcher()->RegisterHandler(protocol::PacketType::WorldData, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::SpawnMob, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::RemoveTower, this);
}
void WorldClient::HandlePacket(const protocol::WorldBeginDataPacket* packet) {
@@ -39,5 +40,13 @@ void WorldClient::HandlePacket(const protocol::WorldAddTowerPacket* packet) {
notifyListeners(&WorldListener::OnTowerAdd, newTower);
}
void WorldClient::HandlePacket(const protocol::RemoveTowerPacket* packet) {
game::TowerPtr tower = removeTower(packet->getTowerID());
if (tower != nullptr) {
notifyListeners(&WorldListener::OnTowerRemove, tower);
}
}
} // namespace client
} // namespace td

View File

@@ -41,6 +41,7 @@ void ServerConnexion::registerHandlers() {
GetDispatcher()->RegisterHandler(protocol::PacketType::PlaceTower, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::SendMobs, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::UpgradeTower, this);
GetDispatcher()->RegisterHandler(protocol::PacketType::RemoveTower, this);
}
bool ServerConnexion::updateSocket() {
@@ -181,6 +182,12 @@ void ServerConnexion::HandlePacket(const protocol::UpgradeTowerPacket* packet) {
m_Server->broadcastPacket(packet);
}
void ServerConnexion::HandlePacket(const protocol::RemoveTowerPacket* packet) {
//TODO: verify the packet
m_Server->broadcastPacket(packet);
}
ServerConnexion::~ServerConnexion() {
if (GetDispatcher() != nullptr)
GetDispatcher()->UnregisterHandler(this);

View File

@@ -28,7 +28,7 @@ static std::map<PacketType, PacketCreator> packets = {
{PacketType::SpawnMob, []() -> PacketPtr {return std::make_unique<SpawnMobPacket>(); } },
{PacketType::PlaceTower, []() -> PacketPtr {return std::make_unique<PlaceTowerPacket>(); } },
{PacketType::WorldAddTower, []() -> PacketPtr {return std::make_unique<WorldAddTowerPacket>(); } },
{PacketType::WorldRemoveTower, []() -> PacketPtr {return std::make_unique<WorldRemoveTowerPacket>(); } },
{PacketType::RemoveTower, []() -> PacketPtr {return std::make_unique<RemoveTowerPacket>(); } },
{PacketType::SendMobs, []() -> PacketPtr {return std::make_unique<SendMobsPacket>(); } },
{PacketType::UpgradeTower, []() -> PacketPtr {return std::make_unique<UpgradeTowerPacket>(); } },
};

View File

@@ -485,13 +485,13 @@ void WorldAddTowerPacket::Deserialize(DataBuffer& data) {
data >> m_TowerID >> m_TowerX >> m_TowerY >> m_TowerType >> m_Builder;
}
DataBuffer WorldRemoveTowerPacket::Serialize() const {
DataBuffer RemoveTowerPacket::Serialize() const {
DataBuffer data;
data << getID() << m_TowerID;
return data;
}
void WorldRemoveTowerPacket::Deserialize(DataBuffer& data) {
void RemoveTowerPacket::Deserialize(DataBuffer& data) {
data >> m_TowerID;
}
@@ -543,7 +543,7 @@ REGISTER_DISPATCH_CLASS(ServerTpsPacket);
REGISTER_DISPATCH_CLASS(SpawnMobPacket);
REGISTER_DISPATCH_CLASS(PlaceTowerPacket);
REGISTER_DISPATCH_CLASS(WorldAddTowerPacket);
REGISTER_DISPATCH_CLASS(WorldRemoveTowerPacket);
REGISTER_DISPATCH_CLASS(RemoveTowerPacket);
REGISTER_DISPATCH_CLASS(SendMobsPacket);
REGISTER_DISPATCH_CLASS(UpgradeTowerPacket);

View File

@@ -5,46 +5,43 @@ namespace td {
namespace render {
void VertexCache::addData(std::uint64_t index, std::vector<float> positions, std::vector<float> 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} });
m_Indexes.insert({ index, {positions, colors} });
m_VertexCount += colors.size(); // one color per vertex
}
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);
m_VertexCount -= it->second.color.size(); // one color per vertex
}
}
void VertexCache::clear() {
m_Positions.clear();
m_Colors.clear();
m_Indexes.clear();
m_VertexCount = 0;
}
void VertexCache::updateVertexArray() {
m_VertexArray = std::make_unique<GL::VertexArray>(m_Colors.size()); // one color per vertex
m_VertexArray = std::make_unique<GL::VertexArray>(m_VertexCount); // one color per vertex
GL::VertexBuffer positionsBuffer(m_Positions, 2);
Vector positions;
positions.reserve(m_VertexCount * 2);
Vector colors;
colors.reserve(m_VertexCount);
for (auto it = m_Indexes.begin(); it != m_Indexes.end(); it++) {
const DataIndex& data = it->second;
positions.insert(positions.end(), data.position.begin(), data.position.end());
colors.insert(colors.end(), data.color.begin(), data.color.end());
}
GL::VertexBuffer positionsBuffer(positions, 2);
positionsBuffer.addVertexAttribPointer(0, 2, 0);
GL::VertexBuffer colorsBuffer(m_Colors, 1);
GL::VertexBuffer colorsBuffer(colors, 1);
colorsBuffer.addVertexAttribPointer(1, 1, 0);
m_VertexArray->bind();

View File

@@ -65,6 +65,18 @@ void WorldRenderer::update() {
m_PopupOpened = false;
}
}
if (ImGui::IsMouseDoubleClicked(1)) removeTower();
}
void WorldRenderer::removeTower() {
glm::vec2 cursorPos = getCursorWorldPos();
game::TowerPtr clickedTower = m_World->getTower(cursorPos);
if (clickedTower != nullptr) {
m_Client->getClient()->removeTower(clickedTower->getID());
}
}
void WorldRenderer::renderWorld() const {