4 Commits

Author SHA1 Message Date
43f21ffd44 chore: bump verssion to alpha-0.1.0 2021-12-12 13:33:12 +01:00
24617c539f feat: add castle tooltip 2021-12-12 13:32:39 +01:00
4611a198c9 fix: add mob spawn border 2021-12-12 13:31:01 +01:00
d40ffe8f6c refactor: removed unused include 2021-12-12 11:36:56 +01:00
14 changed files with 138 additions and 19 deletions

View File

@@ -19,7 +19,7 @@ typedef std::map<std::uint8_t, Player> PlayerList;
class Game { class Game {
protected: protected:
World* m_World; World* m_World;
std::array<Team, 2> m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} }; TeamList m_Teams = { Team{TeamColor::Red}, Team{TeamColor::Blue} };
GameState m_GameState = GameState::Lobby; GameState m_GameState = GameState::Lobby;
PlayerList m_Players; PlayerList m_Players;
public: public:
@@ -49,6 +49,8 @@ public:
const Player* getPlayerById(PlayerID id) const; const Player* getPlayerById(PlayerID id) const;
Player* getPlayerById(PlayerID id); Player* getPlayerById(PlayerID id);
const TeamList& getTeams() const { return m_Teams; }
}; };
} // namespace game } // namespace game

View File

@@ -23,7 +23,7 @@ class Spawn : public utils::shape::Rectangle {
private: private:
Direction m_Direction; Direction m_Direction;
public: public:
Spawn(){ Spawn() {
setWidth(5); setWidth(5);
setHeight(5); setHeight(5);
} }
@@ -33,19 +33,34 @@ public:
void setDirection(Direction direction) { m_Direction = direction; } void setDirection(Direction direction) { m_Direction = direction; }
}; };
struct TeamCastle : public utils::shape::Rectangle{ class Team;
class TeamCastle : public utils::shape::Rectangle {
private: private:
const Team* m_Team;
float m_Life; float m_Life;
public: public:
TeamCastle() : m_Life(1000) { static constexpr int CastleMaxLife = 1000;
TeamCastle(const Team* team) : m_Team(team), m_Life(CastleMaxLife) {
setWidth(5); setWidth(5);
setHeight(5); setHeight(5);
} }
TeamCastle() : TeamCastle(nullptr) {}
float getLife() const { return m_Life; } float getLife() const { return m_Life; }
const Team* getTeam() const { return m_Team; }
void setTeam(const Team* team) { m_Team = team; }
void setLife(float life) { m_Life = life; } void setLife(float life) { m_Life = life; }
void damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); } void damage(float damage) { m_Life = std::max(0.0f, m_Life - damage); }
void setShape(utils::shape::Rectangle rect) {
setCenter(rect.getCenter());
setSize(rect.getSize());
}
}; };
class Team { class Team {
@@ -71,5 +86,7 @@ public:
std::uint8_t getPlayerCount() const; std::uint8_t getPlayerCount() const;
}; };
typedef std::array<Team, 2> TeamList;
} // namespace game } // namespace game
} // namespace td } // namespace td

View File

@@ -205,6 +205,8 @@ public:
Team& getTeam(TeamColor team); Team& getTeam(TeamColor team);
const Team& getTeam(TeamColor team) const; const Team& getTeam(TeamColor team) const;
const TeamList& getTeams() const;
const TowerList& getTowers() const { return m_Towers; }; const TowerList& getTowers() const { return m_Towers; };
TowerPtr getTowerById(TowerID tower); TowerPtr getTowerById(TowerID tower);

View File

@@ -14,6 +14,8 @@ private:
game::TowerID m_CurrentTowerID; game::TowerID m_CurrentTowerID;
Server* m_Server; Server* m_Server;
public: public:
static constexpr float MobSpawnBorder = 0.01f;
ServerWorld(Server* server, ServerGame* game); ServerWorld(Server* server, ServerGame* game);
void spawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count); void spawnMobs(game::MobType type, std::uint8_t level, game::PlayerID sender, std::uint8_t count);

View File

@@ -47,6 +47,9 @@ public:
void setCenterY(float y) { m_Center.setY(y); } void setCenterY(float y) { m_Center.setY(y); }
void setSize(float width, float height) { setWidth(width); setHeight(height); } void setSize(float width, float height) { setWidth(width); setHeight(height); }
void setSize(Point size) { setSize(size.getX(), size.getY()); }
Point getSize() { return { m_Width, m_Height }; }
void setWidth(float width) { m_Width = width; } void setWidth(float width) { m_Width = width; }
void setHeight(float height) { m_Height = height; } void setHeight(float height) { m_Height = height; }

