feat: add summon menu
This commit is contained in:
@@ -27,7 +27,9 @@ enum class MobType : std::uint8_t {
|
||||
Blaze,
|
||||
Witch,
|
||||
Slime,
|
||||
Giant
|
||||
Giant,
|
||||
|
||||
MOB_COUNT
|
||||
};
|
||||
|
||||
typedef std::uint32_t MobID;
|
||||
@@ -132,6 +134,62 @@ public:
|
||||
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) { initHealth(); }
|
||||
|
||||
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) { initHealth(); }
|
||||
|
||||
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) { initHealth(); }
|
||||
|
||||
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) { initHealth(); }
|
||||
|
||||
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) { initHealth(); }
|
||||
|
||||
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) { initHealth(); }
|
||||
|
||||
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) { initHealth(); }
|
||||
|
||||
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) { initHealth(); }
|
||||
|
||||
virtual MobType getType() const { return MobType::Giant; }
|
||||
};
|
||||
|
||||
namespace MobFactory {
|
||||
MobPtr createMob(MobID id, MobType type, std::uint8_t level, PlayerID sender);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "game/Team.h"
|
||||
#include "game/Player.h"
|
||||
|
||||
#include "protocol/Protocol.h"
|
||||
|
||||
#include "render/Renderer.h"
|
||||
|
||||
#include "network/Network.h"
|
||||
@@ -39,6 +41,7 @@ public:
|
||||
bool isConnected() const { return m_Connexion.getSocketStatus() == network::Socket::Connected; }
|
||||
|
||||
void selectTeam(game::TeamColor team);
|
||||
void sendMobs(const std::vector<protocol::MobSend>& mobSends);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
virtual void HandlePacket(protocol::SelectTeamPacket* packet);
|
||||
virtual void HandlePacket(protocol::DisconnectPacket* packet);
|
||||
virtual void HandlePacket(protocol::PlaceTowerPacket* packet);
|
||||
virtual void HandlePacket(protocol::SendMobsPacket* packet);
|
||||
|
||||
std::uint8_t getID() const { return m_ID; }
|
||||
const game::Player* getPlayer() const { return m_Player; }
|
||||
|
||||
@@ -36,6 +36,7 @@ public:
|
||||
virtual void HandlePacket(PlaceTowerPacket* packet) {}
|
||||
virtual void HandlePacket(WorldAddTowerPacket* packet) {}
|
||||
virtual void HandlePacket(WorldRemoveTowerPacket* packet) {}
|
||||
virtual void HandlePacket(SendMobsPacket* packet) {}
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
|
||||
@@ -28,6 +28,7 @@ enum class PacketType : std::uint8_t {
|
||||
UpdatePlayerTeam,
|
||||
ServerTps,
|
||||
SpawnMob,
|
||||
SendMobs,
|
||||
PlaceTower,
|
||||
WorldAddTower,
|
||||
WorldRemoveTower,
|
||||
@@ -369,6 +370,29 @@ public:
|
||||
virtual PacketType getType() const { return PacketType::ServerTps; }
|
||||
};
|
||||
|
||||
struct MobSend { // represents a mob send
|
||||
game::MobType mobType;
|
||||
game::MobLevel mobLevel;
|
||||
std::uint8_t mobCount; // the max is 12
|
||||
};
|
||||
|
||||
class SendMobsPacket : public Packet {
|
||||
private:
|
||||
std::vector<MobSend> m_MobSends;
|
||||
public:
|
||||
SendMobsPacket() {}
|
||||
SendMobsPacket(const std::vector<MobSend>& mobSends) : m_MobSends(mobSends) {}
|
||||
virtual ~SendMobsPacket() {}
|
||||
|
||||
virtual DataBuffer Serialize() const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler);
|
||||
|
||||
const std::vector<MobSend>& getMobSends() const { return m_MobSends; }
|
||||
|
||||
virtual PacketType getType() const { return PacketType::SendMobs; }
|
||||
};
|
||||
|
||||
class SpawnMobPacket : public Packet {
|
||||
private:
|
||||
game::MobID m_MobID;
|
||||
|
||||
27
include/render/gui/GuiManager.h
Normal file
27
include/render/gui/GuiManager.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace td {
|
||||
namespace gui {
|
||||
|
||||
class GuiManager {
|
||||
private:
|
||||
std::vector<std::shared_ptr<GuiWidget>> m_Widgets;
|
||||
public:
|
||||
void renderWidgets(){
|
||||
for(auto widget : m_Widgets){
|
||||
widget->render();
|
||||
}
|
||||
}
|
||||
|
||||
void addWidgets(const std::shared_ptr<GuiWidget>& widget){
|
||||
m_Widgets.push_back(std::move(widget));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace td
|
||||
25
include/render/gui/GuiWidget.h
Normal file
25
include/render/gui/GuiWidget.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
namespace td {
|
||||
|
||||
namespace client {
|
||||
class Client;
|
||||
} // namespace client
|
||||
|
||||
namespace gui {
|
||||
|
||||
class GuiWidget {
|
||||
protected:
|
||||
client::Client* m_Client;
|
||||
public:
|
||||
GuiWidget(client::Client* client) {
|
||||
m_Client = client;
|
||||
}
|
||||
|
||||
client::Client* getClient() { return m_Client; }
|
||||
|
||||
virtual void render() = 0;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace td
|
||||
26
include/render/gui/SummonMenu.h
Normal file
26
include/render/gui/SummonMenu.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "GuiWidget.h"
|
||||
|
||||
#include <array>
|
||||
#include "game/Mobs.h"
|
||||
|
||||
namespace td {
|
||||
namespace gui {
|
||||
|
||||
class SummonMenu : public GuiWidget{
|
||||
private:
|
||||
bool m_MenuOpened;
|
||||
int m_ImageWidth = 100;
|
||||
static constexpr int m_MobTypeCount = static_cast<std::size_t>(td::game::MobType::MOB_COUNT);
|
||||
std::array<int, static_cast<std::size_t>(m_MobTypeCount)> m_Values;
|
||||
public:
|
||||
SummonMenu(client::Client* client);
|
||||
|
||||
virtual void render();
|
||||
private:
|
||||
void setSummonMax(int valueIndex);
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace td
|
||||
@@ -253,8 +253,16 @@ MobPtr MobFactory::createMob(MobID id, MobType type, std::uint8_t level, PlayerI
|
||||
using MobCreator = std::function<std::shared_ptr<Mob>(MobID, std::uint8_t, PlayerID)>;
|
||||
|
||||
static std::map<MobType, MobCreator> mobFactory = {
|
||||
{MobType::Zombie, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Zombie>(id, level, sender);} },
|
||||
{MobType::Spider, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Spider>(id, level, sender);} },
|
||||
{MobType::Zombie, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Zombie>(id, level, sender);} },
|
||||
{MobType::Spider, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Spider>(id, level, sender);} },
|
||||
{MobType::Skeleton, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Skeleton>(id, level, sender);} },
|
||||
{MobType::Pigman, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<PigMan>(id, level, sender);} },
|
||||
{MobType::Creeper, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Creeper>(id, level, sender);} },
|
||||
{MobType::Silverfish, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Silverfish>(id, level, sender);} },
|
||||
{MobType::Blaze, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Blaze>(id, level, sender);} },
|
||||
{MobType::Witch, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Witch>(id, level, sender);} },
|
||||
{MobType::Slime, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Slime>(id, level, sender);} },
|
||||
{MobType::Giant, [](MobID id, std::uint8_t level, PlayerID sender) -> MobPtr {return std::make_shared<Giant>(id, level, sender);} },
|
||||
};
|
||||
|
||||
return mobFactory[type](id, level, sender);
|
||||
|
||||
@@ -49,5 +49,10 @@ void Client::render() {
|
||||
m_Game.renderWorld();
|
||||
}
|
||||
|
||||
void Client::sendMobs(const std::vector<protocol::MobSend>& mobSends){
|
||||
protocol::SendMobsPacket packet(mobSends);
|
||||
m_Connexion.sendPacket(&packet);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
} // namespace td
|
||||
|
||||
@@ -39,6 +39,7 @@ void ServerConnexion::registerHandlers() {
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SelectTeam, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::Disconnect, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlaceTower, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::SendMobs, this);
|
||||
}
|
||||
|
||||
bool ServerConnexion::updateSocket() {
|
||||
@@ -147,6 +148,7 @@ void ServerConnexion::HandlePacket(protocol::PlaceTowerPacket* packet) {
|
||||
game::TowerType towerType = packet->getTowerType();
|
||||
const game::TowerInfo& towerInfo = game::getTowerInfo(towerType);
|
||||
server::ServerWorld* world = m_Server->getGame().getServerWorld();
|
||||
|
||||
if (towerInfo.isBigTower()) {
|
||||
if (!world->CanPlaceBigTower({ packet->getTowerX(), packet->getTowerY() }, m_ID))
|
||||
return;
|
||||
@@ -161,6 +163,16 @@ void ServerConnexion::HandlePacket(protocol::PlaceTowerPacket* packet) {
|
||||
m_Server->broadcastPacket(&addTowerPacket);
|
||||
}
|
||||
|
||||
void ServerConnexion::HandlePacket(protocol::SendMobsPacket* packet) {
|
||||
const std::vector<protocol::MobSend>& mobSent = packet->getMobSends();
|
||||
|
||||
//TODO: verify the packet
|
||||
|
||||
for(protocol::MobSend mobSend : mobSent){
|
||||
m_Server->getGame().getServerWorld()->spawnMobs(mobSend.mobType, mobSend.mobLevel, m_ID, mobSend.mobCount);
|
||||
}
|
||||
}
|
||||
|
||||
ServerConnexion::~ServerConnexion() {
|
||||
if (GetDispatcher() != nullptr)
|
||||
GetDispatcher()->UnregisterHandler(this);
|
||||
|
||||
@@ -29,6 +29,7 @@ static std::map<PacketType, PacketCreator> packets = {
|
||||
{PacketType::PlaceTower, []() -> Packet* {return new PlaceTowerPacket(); } },
|
||||
{PacketType::WorldAddTower, []() -> Packet* {return new WorldAddTowerPacket(); } },
|
||||
{PacketType::WorldRemoveTower, []() -> Packet* {return new WorldRemoveTowerPacket(); } },
|
||||
{PacketType::SendMobs, []() -> Packet* {return new SendMobsPacket(); } },
|
||||
};
|
||||
|
||||
Packet* createPacket(PacketType type, DataBuffer& buffer) {
|
||||
|
||||
@@ -495,6 +495,25 @@ void WorldRemoveTowerPacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_TowerID;
|
||||
}
|
||||
|
||||
DataBuffer SendMobsPacket::Serialize() const {
|
||||
DataBuffer data;
|
||||
data << getID() << static_cast<std::uint8_t>(m_MobSends.size());
|
||||
for(const MobSend& mobSend : m_MobSends){
|
||||
data << mobSend;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void SendMobsPacket::Deserialize(DataBuffer& data) {
|
||||
std::uint8_t mobSendCount;
|
||||
data >> mobSendCount;
|
||||
protocol::MobSend mobSend;
|
||||
for(int i = 0; i < mobSendCount; i++){
|
||||
data >> mobSend;
|
||||
m_MobSends.push_back(mobSend);
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_DISPATCH_CLASS(PlayerLoginPacket);
|
||||
REGISTER_DISPATCH_CLASS(WorldBeginDataPacket);
|
||||
REGISTER_DISPATCH_CLASS(WorldDataPacket);
|
||||
@@ -515,6 +534,7 @@ REGISTER_DISPATCH_CLASS(SpawnMobPacket);
|
||||
REGISTER_DISPATCH_CLASS(PlaceTowerPacket);
|
||||
REGISTER_DISPATCH_CLASS(WorldAddTowerPacket);
|
||||
REGISTER_DISPATCH_CLASS(WorldRemoveTowerPacket);
|
||||
REGISTER_DISPATCH_CLASS(SendMobsPacket);
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace td
|
||||
82
src/render/gui/SummonMenu.cpp
Normal file
82
src/render/gui/SummonMenu.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "render/gui/SummonMenu.h"
|
||||
#include "game/client/Client.h"
|
||||
#include "render/gui/imgui/imgui.h"
|
||||
|
||||
namespace td {
|
||||
namespace gui {
|
||||
|
||||
SummonMenu::SummonMenu(client::Client* client) : GuiWidget(client), m_MenuOpened(true){
|
||||
m_Values.fill(0);
|
||||
}
|
||||
|
||||
void SummonMenu::render(){
|
||||
if (m_MenuOpened) {
|
||||
ImGui::Begin("Summon", &m_MenuOpened);
|
||||
ImTextureID my_tex_id = ImGui::GetIO().Fonts->TexID;
|
||||
for (int i = 0; i < m_MobTypeCount / 2; i++) {
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
ImGui::Image(my_tex_id, ImVec2(100, 100));
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::PushItemWidth(m_ImageWidth);
|
||||
for (int i = 0; i < m_MobTypeCount / 2; i++) {
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::InputInt("", m_Values.data() + i, 1, 10)) {
|
||||
setSummonMax(i);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::Separator();
|
||||
for (int i = m_MobTypeCount / 2; i < m_MobTypeCount; i++) {
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
ImGui::Image(my_tex_id, ImVec2(100, 100));
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::PushItemWidth(m_ImageWidth);
|
||||
for (int i = m_MobTypeCount / 2; i < m_MobTypeCount; i++) {
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::InputInt("", m_Values.data() + i, 1, m_MobTypeCount)) {
|
||||
setSummonMax(i);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
if (ImGui::Button("Send")) {
|
||||
std::vector<protocol::MobSend> mobSent;
|
||||
protocol::MobSend mobSend;
|
||||
for(int i = 0; i < m_MobTypeCount; i++){
|
||||
if(m_Values[i] != 0){
|
||||
mobSend.mobCount = m_Values[i];
|
||||
mobSend.mobLevel = 1; // TODO: add mob levels
|
||||
mobSend.mobType = td::game::MobType(i);
|
||||
mobSent.push_back(mobSend);
|
||||
}
|
||||
}
|
||||
m_Client->sendMobs(mobSent);
|
||||
m_Values.fill(0);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void SummonMenu::setSummonMax(int valueIndex){
|
||||
int& value = m_Values[valueIndex];
|
||||
value = std::max(0, value);
|
||||
value = std::min(12, value);
|
||||
int total = 0;
|
||||
for (std::size_t i = 0; i < m_Values.size(); i++) {
|
||||
total += m_Values[i];
|
||||
}
|
||||
if (total == 13) // if the total is greater than the maximum, we substract the value
|
||||
value--;
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace td
|
||||
@@ -18,6 +18,9 @@
|
||||
#include "render/Renderer.h"
|
||||
#include "network/Network.h"
|
||||
|
||||
#include "render/gui/GuiManager.h"
|
||||
#include "render/gui/SummonMenu.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
@@ -28,9 +31,14 @@ static SDL_GLContext gl_context;
|
||||
static std::unique_ptr<td::client::Client> client;
|
||||
static std::thread* serverThread;
|
||||
static td::render::Renderer* renderer;
|
||||
static td::gui::GuiManager guiManager;
|
||||
|
||||
bool serverShouldStop = false;
|
||||
|
||||
void initWidgets(){
|
||||
guiManager.addWidgets(std::make_shared<td::gui::SummonMenu>(client.get()));
|
||||
}
|
||||
|
||||
void init(SDL_Window* sdl_window, SDL_GLContext sdlContext, td::render::Renderer* render) {
|
||||
window = sdl_window;
|
||||
gl_context = sdlContext;
|
||||
@@ -44,6 +52,7 @@ void init(SDL_Window* sdl_window, SDL_GLContext sdlContext, td::render::Renderer
|
||||
ImGui::GetIO().Fonts->AddFontDefault(&c);
|
||||
renderer = render;
|
||||
client = std::make_unique<td::client::Client>(render);
|
||||
initWidgets();
|
||||
}
|
||||
|
||||
void beginFrame() {
|
||||
@@ -237,53 +246,7 @@ void capValues(int* values, int& value) {
|
||||
}
|
||||
|
||||
void renderSummonMenu() {
|
||||
static bool menu_open = true;
|
||||
if (menu_open) {
|
||||
|
||||
ImGui::Begin("Summon", &menu_open);
|
||||
static int width = 100;
|
||||
static int values[16]{ 0 };
|
||||
ImTextureID my_tex_id = ImGui::GetIO().Fonts->TexID;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
ImGui::Image(my_tex_id, ImVec2(100, 100));
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::PushItemWidth(width);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::InputInt("", values + i, 1, 10)) {
|
||||
capValues(values, values[i]);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::Separator();
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
ImGui::Image(my_tex_id, ImVec2(100, 100));
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::PushItemWidth(width);
|
||||
for (int i = 8; i < 16; i++) {
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::InputInt("", values + i, 1, 10)) {
|
||||
capValues(values, values[i]);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopItemWidth();
|
||||
if (ImGui::Button("Send")) {
|
||||
std::cout << "Sending Troops ...\n";
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void renderGame() {
|
||||
@@ -303,7 +266,7 @@ void renderGame() {
|
||||
showTPS();
|
||||
showStats();
|
||||
showPlayers();
|
||||
renderSummonMenu();
|
||||
guiManager.renderWidgets();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user