uggly main menu

This commit is contained in:
2024-08-03 15:03:38 +02:00
parent b6530c1220
commit 2065ea8334
15 changed files with 729 additions and 354 deletions

View File

@@ -0,0 +1,32 @@
#pragma once
#include <Nazara/Core/ApplicationComponent.hpp>
namespace Nz {
class Window;
class Canvas;
class StateMachine;
} // namespace Nz
namespace blitz {
namespace client {
class StateData;
class ClientApp : public Nz::ApplicationComponent {
public:
ClientApp(Nz::ApplicationBase& app);
~ClientApp();
void Update(Nz::Time elapsedTime) override;
private:
Nz::Window* m_Window;
std::unique_ptr<Nz::StateMachine> m_StateMachine;
std::shared_ptr<StateData> m_StateData;
};
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,75 @@
#pragma once
#include <Nazara/Core/Components/DisabledComponent.hpp>
#include <Nazara/Core/State.hpp>
#include <Nazara/Graphics/RenderTarget.hpp>
#include <Nazara/Widgets/BaseWidget.hpp>
#include <client/states/StateData.h>
#include <functional>
#include <memory>
#include <vector>
namespace blitz {
namespace client {
class AbstractState : public Nz::State, public std::enable_shared_from_this<AbstractState> {
public:
AbstractState(std::shared_ptr<StateData> stateData);
~AbstractState();
protected:
template <typename T, typename... Args>
void ConnectSignal(T& signal, Args&&... args) {
m_CleanupFunctions.emplace_back(
[connection = signal.Connect(std::forward<Args>(args)...)]() mutable { connection.Disconnect(); });
}
template <typename T, typename... Args>
T* CreateWidget(Args&&... args) {
T* widget = m_StateData->m_Canvas->Add<T>(std::forward<Args>(args)...);
auto& entry = m_Widgets.emplace_back();
entry.m_Widget = widget;
if (!m_IsVisible)
entry.m_Widget->Hide();
return widget;
}
void DestroyWidget(Nz::BaseWidget* widget);
StateData& GetStateData() {
return *m_StateData;
}
const StateData& GetStateData() const {
return *m_StateData;
}
const std::shared_ptr<StateData>& GetStateDataPtr() {
return m_StateData;
}
void Enter(Nz::StateMachine& fsm) override;
void Leave(Nz::StateMachine& fsm) override;
bool Update(Nz::StateMachine& fsm, Nz::Time elapsedTime) override;
virtual void LayoutWidgets() {}
private:
NazaraSlot(Nz::RenderTarget, OnRenderTargetSizeChange, m_OnTargetChangeSizeSlot);
struct WidgetEntry {
Nz::BaseWidget* m_Widget;
bool m_WasVisible = true;
};
std::shared_ptr<StateData> m_StateData;
std::vector<std::function<void()>> m_CleanupFunctions;
std::vector<WidgetEntry> m_Widgets;
bool m_IsVisible;
};
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,28 @@
#pragma once
#include <Nazara/Widgets/ButtonWidget.hpp>
#include <client/states/AbstractState.h>
namespace blitz {
namespace client {
class CreateServerState : public AbstractState {
public:
CreateServerState(std::shared_ptr<StateData> a_StateData, std::shared_ptr<AbstractState> a_PreviousState);
~CreateServerState();
private:
Nz::ButtonWidget* m_CreateServerButton;
Nz::ButtonWidget* m_BackButton;
std::shared_ptr<AbstractState> m_NextState;
std::shared_ptr<AbstractState> m_PreviousState;
void LayoutWidgets() override;
bool Update(Nz::StateMachine& fsm, Nz::Time elapsedTime) override;
void OnCreateServerPressed();
void OnBackPressed();
};
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,28 @@
#pragma once
#include <Nazara/Widgets/ButtonWidget.hpp>
#include <client/states/AbstractState.h>
namespace blitz {
namespace client {
class JoinServerState : public AbstractState {
public:
JoinServerState(std::shared_ptr<StateData> a_StateData, std::shared_ptr<AbstractState> a_PreviousState);
~JoinServerState();
private:
Nz::ButtonWidget* m_JoinServerButton;
Nz::ButtonWidget* m_BackButton;
std::shared_ptr<AbstractState> m_NextState;
std::shared_ptr<AbstractState> m_PreviousState;
void LayoutWidgets() override;
bool Update(Nz::StateMachine& fsm, Nz::Time elapsedTime) override;
void OnJoinServerPressed();
void OnBackPressed();
};
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,31 @@
#pragma once
#include <Nazara/Widgets/ButtonWidget.hpp>
#include <client/states/AbstractState.h>
namespace blitz {
namespace client {
class MainMenuState : public AbstractState {
public:
MainMenuState(std::shared_ptr<StateData>);
~MainMenuState();
private:
Nz::ButtonWidget* m_JoinServerButton;
Nz::ButtonWidget* m_CreateServerButton;
Nz::ButtonWidget* m_OptionButton;
Nz::ButtonWidget* m_QuitButton;
std::shared_ptr<AbstractState> m_NextState;
void LayoutWidgets() override;
bool Update(Nz::StateMachine& fsm, Nz::Time elapsedTime) override;
void OnJoinServerPressed();
void OnCreateServerPressed();
void OnOptionPressed();
void OnQuitPressed();
};
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,28 @@
#pragma once
#include <Nazara/Widgets/ButtonWidget.hpp>
#include <client/states/AbstractState.h>
namespace blitz {
namespace client {
class OptionState : public AbstractState {
public:
OptionState(std::shared_ptr<StateData> a_StateData, std::shared_ptr<AbstractState> a_PreviousState);
~OptionState();
private:
Nz::ButtonWidget* m_OptionButton;
Nz::ButtonWidget* m_BackButton;
std::shared_ptr<AbstractState> m_NextState;
std::shared_ptr<AbstractState> m_PreviousState;
void LayoutWidgets() override;
bool Update(Nz::StateMachine& fsm, Nz::Time elapsedTime) override;
void OnOptionPressed();
void OnBackPressed();
};
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,34 @@
#pragma once
#include <Nazara/Core/EnttWorld.hpp>
#include <Nazara/Platform/Window.hpp>
#include <Nazara/Renderer/WindowSwapchain.hpp>
#include <Nazara/Widgets/Canvas.hpp>
#include <entt/fwd.hpp>
#include <memory>
#include <optional>
namespace Nz {
class ApplicationBase;
class RenderTarget;
} // namespace Nz
namespace blitz {
namespace client {
class ClientApp;
struct StateData {
std::optional<Nz::Canvas> m_Canvas;
std::shared_ptr<Nz::RenderTarget> m_RenderTarget;
ClientApp* m_AppComponent;
Nz::ApplicationBase* m_App;
Nz::EnttWorld* m_World;
Nz::Window* m_Window;
Nz::WindowSwapchain* m_Swapchain;
};
} // namespace client
} // namespace blitz

View File

@@ -1,349 +1,17 @@
#include <iostream> #include <Nazara/Core/Application.hpp>
#include <Nazara/Core/EntitySystemAppComponent.hpp>
#include <Nazara/Core.hpp> #include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics.hpp> #include <Nazara/Physics3D/Physics3D.hpp>
#include <Nazara/Physics3D.hpp> #include <Nazara/Platform/WindowingAppComponent.hpp>
#include <Nazara/Platform.hpp> #include <Nazara/Widgets/Widgets.hpp>
#include <Nazara/Renderer.hpp> #include <client/ClientApp.h>
#include <Nazara/Widgets.hpp>
#include <random> int main(int argc, char** argv) {
Nz::Application<Nz::Graphics, Nz::Physics3D, Nz::Widgets, Nz::TextRenderer> app(argc, argv);
constexpr Nz::UInt32 RenderMaskUI = 0x00010000;
constexpr Nz::UInt32 RenderMask3D = 0x0000FFFF; app.AddComponent<Nz::EntitySystemAppComponent>();
app.AddComponent<Nz::WindowingAppComponent>();
static Nz::Vector3f Get2DDirectionVectorFromRotation(float yaw) { app.AddComponent<blitz::client::ClientApp>();
return {
-std::sin(yaw),
0,
-std::cos(yaw),
};
}
static void CreateLight(Nz::EnttWorld& world) {
entt::handle lightEntity = world.CreateEntity();
{
auto& lightNode = lightEntity.emplace<Nz::NodeComponent>();
lightNode.SetPosition({0, 5, 0});
auto& entityLight = lightEntity.emplace<Nz::LightComponent>();
auto& spotLight = entityLight.AddLight<Nz::PointLight>(RenderMask3D);
spotLight.EnableShadowCasting(true);
spotLight.UpdateShadowMapSize(1024);
spotLight.UpdateRadius(10.0f);
spotLight.UpdateDiffuseFactor(0.5f);
}
}
static void CreateBoxes(Nz::EnttWorld& world) {
constexpr float BoxDims = 1.f;
std::mt19937 rd(42);
std::uniform_real_distribution<float> colorDis(0.f, 360.f);
std::uniform_real_distribution<float> radiusDis(0.1f, 0.5f);
std::uniform_real_distribution<float> lengthDis(0.2f, 1.5f);
std::shared_ptr<Nz::GraphicalMesh> boxMesh = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(1.f)));
constexpr std::size_t BoxCount = 100;
for (std::size_t i = 0; i < BoxCount; ++i) {
float width = lengthDis(rd);
float height = lengthDis(rd);
float depth = lengthDis(rd);
std::uniform_real_distribution<float> xRandom(-BoxDims * 0.5f + width, BoxDims * 0.5f - width);
std::uniform_real_distribution<float> yRandom(-BoxDims * 0.5f + height, BoxDims * 0.5f - height);
std::uniform_real_distribution<float> zRandom(-BoxDims * 0.5f + depth, BoxDims * 0.5f - depth);
entt::handle boxEntity = world.CreateEntity();
std::shared_ptr<Nz::MaterialInstance> boxMaterial = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Phong);
boxMaterial->SetValueProperty("BaseColor", Nz::Color::sRGBToLinear(Nz::Color::FromHSV(colorDis(rd), 1.f, 1.f)));
std::shared_ptr<Nz::Model> sphereModel = std::make_shared<Nz::Model>(boxMesh);
sphereModel->SetMaterial(0, std::move(boxMaterial));
boxEntity.emplace<Nz::GraphicsComponent>(std::move(sphereModel), RenderMask3D);
auto& ballNode = boxEntity.emplace<Nz::NodeComponent>();
ballNode.SetPosition({xRandom(rd), yRandom(rd) + 20.0f, zRandom(rd)});
ballNode.SetScale({width, height, depth});
std::shared_ptr<Nz::BoxCollider3D> boxCollider = std::make_shared<Nz::BoxCollider3D>(Nz::Vector3f(width, height, depth));
Nz::RigidBody3D::DynamicSettings settings;
settings.geom = boxCollider;
settings.mass = width * height * depth;
boxEntity.emplace<Nz::RigidBody3DComponent>(settings);
}
}
static void CreateModel(Nz::EnttWorld& world) {
std::filesystem::path resourceDir = "assets/models";
Nz::MeshParams meshParams;
meshParams.center = true;
meshParams.vertexRotation = Nz::EulerAnglesf(0.f, 0.f, 0.f);
meshParams.vertexScale = Nz::Vector3f(1.0f);
meshParams.vertexDeclaration = Nz::VertexDeclaration::Get(Nz::VertexLayout::XYZ_Normal_UV_Tangent);
std::shared_ptr<Nz::Mesh> deambuMesh = Nz::Mesh::LoadFromFile(resourceDir / "sol.obj", meshParams);
if (!deambuMesh) {
NazaraError("failed to load model");
return;
}
std::shared_ptr<Nz::GraphicalMesh> gfxMesh = Nz::GraphicalMesh::BuildFromMesh(*deambuMesh);
std::shared_ptr<Nz::Model> deambModel = std::make_shared<Nz::Model>(std::move(gfxMesh));
entt::handle deambEntity = world.CreateEntity();
{
auto& entityGfx = deambEntity.emplace<Nz::GraphicsComponent>(deambModel, RenderMask3D);
// entityGfx.AttachRenderable(deambModel);
auto& entityNode = deambEntity.emplace<Nz::NodeComponent>();
entityNode.SetPosition(Nz::Vector3f(0.f, 0.f, 0.f));
}
std::shared_ptr<Nz::RenderDevice> device = Nz::Graphics::Instance()->GetRenderDevice();
std::shared_ptr<Nz::MaterialInstance> material = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Phong);
for (std::string_view passName : {"DepthPass", "ForwardPass"}) {
material->UpdatePassStates(passName, [](Nz::RenderStates& states) {
states.depthClamp = true;
return true;
});
}
std::mt19937 rd(42);
std::uniform_real_distribution<float> colorDis(0.f, 360.f);
material->SetValueProperty("BaseColor", Nz::Color::sRGBToLinear(Nz::Color::FromHSV(colorDis(rd), 1.f, 1.f)));
for (std::size_t i = 0; i < deambModel->GetSubMeshCount(); ++i)
deambModel->SetMaterial(i, material);
Nz::VertexMapper vertexMapper(*deambuMesh->GetSubMesh(0));
Nz::SparsePtr<Nz::Vector3f> vertices = vertexMapper.GetComponentPtr<Nz::Vector3f>(Nz::VertexComponent::Position);
auto shipCollider = std::make_shared<Nz::ConvexHullCollider3D>(vertices, vertexMapper.GetVertexCount(), 0.1f);
Nz::RigidBody3D::StaticSettings settings;
settings.geom = shipCollider;
deambEntity.emplace<Nz::RigidBody3DComponent>(settings);
}
static Nz::EulerAnglesf camAngles(0.f, 0.f, 0.f);
static Nz::MillisecondClock updateClock;
static void CreateCamera(Nz::EnttWorld& world, Nz::Window& window, Nz::Application<Nz::Graphics, Nz::Physics3D, Nz::Widgets>& app,
std::shared_ptr<Nz::RenderWindow>& renderTarget) {
// Création de la caméra
entt::handle cameraEntity = world.CreateEntity();
auto& cameraNode = cameraEntity.emplace<Nz::NodeComponent>();
cameraNode.SetPosition({0, 2.5, 0});
auto& cameraComponent = cameraEntity.emplace<Nz::CameraComponent>(renderTarget, Nz::ProjectionType::Perspective);
cameraComponent.UpdateClearColor(Nz::Color(0.3f, 0.8f, 1.0f));
cameraComponent.UpdateZNear(0.1f);
cameraComponent.UpdateZFar(100.0f);
cameraComponent.UpdateRenderMask(RenderMask3D);
cameraComponent.UpdateRenderOrder(-1);
entt::handle playerEntity = world.CreateEntity();
auto& playerNode = playerEntity.emplace<Nz::NodeComponent>();
playerNode.SetPosition({0, 5, 0});
cameraNode.SetParent(playerEntity);
window.GetEventHandler().OnMouseMoved.Connect(
[&](const Nz::WindowEventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event) {
constexpr float sensitivity = 0.3f;
camAngles.yaw -= event.deltaX * sensitivity;
camAngles.yaw.Normalize();
camAngles.pitch = Nz::Clamp(camAngles.pitch - event.deltaY * sensitivity, -89.f, 89.f);
camAngles.roll = 0.0f;
cameraNode.SetRotation(camAngles);
});
Nz::Vector3f playerSize{0.5, 2, 0.5};
{
std::shared_ptr<Nz::GraphicalMesh> boxMesh = Nz::GraphicalMesh::Build(Nz::Primitive::Box(playerSize));
std::shared_ptr<Nz::MaterialInstance> boxMaterial = Nz::MaterialInstance::Instantiate(Nz::MaterialType::Phong);
boxMaterial->SetValueProperty("BaseColor", Nz::Color::sRGBToLinear({1.0, 0.0, 0.0}));
std::shared_ptr<Nz::Model> sphereModel = std::make_shared<Nz::Model>(boxMesh);
sphereModel->SetMaterial(0, std::move(boxMaterial));
playerEntity.emplace<Nz::GraphicsComponent>(std::move(sphereModel), RenderMask3D);
}
std::shared_ptr<Nz::BoxCollider3D> boxCollider = std::make_shared<Nz::BoxCollider3D>(playerSize);
static const int playerMass = 100000;
Nz::RigidBody3D::DynamicSettings settings;
settings.geom = boxCollider;
settings.mass = playerMass;
playerEntity.emplace<Nz::RigidBody3DComponent>(settings);
app.AddUpdaterFunc([playerEntity]() {
if (std::optional<Nz::Time> deltaTime = updateClock.RestartIfOver(Nz::Time::Milliseconds(30))) {
Nz::Vector3f front = Get2DDirectionVectorFromRotation(camAngles.yaw.ToRadians());
Nz::Vector3f left = Get2DDirectionVectorFromRotation(camAngles.yaw.ToRadians() + 3.1415926535 / 2.0);
auto& playerBody = playerEntity.get<Nz::RigidBody3DComponent>();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Z)) {
// std::cout << front << "\n";
// std::cout << "Pos : " << playerBody.GetPosition() << " \n";
playerBody.AddForce(front * 10.f * playerMass, Nz::CoordSys::Global);
}
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::S))
playerBody.AddForce(-front * 10.f * playerMass, Nz::CoordSys::Local);
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Q))
playerBody.AddForce(left * 10.f * playerMass, Nz::CoordSys::Local);
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D))
playerBody.AddForce(-left * 10.f * playerMass, Nz::CoordSys::Local);
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Space)) {
playerBody.AddForce(Nz::Vector3f::Up() * 15.f * playerMass, Nz::CoordSys::Global);
}
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::R)) {
auto& playerNode = playerEntity.get<Nz::NodeComponent>();
playerNode.SetPosition({0, 10, 0});
playerBody.SetPosition({0, 10, 0});
}
// playerBody.SetRotation({});
}
});
}
static void SetupWidgets(Nz::EnttWorld& world, std::shared_ptr<Nz::RenderWindow> renderTarget, Nz::Window& window) {
entt::handle cameraEntity = world.CreateEntity();
{
cameraEntity.emplace<Nz::NodeComponent>();
auto& cameraComponent = cameraEntity.emplace<Nz::CameraComponent>(renderTarget, Nz::ProjectionType::Orthographic);
cameraComponent.UpdateClearColor(Nz::Color(0.3f, 0.8f, 1.0f, 0.0f));
cameraComponent.UpdateRenderMask(RenderMaskUI);
cameraComponent.UpdateRenderOrder(1);
// cameraComponent.UpdateSize({100, 100});
}
Nz::Canvas canvas(world.GetRegistry(), window.GetEventHandler(), window.GetCursorController().CreateHandle(), RenderMaskUI);
canvas.Resize({static_cast<float>(window.GetSize().x), static_cast<float>(window.GetSize().y)});
canvas.EnableBackground(false);
auto widget = canvas.Add<Nz::RichTextAreaWidget>();
widget->EnableBackground(false);
widget->EnableLineWrap(true);
widget->SetBackgroundColor(Nz::Color(0, 0, 0, 50));
widget->SetCharacterSize(22);
widget->SetTextColor(Nz::Color::White());
widget->SetTextOutlineThickness(1.f);
widget->SetReadOnly(true);
auto m_chatEnteringBox = canvas.Add<Nz::TextAreaWidget>();
m_chatEnteringBox->EnableBackground(false);
m_chatEnteringBox->SetBackgroundColor(Nz::Color(255, 255, 255, 150));
m_chatEnteringBox->SetTextColor(Nz::Color::Black());
m_chatEnteringBox->SetText("ceci est un test incroyable");
// m_chatEnteringBox->SetMaximumWidth(m_chatEnteringBox->GetPreferredWidth());
auto versionLabel = canvas.Add<Nz::LabelWidget>();
versionLabel->UpdateText(
Nz::SimpleTextDrawer::Draw(std::to_string(100000000) + "." + std::to_string(0) + "." + std::to_string(0), 14));
versionLabel->Resize({500, 500});
versionLabel->SetPosition({1000, 800});
versionLabel->SetPosition({canvas.GetWidth() - versionLabel->GetWidth(), canvas.GetHeight() - versionLabel->GetHeight()});
// Création d'un texte
Nz::SimpleTextDrawer textDrawer;
textDrawer.SetText("Hello world !");
textDrawer.SetCharacterSize(72);
textDrawer.SetTextOutlineThickness(4.f);
std::shared_ptr<Nz::TextSprite> textSprite = std::make_shared<Nz::TextSprite>();
textSprite->Update(textDrawer);
entt::handle textEntity = world.CreateEntity();
{
auto& nodeComponent = textEntity.emplace<Nz::NodeComponent>();
auto& gfxComponent = textEntity.emplace<Nz::GraphicsComponent>(textSprite, RenderMaskUI);
Nz::Boxf textBox = textSprite->GetAABB();
Nz::Vector2ui windowSize = window.GetSize();
nodeComponent.SetPosition({windowSize.x / 2 - textBox.width / 2, windowSize.y / 2 - textBox.height / 2});
}
}
int Video(int argc, char** argv) {
Nz::Application<Nz::Graphics, Nz::Physics3D, Nz::Widgets> app(argc, argv);
auto& windowing = app.AddComponent<Nz::WindowingAppComponent>();
std::string windowTitle = "Blitz 2";
Nz::Window& window = windowing.CreateWindow(Nz::VideoMode(1920, 1080, 32), windowTitle);
auto& ecs = app.AddComponent<Nz::EntitySystemAppComponent>();
auto& world = ecs.AddWorld<Nz::EnttWorld>();
auto& physSystem = world.AddSystem<Nz::Physics3DSystem>();
physSystem.GetPhysWorld().SetMaxStepCount(1);
physSystem.GetPhysWorld().SetStepSize(Nz::Time::Milliseconds(20));
physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Down() * 9.81f);
Nz::RenderSystem& renderSystem = world.AddSystem<Nz::RenderSystem>();
Nz::SwapchainParameters params;
params.presentMode.clear();
params.presentMode.push_back(Nz::PresentMode::VerticalSync);
Nz::WindowSwapchain& windowSwapchain = renderSystem.CreateSwapchain(window, params);
auto renderTarget = std::make_shared<Nz::RenderWindow>(windowSwapchain);
CreateCamera(world, window, app, renderTarget);
CreateBoxes(world);
CreateModel(world);
CreateLight(world);
Nz::Mouse::SetRelativeMouseMode(true);
Nz::MillisecondClock fpsClock;
unsigned int fps = 0;
app.AddUpdaterFunc([&]() {
fps++;
if (fpsClock.RestartIfOver(Nz::Time::Second())) {
window.SetTitle(windowTitle + " - " + Nz::NumberToString(fps) + " FPS" + " - " +
Nz::NumberToString(world.GetAliveEntityCount()) + " entities");
fps = 0;
}
});
return app.Run(); return app.Run();
} }
int main(int argc, char** argv) {
return Video(argc, argv);
}

