diff --git a/gui/assets/minus.png b/gui/assets/minus.png new file mode 100644 index 0000000..e8a3e03 Binary files /dev/null and b/gui/assets/minus.png differ diff --git a/gui/assets/plus.png b/gui/assets/plus.png new file mode 100644 index 0000000..40e3138 Binary files /dev/null and b/gui/assets/plus.png differ diff --git a/gui/assets/quickMenu.png b/gui/assets/quickMenu.png new file mode 100644 index 0000000..4a9274d Binary files /dev/null and b/gui/assets/quickMenu.png differ diff --git a/gui/assets/speedButton.png b/gui/assets/speedButton.png new file mode 100644 index 0000000..a78aaae Binary files /dev/null and b/gui/assets/speedButton.png differ diff --git a/gui/src/Buttons/Button.cpp b/gui/src/Buttons/Button.cpp new file mode 100644 index 0000000..c3a14c3 --- /dev/null +++ b/gui/src/Buttons/Button.cpp @@ -0,0 +1,47 @@ +#include "Buttons/Button.hpp" +#include +namespace Zappy +{ +Button::Button(Texture &texture, float x, float y, float width, float height, std::function function) : _function(function), _width(width), _height(height), _x(x), _y(y), _hovered(false) +{ + _sprite = std::make_unique(texture); + _sprite->setPosition(x, y); + _sprite->scale = Zappy::Math::vec3(width, height, 1.0f); + + +} + +void Button::draw(Shader &shader) +{ + if (_sprite) { + Zappy::Math::mat4 orthoProjection = Zappy::Math::ortho(0.0f, WIDTH, HEIGHT, 0.0f, -1.0f, 1.0f); + Zappy::Math::mat4 view; + _sprite->draw(shader, view, orthoProjection); + } +} + +void Button::setPosition(float x, float y) +{ + _x = x; + _y = y; +} + +void Button::update(const std::vector &events) +{ + for (const auto &event : events) + { + if (event.type == EventType::MouseMoved){ + if (event.mouseX >= _x - _width / 2 && event.mouseX <= _x + _width / 2 && event.mouseY >= _y - _height / 2 && event.mouseY <= _y + _height / 2){ + _hovered = true; + } else { + _hovered = false; + } + } + if (event.type == EventType::MousePressed && event.button == 1) { + if (_hovered) { + _function(); + } + } + } +} +}// namespace Zappy diff --git a/gui/src/Buttons/Button.hpp b/gui/src/Buttons/Button.hpp new file mode 100644 index 0000000..3d1dda6 --- /dev/null +++ b/gui/src/Buttons/Button.hpp @@ -0,0 +1,26 @@ +#pragma once +#include "Buttons/IButton.hpp" +#include "Sprite/Sprite.hpp" +#include "IScene/IScene.hpp" +#include +#include + +namespace Zappy +{ + class Button : public IButton { + private: + std::unique_ptr _sprite; + std::function _function; + float _width; + float _height; + float _x; + float _y; + bool _hovered; + public: + Button(Texture& texture, float x, float y, float width, float height, std::function function); + void draw(Shader &shader); + void setPosition(float x, float y); + void update(const std::vector &events); + }; + +} // namespace Z diff --git a/gui/src/Buttons/IButton.hpp b/gui/src/Buttons/IButton.hpp new file mode 100644 index 0000000..f0698ad --- /dev/null +++ b/gui/src/Buttons/IButton.hpp @@ -0,0 +1,16 @@ +#pragma once +#include "Core/Shader/Shader.hpp" +#include "Event.hpp" +#include + +namespace Zappy +{ + class IButton { + private: + public: + virtual ~IButton() = default; + virtual void draw(Shader &shader) = 0; + virtual void setPosition(float x, float y) = 0; + virtual void update(const std::vector &events) = 0; + }; +} diff --git a/gui/src/Core/Shader/ui.frag b/gui/src/Core/Shader/ui.frag new file mode 100644 index 0000000..4cd787f --- /dev/null +++ b/gui/src/Core/Shader/ui.frag @@ -0,0 +1,14 @@ +#version 330 core +in vec2 TexCoords; +out vec4 FragColor; + +uniform sampler2D ourTexture; + +void main() +{ + vec4 texColor = texture(ourTexture, TexCoords); + + if (texColor.a < 0.1) + discard; + FragColor = texColor; +} diff --git a/gui/src/Core/Shader/ui.vert b/gui/src/Core/Shader/ui.vert new file mode 100644 index 0000000..5de9ead --- /dev/null +++ b/gui/src/Core/Shader/ui.vert @@ -0,0 +1,13 @@ +#version 330 core +layout (location = 0) in vec2 aPos; +layout (location = 1) in vec2 aTexCoords; + +out vec2 TexCoords; + +uniform mat4 u_MVP; + +void main() +{ + TexCoords = vec2(aTexCoords.x, 1.0 - aTexCoords.y); + gl_Position = u_MVP * vec4(aPos, 0.0, 1.0); +} diff --git a/gui/src/Network/INetworkClient.hpp b/gui/src/Network/INetworkClient.hpp index 5ddbbcc..2becb7f 100644 --- a/gui/src/Network/INetworkClient.hpp +++ b/gui/src/Network/INetworkClient.hpp @@ -7,6 +7,6 @@ class INetworkClient { public: virtual ~INetworkClient() = default; virtual bool connectToServer(const std::string &host, int port) = 0; - virtual void sendCommand(const std::string &cmd) = 0; virtual std::vector fetchLines() = 0; + virtual void sendCommand(const std::string &cmd) = 0; }; \ No newline at end of file diff --git a/gui/src/Network/NetworkManager.cpp b/gui/src/Network/NetworkManager.cpp index 4b6e4e6..5060370 100644 --- a/gui/src/Network/NetworkManager.cpp +++ b/gui/src/Network/NetworkManager.cpp @@ -276,4 +276,15 @@ void NetworkManager::handleSbp(const std::vector &args) { _eventQueue.push_back({NetworkEventType::SERVER_ERROR, args}); } +void NetworkManager::sendSst(int time) +{ + std::string format = "sst " + std::to_string(time) + "\n"; + this->sendCommand(format); +} + +void NetworkManager::sendSgt() +{ + this->sendCommand(std::string("sgt\n")); +} + } // namespace Zappy \ No newline at end of file diff --git a/gui/src/Network/NetworkManager.hpp b/gui/src/Network/NetworkManager.hpp index b9ed7a1..a7de2ec 100644 --- a/gui/src/Network/NetworkManager.hpp +++ b/gui/src/Network/NetworkManager.hpp @@ -41,6 +41,8 @@ class NetworkManager { void processLine(const std::string &line); std::vector splitString(const std::string &str, char delimiter); int parseId(const std::string &idStr); + void sendSst(int time); + void sendSgt(); void handleWelcome(); void handleMsz(const std::vector &args); diff --git a/gui/src/Scene/Game.cpp b/gui/src/Scene/Game.cpp index f52b78e..4ac6d27 100644 --- a/gui/src/Scene/Game.cpp +++ b/gui/src/Scene/Game.cpp @@ -53,6 +53,29 @@ Zappy::SceneState Zappy::GameScene::update( if (_isMapBuilt) { float offsetX = gameState.map.width / 2.0f; float offsetZ = gameState.map.height / 2.0f; + bool isSpacePressed = false; + + for (const auto &event : events) { + if (event.type == Zappy::EventType::KeyPressed && event.keyCode == Zappy::Key::Space) { + isSpacePressed = true; + } + } + if (isSpacePressed && !_wasSpacePressed) { + if (_quickMenu) { + _quickMenu->onExit(); + _quickMenu.reset(); + } else { + _quickMenu = std::make_unique(_texManager, _networkManager); + _quickMenu->onEnter(); + } + } + _wasSpacePressed = isSpacePressed; + if (_quickMenu) { + SceneState quickMenuState = _quickMenu->update(events, gameState, netEvents, deltaTime); + if (quickMenuState != SceneState::NONE) + return quickMenuState; + } else + _camera.update(events); for (const auto &netEvent : netEvents) { @@ -103,7 +126,7 @@ Zappy::SceneState Zappy::GameScene::update( return SceneState::NONE; } -void Zappy::GameScene::draw(Shader &) { +void Zappy::GameScene::draw(Shader &shader) { if (_renderer && _isMapBuilt && _floor) { std::vector> resourcesToDraw; @@ -116,6 +139,11 @@ void Zappy::GameScene::draw(Shader &) { } _renderer->render(_camera, *_floor, _players, resourcesToDraw); } + if (_quickMenu) { + glDisable(GL_DEPTH_TEST); + _quickMenu->draw(shader); + glEnable(GL_DEPTH_TEST); + } } void Zappy::GameScene::onExit() { diff --git a/gui/src/Scene/Game.hpp b/gui/src/Scene/Game.hpp index c16e7ea..8a536ab 100644 --- a/gui/src/Scene/Game.hpp +++ b/gui/src/Scene/Game.hpp @@ -3,9 +3,10 @@ #include "Logger.hpp" #include "Sprite/InstancedGrid.hpp" #include "Sprite/Sprite.hpp" +#include "Scene/QuickMenu.hpp" #include "Texture/TextureManager.hpp" #include "Utils/math.hpp" - +#include "Network/NetworkManager.hpp" #include "Render/Camera.hpp" #include "Render/Render.hpp" @@ -19,16 +20,19 @@ class GameScene : public IScene { private: TextureManager &_texManager; std::unique_ptr _renderer; - + Camera _camera; std::unique_ptr _floor; std::vector> _players; std::map _playerMap; - + std::unique_ptr _quickMenu = nullptr; + bool _wasSpacePressed = false; + bool _isMapBuilt; + Zappy::NetworkManager &_networkManager; public: - GameScene(TextureManager &tm) : _texManager(tm), _isMapBuilt(false) {} + GameScene(TextureManager &tm, Zappy::NetworkManager &nm) : _texManager(tm), _isMapBuilt(false), _networkManager(nm) {} void onEnter() override; diff --git a/gui/src/Scene/QuickMenu.hpp b/gui/src/Scene/QuickMenu.hpp new file mode 100644 index 0000000..1f27e53 --- /dev/null +++ b/gui/src/Scene/QuickMenu.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include "IScene/IScene.hpp" +#include "Texture/TextureManager.hpp" +#include "Sprite/Sprite.hpp" +#include "Logger.hpp" +#include "Buttons/Button.hpp" +#include "Network/NetworkManager.hpp" +#include "Render/Render.hpp" +#include +#include +#include +#include "Utils/math.hpp" +#include + +namespace Zappy { + class quickMenu : public IScene { + private: + TextureManager &_texManager; + std::unique_ptr _backgroundSprite; + Zappy::NetworkManager &_networkManager; + std::vector> _buttons; + std::unique_ptr _uiShader; + int _speed; + public: + quickMenu(TextureManager &tm, Zappy::NetworkManager &nm) : _texManager(tm), _networkManager(nm) { + _speed = 0; + } + void onEnter() override { + Texture& menuTex = _texManager.get("gui/assets/quickMenu.png"); + Texture& speedButtonTex = _texManager.get("gui/assets/speedButton.png"); + Texture& decreaseButtonTex = _texManager.get("gui/assets/minus.png"); + Texture& increaseButtonTex = _texManager.get("gui/assets/plus.png"); + _uiShader = std::make_unique("gui/src/Core/Shader/ui.vert", "gui/src/Core/Shader/ui.frag"); + _backgroundSprite = std::make_unique(menuTex); + _backgroundSprite->setPosition(960.0f, 332.5f); + _networkManager.sendCommand("sgt\n"); + auto helper = []() { + std::cout << "You can decrease / increase the number of ticks per seconds." << std::endl; + }; + auto decrease = [this]() { + int newSpeed = std::max(1, this->_speed - 5); + this->_networkManager.sendCommand("sst " + std::to_string(newSpeed) + "\n"); + std::cout << "Decrease requested: " << newSpeed << std::endl; + }; + auto increase = [this]() { + int newSpeed = this->_speed + 5; + this->_networkManager.sendCommand("sst " + std::to_string(newSpeed) + "\n"); + std::cout << "Increase requested: " << newSpeed << std::endl; + }; + _buttons.push_back(std::make_unique(speedButtonTex, 950.0f, 450.0f, 80.0f, 80.0f, helper)); + _buttons.push_back(std::make_unique(increaseButtonTex, 1050.0f, 465.0f, 50.0f, 50.0f, increase)); + _buttons.push_back(std::make_unique(decreaseButtonTex, 850.0f, 465.0f, 50.0f, 50.0f, decrease)); + _backgroundSprite->scale = Zappy::Math::vec3(415.0f, 415.0f, 1.0f); + } + SceneState update(const std::vector &events, const Zappy::GameState &gameState, const std::vector &netEvents, float deltaTime) override + { + _speed = gameState.map.timeUnit; + for (auto& button : _buttons) { + button->update(events); + } + return SceneState::NONE; + } + void draw(Shader &shader) override { + if (!_backgroundSprite || !_uiShader) + return; + glDisable(GL_DEPTH_TEST); + _uiShader->bind(); + Zappy::Math::mat4 orthoProjection = Zappy::Math::ortho(0.0f, WIDTH, HEIGHT, 0.0f, -1.0f, 1.0f); + Zappy::Math::mat4 view; + _backgroundSprite->draw(*_uiShader, view, orthoProjection); + for (auto &button : _buttons) { + button->draw(*_uiShader); + } + glEnable(GL_DEPTH_TEST); + } + void onExit() override { + _buttons.clear(); + _backgroundSprite.reset(); + _uiShader.reset(); + } + }; +} diff --git a/gui/src/SceneManager/SceneManager.hpp b/gui/src/SceneManager/SceneManager.hpp index b3c44ea..211087c 100644 --- a/gui/src/SceneManager/SceneManager.hpp +++ b/gui/src/SceneManager/SceneManager.hpp @@ -47,7 +47,7 @@ class SceneManager { changeScene(std::make_unique(_textureManager, _audios)); break; case SceneState::MENU: - changeScene(std::make_unique(_textureManager)); + changeScene(std::make_unique(_textureManager, networkManager)); break; case SceneState::LOAD_NETWORK: changeScene(