Compare commits
2 Commits
main
...
86275a38a6
| Author | SHA1 | Date | |
|---|---|---|---|
| 86275a38a6 | |||
| 48cf4b350c |
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "Player.h"
|
||||
#include "blitz/misc/Time.h"
|
||||
#include <map>
|
||||
|
||||
namespace blitz {
|
||||
@@ -8,12 +9,22 @@ namespace game {
|
||||
|
||||
typedef std::map<PlayerID, Player> PlayerMap;
|
||||
|
||||
enum GameState : std::uint8_t {
|
||||
gsNone = 0,
|
||||
gsWaiting,
|
||||
gsPreparing,
|
||||
gsGame,
|
||||
gsEnd,
|
||||
};
|
||||
|
||||
class Game {
|
||||
private:
|
||||
protected:
|
||||
PlayerMap m_Players;
|
||||
GameState m_GameState;
|
||||
utils::Timer m_GameTimer;
|
||||
|
||||
public:
|
||||
Game() {}
|
||||
Game() : m_GameState(gsNone) {}
|
||||
|
||||
virtual void Tick(std::uint64_t delta) = 0;
|
||||
|
||||
@@ -28,8 +39,16 @@ class Game {
|
||||
return m_Players;
|
||||
}
|
||||
|
||||
GameState GetGameState() const {
|
||||
return m_GameState;
|
||||
}
|
||||
|
||||
virtual void AddPlayer(PlayerID player, const std::string& name);
|
||||
virtual void RemovePlayer(PlayerID player);
|
||||
|
||||
std::uint64_t GetGameStateRemainingTime() const {
|
||||
return m_GameTimer.GetTimeRemaining();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -59,6 +59,15 @@ class Timer {
|
||||
bool Update(std::uint64_t delta);
|
||||
|
||||
void Reset();
|
||||
// void ResetSoft(); // don't trigger the timer
|
||||
|
||||
std::uint64_t GetTimeRemaining() const {
|
||||
return m_Interval - m_InternalTime;
|
||||
}
|
||||
|
||||
std::uint64_t GetTimeElapsed() const {
|
||||
return m_InternalTime;
|
||||
}
|
||||
|
||||
void SetInterval(std::uint64_t newInterval) {
|
||||
m_Interval = newInterval;
|
||||
|
||||
@@ -32,6 +32,7 @@ class PacketHandler {
|
||||
virtual void HandlePacket(const PlayerShootPacket* packet) {}
|
||||
virtual void HandlePacket(const PlayerStatsPacket* packet) {}
|
||||
virtual void HandlePacket(const ServerTpsPacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateGameStatePacket* packet) {}
|
||||
virtual void HandlePacket(const UpdateHealthPacket* packet) {}
|
||||
};
|
||||
|
||||
|
||||
@@ -10,4 +10,5 @@
|
||||
#include "packets/PlayerShootPacket.h"
|
||||
#include "packets/PlayerStatsPacket.h"
|
||||
#include "packets/ServerTpsPacket.h"
|
||||
#include "packets/UpdateGameStatePacket.h"
|
||||
#include "packets/UpdateHealthPacket.h"
|
||||
|
||||
@@ -15,6 +15,7 @@ class PlayerPositionAndRotationPacket;
|
||||
class PlayerShootPacket;
|
||||
class PlayerStatsPacket;
|
||||
class ServerTpsPacket;
|
||||
class UpdateGameStatePacket;
|
||||
class UpdateHealthPacket;
|
||||
|
||||
} // namespace protocol
|
||||
|
||||
@@ -24,12 +24,13 @@ enum class PacketType : std::uint8_t {
|
||||
|
||||
// client <-- server
|
||||
|
||||
ConnexionInfo, /**< Corresponds to ConnexionInfoPacket */
|
||||
PlayerJoin, /**< Corresponds to PlayerJoinPacket */
|
||||
PlayerLeave, /**< Corresponds to PlayerLeavePacket */
|
||||
PlayerList, /**< Corresponds to PlayerListPacket */
|
||||
PlayerStats, /**< Corresponds to PlayerStatsPacket */
|
||||
ServerTps, /**< Corresponds to ServerTpsPacket */
|
||||
ConnexionInfo, /**< Corresponds to ConnexionInfoPacket */
|
||||
PlayerJoin, /**< Corresponds to PlayerJoinPacket */
|
||||
PlayerLeave, /**< Corresponds to PlayerLeavePacket */
|
||||
PlayerList, /**< Corresponds to PlayerListPacket */
|
||||
PlayerStats, /**< Corresponds to PlayerStatsPacket */
|
||||
ServerTps, /**< Corresponds to ServerTpsPacket */
|
||||
UpdateGameState, /**< Corresponds to UpdateGameStatePacket */
|
||||
|
||||
// client <--> server
|
||||
|
||||
|
||||
38
include/blitz/protocol/packets/UpdateGameStatePacket.h
Normal file
38
include/blitz/protocol/packets/UpdateGameStatePacket.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/game/Game.h"
|
||||
#include "blitz/protocol/Protocol.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace protocol {
|
||||
|
||||
class UpdateGameStatePacket : public Packet {
|
||||
private:
|
||||
game::GameState m_GameState;
|
||||
std::uint64_t m_TimeRemaining;
|
||||
|
||||
public:
|
||||
UpdateGameStatePacket() {}
|
||||
UpdateGameStatePacket(game::GameState a_GameState, std::uint64_t a_TimeRemaining = 0) :
|
||||
m_GameState(a_GameState), m_TimeRemaining(a_TimeRemaining) {}
|
||||
virtual ~UpdateGameStatePacket() {}
|
||||
|
||||
virtual DataBuffer Serialize(bool packetID = true) const;
|
||||
virtual void Deserialize(DataBuffer& data);
|
||||
virtual void Dispatch(PacketHandler* handler) const;
|
||||
|
||||
game::GameState GetGameState() const {
|
||||
return m_GameState;
|
||||
}
|
||||
|
||||
std::uint64_t GetTimeRemaining() const {
|
||||
return m_TimeRemaining;
|
||||
}
|
||||
|
||||
virtual PacketType GetType() const {
|
||||
return PacketType::UpdateGameState;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace blitz
|
||||
@@ -26,6 +26,7 @@ class ClientGame : public game::Game, public protocol::PacketHandler {
|
||||
virtual void HandlePacket(const protocol::PlayerShootPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateHealthPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::PlayerStatsPacket* packet) override;
|
||||
virtual void HandlePacket(const protocol::UpdateGameStatePacket* packet) override;
|
||||
|
||||
private:
|
||||
void RegisterHandlers();
|
||||
|
||||
@@ -10,15 +10,16 @@ class Client;
|
||||
namespace gui {
|
||||
class Hud : public GuiWidget {
|
||||
private:
|
||||
/* data */
|
||||
|
||||
void Draw(const char* title, bool* p_open);
|
||||
unsigned int m_GunTexture;
|
||||
unsigned int m_JP;
|
||||
unsigned int m_JPTexture;
|
||||
|
||||
public:
|
||||
Hud(GuiWidget* parent, Client* client);
|
||||
virtual void Render() override;
|
||||
|
||||
private:
|
||||
void Draw(const char* title, bool* p_open);
|
||||
void RenderTime();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -57,6 +57,7 @@ class ServerConnexion : public network::Connexion {
|
||||
void InitConnection();
|
||||
void InitPlayerChatColor();
|
||||
void SendPlayers();
|
||||
void SendGameState();
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "blitz/game/Game.h"
|
||||
#include "blitz/misc/Time.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
@@ -24,11 +23,16 @@ class ServerGame : public game::Game {
|
||||
|
||||
void Tick(std::uint64_t delta) override;
|
||||
|
||||
void SetGameState(game::GameState gameState, std::uint64_t duration);
|
||||
|
||||
private:
|
||||
void SendPlayerPositions();
|
||||
void DamagePlayer(game::Player& player, game::Player& shooter);
|
||||
void UpdateHP(game::Player& player, float newHP);
|
||||
void UpdatePlayerStats();
|
||||
void StartGame(); // when at least 2 players joined
|
||||
void CancelGame(); // when not enough players are left
|
||||
void ResetPlayerStats();
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
|
||||
@@ -21,6 +21,7 @@ static std::array<PacketPtr, static_cast<std::size_t>(PacketType::PACKET_COUNT)>
|
||||
std::make_unique<PlayerListPacket>(),
|
||||
std::make_unique<PlayerStatsPacket>(),
|
||||
std::make_unique<ServerTpsPacket>(),
|
||||
std::make_unique<UpdateGameStatePacket>(),
|
||||
std::make_unique<KeepAlivePacket>(),
|
||||
std::make_unique<DisconnectPacket>(),
|
||||
std::make_unique<ChatPacket>(),
|
||||
|
||||
@@ -27,6 +27,7 @@ REGISTER_DISPATCH_CLASS(PlayerPositionAndRotationPacket)
|
||||
REGISTER_DISPATCH_CLASS(PlayerShootPacket);
|
||||
REGISTER_DISPATCH_CLASS(UpdateHealthPacket);
|
||||
REGISTER_DISPATCH_CLASS(PlayerStatsPacket);
|
||||
REGISTER_DISPATCH_CLASS(UpdateGameStatePacket);
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace blitz
|
||||
|
||||
19
src/blitz/protocol/packets/UpdateGameStatePacket.cpp
Normal file
19
src/blitz/protocol/packets/UpdateGameStatePacket.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "blitz/protocol/packets/UpdateGameStatePacket.h"
|
||||
|
||||
namespace blitz {
|
||||
namespace protocol {
|
||||
|
||||
DataBuffer UpdateGameStatePacket::Serialize(bool packetID) const {
|
||||
DataBuffer data;
|
||||
|
||||
WritePacketID(data, packetID);
|
||||
data << m_GameState << m_TimeRemaining;
|
||||
return data;
|
||||
}
|
||||
|
||||
void UpdateGameStatePacket::Deserialize(DataBuffer& data) {
|
||||
data >> m_GameState >> m_TimeRemaining;
|
||||
}
|
||||
|
||||
} // namespace protocol
|
||||
} // namespace blitz
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerShootPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerStatsPacket.h"
|
||||
#include "blitz/protocol/packets/UpdateGameStatePacket.h"
|
||||
#include "blitz/protocol/packets/UpdateHealthPacket.h"
|
||||
#include "client/Client.h"
|
||||
|
||||
@@ -31,6 +32,7 @@ void ClientGame::RegisterHandlers() {
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerPositionAndRotation, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerShoot, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::PlayerStats, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateGameState, this);
|
||||
GetDispatcher()->RegisterHandler(protocol::PacketType::UpdateHealth, this);
|
||||
}
|
||||
|
||||
@@ -69,6 +71,11 @@ void ClientGame::HandlePacket(const protocol::UpdateHealthPacket* packet) {
|
||||
}
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::UpdateGameStatePacket* packet) {
|
||||
m_GameState = packet->GetGameState();
|
||||
m_GameTimer.SetInterval(packet->GetTimeRemaining());
|
||||
m_GameTimer.Reset();
|
||||
}
|
||||
|
||||
void ClientGame::HandlePacket(const protocol::PlayerShootPacket* packet) {
|
||||
m_Client->NotifyListeners(
|
||||
@@ -93,6 +100,11 @@ void ClientGame::Tick(std::uint64_t delta) {
|
||||
for (auto& [playerId, player] : GetPlayers()) {
|
||||
player.SetPosition(player.GetPosition() + player.GetVelocity() * (static_cast<float>(delta) / 100.0f));
|
||||
}
|
||||
if (m_GameTimer.GetInterval() > 0) {
|
||||
if (m_GameTimer.Update(delta)) {
|
||||
m_GameTimer.SetInterval(0); // disables the timer so it does not loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace gui {
|
||||
|
||||
Hud::Hud(GuiWidget* parent, Client* client) : GuiWidget(parent, client) {
|
||||
m_GunTexture = TextureLoader::LoadGLTexture("fingergun.png");
|
||||
m_JP = TextureLoader::LoadGLTexture("jp.png");
|
||||
m_JPTexture = TextureLoader::LoadGLTexture("jp.png");
|
||||
}
|
||||
|
||||
void Hud::Draw(const char* title, bool* p_open) {
|
||||
@@ -20,7 +20,6 @@ void Hud::Draw(const char* title, bool* p_open) {
|
||||
ImGui::Begin(title, nullptr, GetWindowFullScreenFlags() | ImGuiWindowFlags_NoInputs);
|
||||
|
||||
auto displaySize = ImGui::GetIO().DisplaySize;
|
||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
|
||||
const static ImVec2 buttonSize = {300, 60};
|
||||
const static ImVec2 fingergunSize = {256, 134.5};
|
||||
@@ -34,17 +33,12 @@ void Hud::Draw(const char* title, bool* p_open) {
|
||||
displaySize.x - fingergunSize.x - paddingHeight, displaySize.y - fingergunSize.y + 1.0f / 2.5f * paddingHeight};
|
||||
ImVec2 spacing = ImGui::GetStyle().ItemInnerSpacing;
|
||||
|
||||
const float timetextWidth = ImGui::CalcTextSize("03 : 00").x;
|
||||
const float timetextHeight = ImGui::CalcTextSize("03 : 00").y;
|
||||
|
||||
ImGui::SetCursorPosX(center.x - timetextWidth / 2);
|
||||
ImGui::SetCursorPosY(timetextHeight / 2);
|
||||
ImGui::Text("03 : 00");
|
||||
RenderTime();
|
||||
|
||||
ImGui::SetCursorPosX(3 * paddingHeight);
|
||||
ImGui::SetCursorPosY(pvBarPos.y - 2 * paddingHeight);
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(m_JP), jpSize);
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(m_JPTexture), jpSize);
|
||||
|
||||
ImGui::SameLine(0.0f, paddingHeight);
|
||||
|
||||
@@ -78,6 +72,34 @@ void Hud::Draw(const char* title, bool* p_open) {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Hud::RenderTime() {
|
||||
|
||||
std::string timeFormated;
|
||||
|
||||
std::uint64_t timeRemaining = m_Client->GetGame()->GetGameStateRemainingTime();
|
||||
|
||||
if (timeRemaining == 0) {
|
||||
timeFormated = "Waiting for players ...";
|
||||
} else {
|
||||
timeRemaining += 1000;
|
||||
|
||||
int seconds = timeRemaining / 1000 % 60;
|
||||
int minutes = timeRemaining / 1000 / 60;
|
||||
|
||||
timeFormated = (minutes < 10 ? "0" + std::to_string(minutes) : std::to_string(minutes)) + " : " +
|
||||
(seconds < 10 ? "0" + std::to_string(seconds) : std::to_string(seconds));
|
||||
}
|
||||
|
||||
|
||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
const float timetextWidth = ImGui::CalcTextSize(timeFormated.c_str()).x;
|
||||
const float timetextHeight = ImGui::CalcTextSize(timeFormated.c_str()).y;
|
||||
|
||||
ImGui::SetCursorPosX(center.x - timetextWidth / 2);
|
||||
ImGui::SetCursorPosY(timetextHeight / 2);
|
||||
ImGui::Text("%s", timeFormated.c_str());
|
||||
}
|
||||
|
||||
void Hud::Render() {
|
||||
if (!m_Client->IsConnected())
|
||||
return;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "blitz/protocol/packets/PlayerLoginPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerShootPacket.h"
|
||||
#include "blitz/protocol/packets/UpdateGameStatePacket.h"
|
||||
#include "client/gui/ColorFulText.h"
|
||||
#include "server/Server.h"
|
||||
#include <unordered_map>
|
||||
@@ -94,6 +95,7 @@ void ServerConnexion::InitPlayerChatColor() {
|
||||
void ServerConnexion::HandlePacket(const protocol::PlayerLoginPacket* packet) {
|
||||
|
||||
SendPlayers();
|
||||
SendGameState();
|
||||
|
||||
m_Server->GetGame().AddPlayer(m_ID, packet->GetPlayerName());
|
||||
|
||||
@@ -143,6 +145,11 @@ void ServerConnexion::Start() {
|
||||
SendKeepAlive();
|
||||
}
|
||||
|
||||
void ServerConnexion::SendGameState() {
|
||||
protocol::UpdateGameStatePacket packet(m_Server->GetGame().GetGameState(), m_Server->GetGame().GetGameStateRemainingTime());
|
||||
SendPacket(&packet);
|
||||
}
|
||||
|
||||
void ServerConnexion::SendPlayers() {
|
||||
protocol::PlayerList list;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "blitz/protocol/packets/PlayerJoinPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerPositionAndRotationPacket.h"
|
||||
#include "blitz/protocol/packets/PlayerStatsPacket.h"
|
||||
#include "blitz/protocol/packets/UpdateGameStatePacket.h"
|
||||
#include "blitz/protocol/packets/UpdateHealthPacket.h"
|
||||
#include "server/Server.h"
|
||||
#include <cmath>
|
||||
@@ -15,14 +16,52 @@
|
||||
namespace blitz {
|
||||
namespace server {
|
||||
|
||||
ServerGame::ServerGame(Server* server) : m_Server(server), m_PositionTimer(SERVER_TPS) {}
|
||||
static const std::uint64_t PREP_DURATION = 1000 * 10;
|
||||
static const std::uint64_t GAME_DURATION = 1000 * 60 * 3;
|
||||
static const std::uint64_t END_DURATION = 1000 * 30;
|
||||
|
||||
ServerGame::ServerGame(Server* server) : m_Server(server), m_PositionTimer(SERVER_TPS) {
|
||||
CancelGame();
|
||||
}
|
||||
|
||||
ServerGame::~ServerGame() {}
|
||||
|
||||
void ServerGame::StartGame() {
|
||||
SetGameState(game::gsPreparing, PREP_DURATION);
|
||||
m_Server->BroadcastChatMessage(protocol::ChatPacket::GetTextColor(protocol::AQUA) + "La partie commence dans 10s !");
|
||||
}
|
||||
|
||||
void ServerGame::CancelGame() {
|
||||
SetGameState(game::gsWaiting, 0);
|
||||
}
|
||||
|
||||
void ServerGame::Tick(std::uint64_t delta) {
|
||||
if (m_PositionTimer.Update(delta)) {
|
||||
SendPlayerPositions();
|
||||
}
|
||||
if (m_GameState != game::gsWaiting && m_GameTimer.Update(delta)) {
|
||||
switch (m_GameState) {
|
||||
case game::gsPreparing:
|
||||
SetGameState(game::gsGame, GAME_DURATION);
|
||||
break;
|
||||
|
||||
case game::gsGame:
|
||||
SetGameState(game::gsEnd, END_DURATION);
|
||||
break;
|
||||
|
||||
case game::gsEnd: {
|
||||
if (m_Players.size() > 1) {
|
||||
SetGameState(game::gsGame, GAME_DURATION);
|
||||
} else {
|
||||
SetGameState(game::gsWaiting, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::SendPlayerPositions() {
|
||||
@@ -70,10 +109,18 @@ void ServerGame::AddPlayer(game::PlayerID player, const std::string& name) {
|
||||
|
||||
utils::LOG("[Server] " + joinMessage);
|
||||
m_Server->BroadcastChatMessage(protocol::ChatPacket::GetTextColor(protocol::YELLOW) + joinMessage);
|
||||
|
||||
if (m_GameState == game::gsWaiting && m_Players.size() > 1) {
|
||||
StartGame();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::RemovePlayer(game::PlayerID player) {
|
||||
Game::RemovePlayer(player);
|
||||
|
||||
if (m_GameState == game::gsGame && m_Players.size() <= 1) {
|
||||
CancelGame();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::DamagePlayer(game::Player& player, game::Player& shooter) {
|
||||
@@ -110,5 +157,25 @@ void ServerGame::UpdatePlayerStats() {
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::ResetPlayerStats() {
|
||||
for (auto& [playerId, player] : GetPlayers()) {
|
||||
player.GetStats() = {};
|
||||
}
|
||||
}
|
||||
|
||||
void ServerGame::SetGameState(game::GameState gameState, std::uint64_t duration) {
|
||||
m_GameState = gameState;
|
||||
m_GameTimer.SetInterval(duration);
|
||||
m_GameTimer.Reset();
|
||||
|
||||
if (gameState == game::gsGame) {
|
||||
ResetPlayerStats();
|
||||
UpdatePlayerStats();
|
||||
}
|
||||
|
||||
protocol::UpdateGameStatePacket packet(gameState, duration);
|
||||
m_Server->BroadcastPacket(&packet);
|
||||
}
|
||||
|
||||
} // namespace server
|
||||
} // namespace blitz
|
||||
|
||||
Reference in New Issue
Block a user