View File

@@ -6,23 +6,23 @@
#include <client/handlers/PlayerLeaveHandler.h> #include <client/handlers/PlayerLeaveHandler.h>
#include <client/handlers/PlayerListHandler.h> #include <client/handlers/PlayerListHandler.h>
#define RegisterHandler(Handler) m_Handlers.push_back(std::make_unique<Handler>(m_NetworkClient->GetConnection(), m_World))
namespace blitz { namespace blitz {
namespace client { namespace client {
Client::Client(Nz::EnttWorld& a_World) : m_World({a_World}) {} Client::Client(Nz::EnttWorld& a_World) : m_World({a_World}) {
// TODO: bind RemovePlayersSystem
}
Client::~Client() { Client::~Client() {
Disconnect(); Disconnect();
} }
void Client::BindHandlers() { void Client::BindHandlers() {
RegisterHandler(KeepAliveHandler); m_Handlers.push_back(std::make_unique<KeepAliveHandler>(m_NetworkClient->GetConnection(), m_World));
RegisterHandler(LoggingSuccessHandler); m_Handlers.push_back(std::make_unique<LoggingSuccessHandler>(m_NetworkClient->GetConnection(), m_World));
RegisterHandler(PlayerJoinHandler); m_Handlers.push_back(std::make_unique<PlayerJoinHandler>(m_NetworkClient->GetConnection(), m_World));
RegisterHandler(PlayerLeaveHandler); m_Handlers.push_back(std::make_unique<PlayerLeaveHandler>(m_NetworkClient->GetConnection(), m_World));
RegisterHandler(PlayerListHandler); m_Handlers.push_back(std::make_unique<PlayerListHandler>(m_NetworkClient->GetConnection(), m_World));
} }
void Client::UnbindHandlers() { void Client::UnbindHandlers() {

74
src/client/ClientApp.cpp Normal file
View File

@@ -0,0 +1,74 @@
#include <client/ClientApp.h>
#include <Nazara/Core.hpp>
#include <Nazara/Core/StateMachine.hpp>
#include <Nazara/Graphics.hpp>
#include <Nazara/Physics3D.hpp>
#include <Nazara/Platform.hpp>
#include <Nazara/Renderer.hpp>
#include <Nazara/Widgets.hpp>
#include <client/states/MainMenuState.h>
#include <random>
namespace blitz {
namespace client {
constexpr Nz::UInt32 RenderMaskUI = 0x00010000;
constexpr Nz::UInt32 RenderMask3D = 0x0000FFFF;
ClientApp::ClientApp(Nz::ApplicationBase& app) : Nz::ApplicationComponent(app), m_StateMachine(std::make_unique<Nz::StateMachine>()) {
auto& windowing = app.GetComponent<Nz::WindowingAppComponent>();
std::string windowTitle = "Blitz 2";
m_Window = &windowing.CreateWindow(Nz::VideoMode(1920, 1080, 32), windowTitle);
auto& ecs = app.GetComponent<Nz::EntitySystemAppComponent>();
auto& world = ecs.AddWorld<Nz::EnttWorld>();
Nz::RenderSystem& renderSystem = world.AddSystem<Nz::RenderSystem>();
Nz::SwapchainParameters params;
params.presentMode.clear();
params.presentMode.push_back(Nz::PresentMode::VerticalSync);
Nz::WindowSwapchain& windowSwapchain = renderSystem.CreateSwapchain(*m_Window, params);
auto renderTarget = std::make_shared<Nz::RenderWindow>(windowSwapchain);
entt::handle cameraEntity = world.CreateEntity();
{
cameraEntity.emplace<Nz::NodeComponent>();
auto& cameraComponent = cameraEntity.emplace<Nz::CameraComponent>(renderTarget, Nz::ProjectionType::Orthographic);
cameraComponent.UpdateClearColor(Nz::Color(0.0f, 0.f, .0f, 0.0f));
cameraComponent.UpdateRenderMask(RenderMaskUI);
cameraComponent.UpdateRenderOrder(1);
}
m_StateData = std::make_shared<StateData>();
m_StateData->m_App = &app;
m_StateData->m_AppComponent = this;
m_StateData->m_RenderTarget = renderTarget;
m_StateData->m_Window = m_Window;
m_StateData->m_World = &world;
m_StateData->m_Canvas.emplace(
world.GetRegistry(), m_Window->GetEventHandler(), m_Window->GetCursorController().CreateHandle(), RenderMaskUI);
m_StateData->m_Canvas->Resize(Nz::Vector2f(m_Window->GetSize()));
m_StateMachine->PushState(std::make_shared<MainMenuState>(m_StateData));
}
ClientApp::~ClientApp() {
m_StateMachine->ResetState(nullptr);
m_StateMachine->Update(Nz::Time::Zero());
}
void ClientApp::Update(Nz::Time elapsedTime) {
if (!m_StateMachine->Update(elapsedTime))
GetApp().Quit();
}
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,57 @@
#include <client/states/AbstractState.h>
namespace blitz {
namespace client {
AbstractState::AbstractState(std::shared_ptr<StateData> a_StateData) : m_StateData(std::move(a_StateData)), m_IsVisible(false) {
m_OnTargetChangeSizeSlot.Connect(
m_StateData->m_RenderTarget->OnRenderTargetSizeChange, [this](const Nz::RenderTarget*, const Nz::Vector2ui& /*newSize*/) {
if (m_IsVisible)
LayoutWidgets();
});
}
AbstractState::~AbstractState() {
for (const auto& cleanupFunc : m_CleanupFunctions)
cleanupFunc();
for (WidgetEntry& entry : m_Widgets)
entry.m_Widget->Destroy();
}
void AbstractState::DestroyWidget(Nz::BaseWidget* widget) {
auto it = std::find_if(
m_Widgets.begin(), m_Widgets.end(), [&](const WidgetEntry& widgetEntity) { return widgetEntity.m_Widget == widget; });
assert(it != m_Widgets.end());
m_Widgets.erase(it);
widget->Destroy();
}
void AbstractState::Enter(Nz::StateMachine& /*fsm*/) {
m_IsVisible = true;
for (WidgetEntry& entry : m_Widgets) {
if (entry.m_WasVisible)
entry.m_Widget->Show();
}
LayoutWidgets();
}
void AbstractState::Leave(Nz::StateMachine& /*fsm*/) {
m_IsVisible = false;
for (WidgetEntry& entry : m_Widgets) {
entry.m_WasVisible = entry.m_Widget->IsVisible();
entry.m_Widget->Hide();
}
}
bool AbstractState::Update(Nz::StateMachine& /*fsm*/, Nz::Time /*elapsedTime*/) {
return true;
}
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,73 @@
#include <client/states/CreateServerState.h>
#include <Nazara/Core/StateMachine.hpp>
#include <Nazara/TextRenderer.hpp>
namespace blitz {
namespace client {
CreateServerState::CreateServerState(std::shared_ptr<StateData> a_StateData, std::shared_ptr<AbstractState> a_PreviousState) :
AbstractState(std::move(a_StateData)), m_PreviousState(std::move(a_PreviousState)) {
Nz::SimpleTextDrawer textDrawer;
textDrawer.SetTextColor({0.0, 0.0, 0.0, 1.0});
textDrawer.SetCharacterSize(75);
m_CreateServerButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Create Server");
m_CreateServerButton->UpdateText(textDrawer);
m_CreateServerButton->Resize(m_CreateServerButton->GetPreferredSize());
m_CreateServerButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnCreateServerPressed(); });
m_BackButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Back");
m_BackButton->UpdateText(textDrawer);
m_BackButton->Resize(m_BackButton->GetPreferredSize());
m_BackButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnBackPressed(); });
}
CreateServerState::~CreateServerState() {}
bool CreateServerState::Update(Nz::StateMachine& fsm, Nz::Time /*elapsedTime*/) {
if (m_NextState)
fsm.ChangeState(std::move(m_NextState));
return true;
}
void CreateServerState::LayoutWidgets() {
Nz::Vector2f canvasSize = GetStateData().m_Canvas->GetSize();
Nz::Vector2f center = canvasSize / 2.f;
constexpr float padding = 10.f;
std::array<Nz::BaseWidget*, 2> widgets = {m_CreateServerButton, m_BackButton};
float maxWidth = 0.f;
float totalSize = padding * (widgets.size() - 1);
for (Nz::BaseWidget* widget : widgets) {
Nz::Vector2f size = widget->GetSize();
maxWidth = std::max(maxWidth, size.x);
totalSize += size.y;
}
Nz::Vector2f cursor = center;
cursor.y += totalSize / 2.f;
for (Nz::BaseWidget* widget : widgets) {
widget->Resize({maxWidth, widget->GetHeight()});
widget->SetPosition({0.f, cursor.y - widget->GetSize().y, 0.f});
widget->CenterHorizontal();
cursor.y -= widget->GetSize().y + padding;
}
}
void CreateServerState::OnCreateServerPressed() {}
void CreateServerState::OnBackPressed() {
m_NextState = std::move(m_PreviousState);
}
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,73 @@
#include <client/states/JoinServerState.h>
#include <Nazara/Core/StateMachine.hpp>
#include <Nazara/TextRenderer.hpp>
namespace blitz {
namespace client {
JoinServerState::JoinServerState(std::shared_ptr<StateData> a_StateData, std::shared_ptr<AbstractState> a_PreviousState) :
AbstractState(std::move(a_StateData)), m_PreviousState(std::move(a_PreviousState)) {
Nz::SimpleTextDrawer textDrawer;
textDrawer.SetTextColor({0.0, 0.0, 0.0, 1.0});
textDrawer.SetCharacterSize(75);
m_JoinServerButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Join Server");
m_JoinServerButton->UpdateText(textDrawer);
m_JoinServerButton->Resize(m_JoinServerButton->GetPreferredSize());
m_JoinServerButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnJoinServerPressed(); });
m_BackButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Back");
m_BackButton->UpdateText(textDrawer);
m_BackButton->Resize(m_BackButton->GetPreferredSize());
m_BackButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnBackPressed(); });
}
JoinServerState::~JoinServerState() {}
bool JoinServerState::Update(Nz::StateMachine& fsm, Nz::Time /*elapsedTime*/) {
if (m_NextState)
fsm.ChangeState(std::move(m_NextState));
return true;
}
void JoinServerState::LayoutWidgets() {
Nz::Vector2f canvasSize = GetStateData().m_Canvas->GetSize();
Nz::Vector2f center = canvasSize / 2.f;
constexpr float padding = 10.f;
std::array<Nz::BaseWidget*, 2> widgets = {m_JoinServerButton, m_BackButton};
float maxWidth = 0.f;
float totalSize = padding * (widgets.size() - 1);
for (Nz::BaseWidget* widget : widgets) {
Nz::Vector2f size = widget->GetSize();
maxWidth = std::max(maxWidth, size.x);
totalSize += size.y;
}
Nz::Vector2f cursor = center;
cursor.y += totalSize / 2.f;
for (Nz::BaseWidget* widget : widgets) {
widget->Resize({maxWidth, widget->GetHeight()});
widget->SetPosition({0.f, cursor.y - widget->GetSize().y, 0.f});
widget->CenterHorizontal();
cursor.y -= widget->GetSize().y + padding;
}
}
void JoinServerState::OnJoinServerPressed() {}
void JoinServerState::OnBackPressed() {
m_NextState = std::move(m_PreviousState);
}
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,101 @@
#include <client/states/MainMenuState.h>
#include <Nazara/Core/ApplicationBase.hpp>
#include <Nazara/Core/StateMachine.hpp>
#include <Nazara/TextRenderer.hpp>
#include <client/states/CreateServerState.h>
#include <client/states/JoinServerState.h>
#include <client/states/OptionState.h>
namespace blitz {
namespace client {
MainMenuState::MainMenuState(std::shared_ptr<StateData> a_StateData) : AbstractState(std::move(a_StateData)) {
Nz::SimpleTextDrawer textDrawer;
textDrawer.SetTextColor({0.0, 0.0, 0.0, 1.0});
textDrawer.SetCharacterSize(75);
m_JoinServerButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Join Server");
m_JoinServerButton->UpdateText(textDrawer);
m_JoinServerButton->Resize(m_JoinServerButton->GetPreferredSize());
m_JoinServerButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnJoinServerPressed(); });
m_CreateServerButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Create Server");
m_CreateServerButton->UpdateText(textDrawer);
m_CreateServerButton->Resize(m_CreateServerButton->GetPreferredSize());
m_CreateServerButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnCreateServerPressed(); });
m_OptionButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Settings");
m_OptionButton->UpdateText(textDrawer);
m_OptionButton->Resize(m_OptionButton->GetPreferredSize());
m_OptionButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnOptionPressed(); });
m_QuitButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Quit game");
m_QuitButton->UpdateText(textDrawer);
m_QuitButton->Resize(m_QuitButton->GetPreferredSize());
m_QuitButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnQuitPressed(); });
}
MainMenuState::~MainMenuState() {}
bool MainMenuState::Update(Nz::StateMachine& fsm, Nz::Time elapsedTime) {
if (!AbstractState::Update(fsm, elapsedTime))
return false;
if (m_NextState)
fsm.ChangeState(std::move(m_NextState));
return true;
}
void MainMenuState::LayoutWidgets() {
Nz::Vector2f canvasSize = GetStateData().m_Canvas->GetSize();
Nz::Vector2f center = canvasSize / 2.f;
constexpr float padding = 10.f;
std::array<Nz::BaseWidget*, 4> widgets = {m_JoinServerButton, m_CreateServerButton, m_OptionButton, m_QuitButton};
float maxWidth = 0.f;
float totalSize = padding * (widgets.size() - 1);
for (Nz::BaseWidget* widget : widgets) {
Nz::Vector2f size = widget->GetSize();
maxWidth = std::max(maxWidth, size.x);
totalSize += size.y;
}
Nz::Vector2f cursor = center;
cursor.y += totalSize / 2.f;
for (Nz::BaseWidget* widget : widgets) {
widget->Resize({maxWidth, widget->GetHeight()});
widget->SetPosition({0.f, cursor.y - widget->GetSize().y, 0.f});
widget->CenterHorizontal();
cursor.y -= widget->GetSize().y + padding;
}
}
void MainMenuState::OnJoinServerPressed() {
m_NextState = std::make_shared<JoinServerState>(GetStateDataPtr(), shared_from_this());
}
void MainMenuState::OnCreateServerPressed() {
m_NextState = std::make_shared<CreateServerState>(GetStateDataPtr(), shared_from_this());
}
void MainMenuState::OnOptionPressed() {
m_NextState = std::make_shared<OptionState>(GetStateDataPtr(), shared_from_this());
}
void MainMenuState::OnQuitPressed() {
GetStateData().m_App->Quit();
}
} // namespace client
} // namespace blitz