View File

@@ -7,6 +7,7 @@
#include "render/gui/TowerPlacePopup.h" #include "render/gui/TowerPlacePopup.h"
#include "render/gui/MobTooltip.h" #include "render/gui/MobTooltip.h"
#include "render/gui/CastleTooltip.h"
#include "render/gui/imgui/imgui.h" #include "render/gui/imgui/imgui.h"
@@ -40,6 +41,7 @@ private:
std::unique_ptr<gui::TowerPlacePopup> m_TowerPlacePopup; std::unique_ptr<gui::TowerPlacePopup> m_TowerPlacePopup;
std::unique_ptr<gui::MobTooltip> m_MobTooltip; std::unique_ptr<gui::MobTooltip> m_MobTooltip;
std::unique_ptr<gui::CastleTooltip> m_CastleTooltip;
public: public:
WorldRenderer(game::World* world, client::ClientGame* client); WorldRenderer(game::World* world, client::ClientGame* client);
~WorldRenderer(); ~WorldRenderer();
@@ -69,8 +71,11 @@ private:
void renderPopups(); void renderPopups();
void renderTowerUpgradePopup(); void renderTowerUpgradePopup();
void renderMobTooltip() const; void renderMobTooltip() const;
void renderCastleTooltip() const;
void detectClick(); void detectClick();
void detectMobHovering() const; void detectMobHovering() const;
void detectCastleHovering() const;
void renderTooltips() const;
void removeTower(); void removeTower();
glm::vec2 getCursorWorldPos() const; glm::vec2 getCursorWorldPos() const;
glm::vec2 getClickWorldPos() const; glm::vec2 getClickWorldPos() const;

View File

@@ -0,0 +1,27 @@
#pragma once
#include "GuiWidget.h"
namespace td {
namespace game {
class TeamCastle;
} // namespace game
namespace gui {
class CastleTooltip : public GuiWidget {
private:
const game::TeamCastle* m_Castle;
public:
CastleTooltip(client::Client* client);
virtual void render();
void setCastle(const game::TeamCastle* castle) { m_Castle = castle; }
};
} // namespace gui
} // namespace td

View File