View File

@@ -0,0 +1,73 @@
#include <client/states/OptionState.h>
#include <Nazara/Core/StateMachine.hpp>
#include <Nazara/TextRenderer.hpp>
namespace blitz {
namespace client {
OptionState::OptionState(std::shared_ptr<StateData> a_StateData, std::shared_ptr<AbstractState> a_PreviousState) :
AbstractState(std::move(a_StateData)), m_PreviousState(std::move(a_PreviousState)) {
Nz::SimpleTextDrawer textDrawer;
textDrawer.SetTextColor({0.0, 0.0, 0.0, 1.0});
textDrawer.SetCharacterSize(75);
m_OptionButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Settings");
m_OptionButton->UpdateText(textDrawer);
m_OptionButton->Resize(m_OptionButton->GetPreferredSize());
m_OptionButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnOptionPressed(); });
m_BackButton = CreateWidget<Nz::ButtonWidget>();
textDrawer.SetText("Back");
m_BackButton->UpdateText(textDrawer);
m_BackButton->Resize(m_BackButton->GetPreferredSize());
m_BackButton->OnButtonTrigger.Connect([this](const Nz::ButtonWidget*) { OnBackPressed(); });
}
OptionState::~OptionState() {}
void OptionState::LayoutWidgets() {
Nz::Vector2f canvasSize = GetStateData().m_Canvas->GetSize();
Nz::Vector2f center = canvasSize / 2.f;
constexpr float padding = 10.f;
std::array<Nz::BaseWidget*, 2> widgets = {m_OptionButton, m_BackButton};
float maxWidth = 0.f;
float totalSize = padding * (widgets.size() - 1);
for (Nz::BaseWidget* widget : widgets) {
Nz::Vector2f size = widget->GetSize();
maxWidth = std::max(maxWidth, size.x);
totalSize += size.y;
}
Nz::Vector2f cursor = center;
cursor.y += totalSize / 2.f;
for (Nz::BaseWidget* widget : widgets) {
widget->Resize({maxWidth, widget->GetHeight()});
widget->SetPosition({0.f, cursor.y - widget->GetSize().y, 0.f});
widget->CenterHorizontal();
cursor.y -= widget->GetSize().y + padding;
}
}
bool OptionState::Update(Nz::StateMachine& fsm, Nz::Time /*elapsedTime*/) {
if (m_NextState)
fsm.ChangeState(std::move(m_NextState));
return true;
}
void OptionState::OnOptionPressed() {}
void OptionState::OnBackPressed() {
m_NextState = std::move(m_PreviousState);
}
} // namespace client
} // namespace blitz