@@ -2,9 +2,7 @@
#include "misc/DataBuffer.h" #include "misc/DataBuffer.h"
#include <ctime> #define TD_VERSION "alpha-0.1.0"
#define TD_VERSION "alpha-0.0.5"
namespace td { namespace td {
namespace utils { namespace utils {

View File

@@ -5,7 +5,7 @@
namespace td { namespace td {
namespace game { namespace game {
Team::Team(TeamColor color) : m_Color(color) {} Team::Team(TeamColor color) : m_Color(color), m_TeamCastle(this) {}
void Team::addPlayer(Player* newPlayer) { void Team::addPlayer(Player* newPlayer) {
m_Players.push_back(newPlayer); m_Players.push_back(newPlayer);

View File

@@ -44,7 +44,10 @@ bool World::loadMap(const protocol::WorldBeginDataPacket* worldHeader) {
m_SpawnColorPalette = worldHeader->getSpawnPalette(); m_SpawnColorPalette = worldHeader->getSpawnPalette();
getRedTeam().getCastle() = worldHeader->getRedCastle(); getRedTeam().getCastle() = worldHeader->getRedCastle();
getRedTeam().getCastle().setTeam(&getRedTeam());
getBlueTeam().getCastle() = worldHeader->getBlueCastle(); getBlueTeam().getCastle() = worldHeader->getBlueCastle();
getBlueTeam().getCastle().setTeam(&getBlueTeam());
m_TilePalette = worldHeader->getTilePalette(); m_TilePalette = worldHeader->getTilePalette();
@@ -328,5 +331,9 @@ const Player* World::getPlayerById(PlayerID id) const {
return m_Game->getPlayerById(id); return m_Game->getPlayerById(id);
} }
const TeamList& World::getTeams() const {
return m_Game->getTeams();
}
} // namespace game } // namespace game
} // namespace td } // namespace td

View File

@@ -37,8 +37,8 @@ void ServerWorld::spawnMobs(game::MobType type, std::uint8_t level, game::Player
float minSpawnY = spawnCenterY - spawnHeight / 2.0f + mobSize.y / 2.0f; float minSpawnY = spawnCenterY - spawnHeight / 2.0f + mobSize.y / 2.0f;
float maxSpawnY = spawnCenterY + spawnHeight / 2.0f - mobSize.y / 2.0f; float maxSpawnY = spawnCenterY + spawnHeight / 2.0f - mobSize.y / 2.0f;
float mobX = utils::getRandomReal<float>(minSpawnX, maxSpawnX); float mobX = utils::getRandomReal<float>(minSpawnX + MobSpawnBorder, maxSpawnX - MobSpawnBorder);
float mobY = utils::getRandomReal<float>(minSpawnY, maxSpawnY); float mobY = utils::getRandomReal<float>(minSpawnY + MobSpawnBorder, maxSpawnY - MobSpawnBorder);
spawnMobAt(m_CurrentMobID, type, level, sender, mobX, mobY, enemyMobSpawn->getDirection()); spawnMobAt(m_CurrentMobID, type, level, sender, mobX, mobY, enemyMobSpawn->getDirection());

View File

@@ -94,11 +94,11 @@ DataBuffer WorldBeginDataPacket::SerializeCustom() const {
const game::Spawn& redSpawn = m_Header.m_RedSpawn, blueSpawn = m_Header.m_BlueSpawn; const game::Spawn& redSpawn = m_Header.m_RedSpawn, blueSpawn = m_Header.m_BlueSpawn;
const game::TeamCastle& redCastle = m_Header.m_RedCastle, blueCastle = m_Header.m_BlueCastle; const game::TeamCastle& redCastle = m_Header.m_RedCastle, blueCastle = m_Header.m_BlueCastle;
data << redSpawn << redCastle; data << redSpawn << static_cast<utils::shape::Rectangle>(redCastle);
data << blueSpawn << blueCastle; data << blueSpawn << static_cast<utils::shape::Rectangle>(blueCastle);
// tile palette // tile palette
data << m_Header.m_TilePalette.size(); data << static_cast<std::uint64_t>(m_Header.m_TilePalette.size());
for (game::TilePtr tile : m_Header.m_TilePalette) { for (game::TilePtr tile : m_Header.m_TilePalette) {
data << tile; data << tile;
@@ -126,11 +126,11 @@ DataBuffer WorldBeginDataPacket::Serialize() const {
const game::Spawn& redSpawn = m_Header.m_World->getRedTeam().getSpawn(), blueSpawn = m_Header.m_World->getBlueTeam().getSpawn(); const game::Spawn& redSpawn = m_Header.m_World->getRedTeam().getSpawn(), blueSpawn = m_Header.m_World->getBlueTeam().getSpawn();
const game::TeamCastle& redCastle = m_Header.m_World->getRedTeam().getCastle(), blueCastle = m_Header.m_World->getBlueTeam().getCastle(); const game::TeamCastle& redCastle = m_Header.m_World->getRedTeam().getCastle(), blueCastle = m_Header.m_World->getBlueTeam().getCastle();
data << redSpawn << redCastle; data << redSpawn << static_cast<utils::shape::Rectangle>(redCastle);
data << blueSpawn << blueCastle; data << blueSpawn << static_cast<utils::shape::Rectangle>(blueCastle);
// tile palette // tile palette
data << m_Header.m_World->getTilePalette().size(); data << static_cast<std::uint64_t>(m_Header.m_World->getTilePalette().size());
for (game::TilePtr tile : m_Header.m_World->getTilePalette()) { for (game::TilePtr tile : m_Header.m_World->getTilePalette()) {
data << tile; data << tile;
@@ -155,8 +155,13 @@ void WorldBeginDataPacket::Deserialize(DataBuffer& data) {
data.SetReadOffset(data.GetReadOffset() + decoPalletteSizeByte); data.SetReadOffset(data.GetReadOffset() + decoPalletteSizeByte);
data >> m_Header.m_RedSpawn >> m_Header.m_RedCastle; utils::shape::Rectangle redCastle, blueCastle;
data >> m_Header.m_BlueSpawn >> m_Header.m_BlueCastle;
data >> m_Header.m_RedSpawn >> redCastle;
data >> m_Header.m_BlueSpawn >> blueCastle;
m_Header.m_RedCastle.setShape(redCastle);
m_Header.m_BlueCastle.setShape(blueCastle);
std::uint64_t tilePaletteSize; std::uint64_t tilePaletteSize;
data >> tilePaletteSize; data >> tilePaletteSize;

View File

@@ -37,6 +37,7 @@ WorldRenderer::WorldRenderer(game::World* world, client::ClientGame* client) : m
m_Renderer->setCamMovement({}); m_Renderer->setCamMovement({});
m_TowerPlacePopup = std::make_unique<gui::TowerPlacePopup>(m_Client->getClient()); m_TowerPlacePopup = std::make_unique<gui::TowerPlacePopup>(m_Client->getClient());
m_MobTooltip = std::make_unique<gui::MobTooltip>(m_Client->getClient()); m_MobTooltip = std::make_unique<gui::MobTooltip>(m_Client->getClient());
m_CastleTooltip = std::make_unique<gui::CastleTooltip>(m_Client->getClient());
m_Client->getWorld().getWorldNotifier().bindListener(this); m_Client->getWorld().getWorldNotifier().bindListener(this);
} }
@@ -119,7 +120,7 @@ void WorldRenderer::render() {
renderMobs(); renderMobs();
renderTowers(); renderTowers();
renderTileSelect(); renderTileSelect();
renderMobTooltip(); renderTooltips();
renderPopups(); renderPopups();
detectClick(); detectClick();
} }
@@ -128,6 +129,11 @@ WorldRenderer::~WorldRenderer() {
} }
void WorldRenderer::renderTooltips() const {
renderMobTooltip();
renderCastleTooltip();
}
void WorldRenderer::moveCam(float relativeX, float relativeY, float aspectRatio) { void WorldRenderer::moveCam(float relativeX, float relativeY, float aspectRatio) {
if (m_WorldVao == nullptr) if (m_WorldVao == nullptr)
return; return;
@@ -245,6 +251,13 @@ void WorldRenderer::renderMobTooltip() const {
m_MobTooltip->render(); m_MobTooltip->render();
} }
void WorldRenderer::renderCastleTooltip() const {
if (ImGui::IsAnyItemHovered()) return;
detectCastleHovering();
m_CastleTooltip->render();
}
void WorldRenderer::detectMobHovering() const { void WorldRenderer::detectMobHovering() const {
glm::vec2 cursorWorldPos = getCursorWorldPos(); glm::vec2 cursorWorldPos = getCursorWorldPos();
for (game::MobPtr mob : m_World->getMobList()) { for (game::MobPtr mob : m_World->getMobList()) {
@@ -256,6 +269,17 @@ void WorldRenderer::detectMobHovering() const {
m_MobTooltip->setMob(nullptr); m_MobTooltip->setMob(nullptr);
} }
void WorldRenderer::detectCastleHovering() const {
glm::vec2 cursorWorldPos = getCursorWorldPos();
for (const game::Team& team : m_World->getTeams()) {
if (team.getCastle().collidesWith({ cursorWorldPos.x, cursorWorldPos.y })) {
m_CastleTooltip->setCastle(&team.getCastle());
return;
}
}
m_CastleTooltip->setCastle(nullptr);
}
void WorldRenderer::OnTowerAdd(game::TowerPtr tower) { void WorldRenderer::OnTowerAdd(game::TowerPtr tower) {
WorldLoader::RenderData renderData = WorldLoader::loadTowerModel(tower); WorldLoader::RenderData renderData = WorldLoader::loadTowerModel(tower);
m_TowersCache.addData(tower->getID(), renderData.positions, renderData.colors); m_TowersCache.addData(tower->getID(), renderData.positions, renderData.colors);

View File

@@ -0,0 +1,27 @@
#include "render/gui/CastleTooltip.h"
#include "render/gui/imgui/imgui.h"
#include "render/WorldRenderer.h"
#include "game/client/Client.h"
namespace td {
namespace gui {
CastleTooltip::CastleTooltip(client::Client* client) : GuiWidget(client) {
}
void CastleTooltip::render() {
if (m_Castle == nullptr) return;
ImGui::BeginTooltip();
ImGui::PushStyleColor(ImGuiCol_Text, render::WorldRenderer::getImGuiTeamColor(m_Castle->getTeam()->getColor()));
ImGui::Text("Castle : ");
ImGui::PopStyleColor();
ImGui::Text("\tCastle HP : %i/%i", static_cast<int>(m_Castle->getLife()), game::TeamCastle::CastleMaxLife);
ImGui::EndTooltip();
}
} // namespace gui
} // namespace td