Updated UI
This commit is contained in:
parent
46d7a2a25d
commit
1265d87bc5
@ -63,6 +63,10 @@ add_executable(space-game001
|
||||
../src/network/WebSocketClientEmscripten.cpp
|
||||
../src/render/TextRenderer.h
|
||||
../src/render/TextRenderer.cpp
|
||||
../src/MenuManager.h
|
||||
../src/MenuManager.cpp
|
||||
../src/Space.h
|
||||
../src/Space.cpp
|
||||
)
|
||||
|
||||
# Установка проекта по умолчанию для Visual Studio
|
||||
@ -84,7 +88,7 @@ target_compile_definitions(space-game001 PRIVATE
|
||||
WIN32_LEAN_AND_MEAN
|
||||
PNG_ENABLED
|
||||
SDL_MAIN_HANDLED
|
||||
NETWORK
|
||||
#NETWORK
|
||||
# SIMPLIFIED
|
||||
)
|
||||
|
||||
|
||||
297
src/Game.cpp
297
src/Game.cpp
@ -34,7 +34,9 @@ namespace ZL
|
||||
const char* CONST_ZIP_FILE = "";
|
||||
#endif
|
||||
|
||||
static bool g_exitBgAnimating = false;
|
||||
bool g_exitBgAnimating = false;
|
||||
|
||||
bool firePressed = false;
|
||||
|
||||
float x = 0;
|
||||
|
||||
@ -246,6 +248,7 @@ namespace ZL
|
||||
, newTickCount(0)
|
||||
, lastTickCount(0)
|
||||
, planetObject(renderer, taskManager, mainThreadHandler)
|
||||
, menuManager(renderer)
|
||||
{
|
||||
projectiles.reserve(maxProjectiles);
|
||||
for (int i = 0; i < maxProjectiles; ++i) {
|
||||
@ -307,156 +310,29 @@ namespace ZL
|
||||
explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
projectileEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
|
||||
uiManager.loadFromFile("resources/config/main_menu.json", renderer, CONST_ZIP_FILE);
|
||||
std::function<void()> loadGameplayUI;
|
||||
loadGameplayUI = [this]() {
|
||||
uiManager.loadFromFile("resources/config/ui.json", renderer, CONST_ZIP_FILE);
|
||||
menuManager.onRestartPressed = [this]() {
|
||||
this->shipAlive = true;
|
||||
this->gameOver = false;
|
||||
this->showExplosion = false;
|
||||
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
Environment::shipState.position = Vector3f{ 0, 0, 45000.f };
|
||||
Environment::shipState.velocity = 0.0f;
|
||||
Environment::shipState.rotation = Eigen::Matrix3f::Identity();
|
||||
Environment::inverseShipMatrix = Eigen::Matrix3f::Identity();
|
||||
Environment::zoom = DEFAULT_ZOOM;
|
||||
Environment::tapDownHold = false;
|
||||
|
||||
auto velocityTv = uiManager.findTextView("velocityText");
|
||||
if (velocityTv) {
|
||||
velocityTv->rect.x = 10.0f;
|
||||
velocityTv->rect.y = static_cast<float>(Environment::height) - velocityTv->rect.h - 10.0f;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to find velocityText in UI" << std::endl;
|
||||
}
|
||||
std::cerr << "Game restarted\n";
|
||||
};
|
||||
|
||||
uiManager.startAnimationOnNode("backgroundNode", "bgScroll");
|
||||
static bool isExitButtonAnimating = false;
|
||||
uiManager.setAnimationCallback("settingsButton", "buttonsExit", [this]() {
|
||||
std::cerr << "Settings button animation finished -> переход в настройки" << std::endl;
|
||||
if (uiManager.pushMenuFromFile("resources/config/settings.json", this->renderer, CONST_ZIP_FILE)) {
|
||||
uiManager.setButtonCallback("Opt1", [this](const std::string& n) {
|
||||
std::cerr << "Opt1 pressed: " << n << std::endl;
|
||||
});
|
||||
uiManager.setButtonCallback("Opt2", [this](const std::string& n) {
|
||||
std::cerr << "Opt2 pressed: " << n << std::endl;
|
||||
});
|
||||
uiManager.setButtonCallback("backButton", [this](const std::string& n) {
|
||||
uiManager.stopAllAnimations();
|
||||
uiManager.popMenu();
|
||||
});
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to open settings menu after animations" << std::endl;
|
||||
}
|
||||
});
|
||||
|
||||
uiManager.setAnimationCallback("exitButton", "bgScroll", []() {
|
||||
std::cerr << "Exit button bgScroll animation finished" << std::endl;
|
||||
g_exitBgAnimating = false;
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("playButton", [this](const std::string& name) {
|
||||
std::cerr << "Play button pressed: " << name << std::endl;
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("settingsButton", [this](const std::string& name) {
|
||||
std::cerr << "Settings button pressed: " << name << std::endl;
|
||||
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("exitButton", "buttonsExit");
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("exitButton", [this](const std::string& name) {
|
||||
std::cerr << "Exit button pressed: " << name << std::endl;
|
||||
|
||||
if (!g_exitBgAnimating) {
|
||||
std::cerr << "start repeat anim bgScroll on exitButton" << std::endl;
|
||||
g_exitBgAnimating = true;
|
||||
uiManager.startAnimationOnNode("exitButton", "bgScroll");
|
||||
}
|
||||
else {
|
||||
std::cerr << "stop repeat anim bgScroll on exitButton" << std::endl;
|
||||
g_exitBgAnimating = false;
|
||||
uiManager.stopAnimationOnNode("exitButton", "bgScroll");
|
||||
|
||||
auto exitButton = uiManager.findButton("exitButton");
|
||||
if (exitButton) {
|
||||
exitButton->animOffsetX = 0.0f;
|
||||
exitButton->animOffsetY = 0.0f;
|
||||
exitButton->animScaleX = 1.0f;
|
||||
exitButton->animScaleY = 1.0f;
|
||||
exitButton->buildMesh();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("shootButton", [this](const std::string& name) {
|
||||
firePressed = true;
|
||||
});
|
||||
uiManager.setButtonCallback("shootButton2", [this](const std::string& name) {
|
||||
firePressed = true;
|
||||
});
|
||||
uiManager.setSliderCallback("velocitySlider", [this](const std::string& name, float value) {
|
||||
int newVel = roundf(value * 10);
|
||||
if (newVel > 2)
|
||||
{
|
||||
newVel = 2;
|
||||
}
|
||||
|
||||
if (newVel != Environment::shipState.selectedVelocity) {
|
||||
newShipVelocity = newVel;
|
||||
}
|
||||
});
|
||||
menuManager.onVelocityChanged = [this](float newVelocity) {
|
||||
newShipVelocity = newVelocity;
|
||||
//Environment::shipState.velocity = newVelocity;
|
||||
//std::cerr << "Ship velocity changed: " << newVelocity << "\n";
|
||||
};
|
||||
menuManager.setupMenu();
|
||||
|
||||
uiManager.setButtonCallback("singleButton", [loadGameplayUI](const std::string& name) {
|
||||
std::cerr << "Single button pressed: " << name << " -> load gameplay UI\n";
|
||||
loadGameplayUI();
|
||||
});
|
||||
/*uiManager.setButtonCallback("multiplayerButton", [loadGameplayUI](const std::string& name) {
|
||||
std::cerr << "Multiplayer button pressed: " << name << " -> load gameplay UI\n";
|
||||
loadGameplayUI();
|
||||
});*/
|
||||
|
||||
uiManager.setButtonCallback("multiplayerButton", [this](const std::string& name) {
|
||||
std::cerr << "Multiplayer button pressed → opening multiplayer menu\n";
|
||||
|
||||
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("multiplayerButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("exitButton", "buttonsExit");
|
||||
|
||||
if (uiManager.pushMenuFromFile("resources/config/multiplayer_menu.json", this->renderer, CONST_ZIP_FILE)) {
|
||||
|
||||
// Callback для кнопки подключения
|
||||
uiManager.setButtonCallback("connectButton", [this](const std::string& buttonName) {
|
||||
std::string serverAddress = uiManager.getTextFieldValue("serverInputField");
|
||||
|
||||
if (serverAddress.empty()) {
|
||||
uiManager.setText("statusText", "Please enter server address");
|
||||
return;
|
||||
}
|
||||
|
||||
uiManager.setText("statusText", "Connecting to " + serverAddress + "...");
|
||||
std::cerr << "Connecting to server: " << serverAddress << std::endl;
|
||||
|
||||
// Здесь добавить вашу логику подключения к серверу
|
||||
// connectToServer(serverAddress);
|
||||
});
|
||||
|
||||
// Callback для кнопки назад
|
||||
uiManager.setButtonCallback("backButton", [this](const std::string& buttonName) {
|
||||
uiManager.popMenu();
|
||||
});
|
||||
|
||||
// Callback для отслеживания ввода текста
|
||||
uiManager.setTextFieldCallback("serverInputField",
|
||||
[this](const std::string& fieldName, const std::string& newText) {
|
||||
std::cout << "Server input field changed to: " << newText << std::endl;
|
||||
});
|
||||
|
||||
std::cerr << "Multiplayer menu loaded successfully\n";
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to load multiplayer menu\n";
|
||||
}
|
||||
});
|
||||
uiManager.setButtonCallback("exitButton", [](const std::string& name) {
|
||||
std::cerr << "Exit from main menu pressed: " << name << " -> exiting\n";
|
||||
Environment::exitGameLoop = true;
|
||||
});
|
||||
|
||||
cubemapTexture = std::make_shared<Texture>(
|
||||
std::array<TextureDataStruct, 6>{
|
||||
@ -756,7 +632,7 @@ namespace ZL
|
||||
renderer.DisableVertexAttribArray(vPositionName);
|
||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||
glEnable(GL_BLEND);
|
||||
uiManager.draw(renderer);
|
||||
menuManager.uiManager.draw(renderer);
|
||||
glDisable(GL_BLEND);
|
||||
renderer.shaderManager.PopShader();
|
||||
CheckGlError();
|
||||
@ -1445,41 +1321,7 @@ namespace ZL
|
||||
|
||||
std::cerr << "GAME OVER: collision with planet (moved back and exploded)\n";
|
||||
|
||||
if (!uiGameOverShown) {
|
||||
if (uiManager.pushMenuFromFile("resources/config/game_over.json", this->renderer, CONST_ZIP_FILE)) {
|
||||
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
||||
|
||||
std::string respawnMsg = "RESPAWN:" + std::to_string(networkClient->GetClientId());
|
||||
networkClient->Send(respawnMsg);
|
||||
|
||||
this->shipAlive = true;
|
||||
this->gameOver = false;
|
||||
this->uiGameOverShown = false;
|
||||
this->showExplosion = false;
|
||||
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
this->deadRemotePlayers.clear();
|
||||
|
||||
Environment::shipState.position = Vector3f{ 0, 0, 45000.f };
|
||||
Environment::shipState.velocity = 0.0f;
|
||||
Environment::shipState.rotation = Eigen::Matrix3f::Identity();
|
||||
Environment::inverseShipMatrix = Eigen::Matrix3f::Identity();
|
||||
Environment::zoom = DEFAULT_ZOOM;
|
||||
Environment::tapDownHold = false;
|
||||
|
||||
uiManager.popMenu();
|
||||
std::cerr << "Game restarted\n";
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
||||
Environment::exitGameLoop = true;
|
||||
});
|
||||
|
||||
uiGameOverShown = true;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to load game_over.json\n";
|
||||
}
|
||||
}
|
||||
menuManager.showGameOver();
|
||||
}
|
||||
else {
|
||||
bool stoneCollided = false;
|
||||
@ -1554,34 +1396,7 @@ namespace ZL
|
||||
planetObject.planetStones.statuses[collidedTriIdx] = ChunkStatus::Empty;
|
||||
}
|
||||
|
||||
if (!uiGameOverShown) {
|
||||
if (uiManager.pushMenuFromFile("resources/config/game_over.json", this->renderer, CONST_ZIP_FILE)) {
|
||||
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
||||
this->shipAlive = true;
|
||||
this->gameOver = false;
|
||||
this->uiGameOverShown = false;
|
||||
this->showExplosion = false;
|
||||
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
Environment::shipState.position = Vector3f{ 0, 0, 45000.f };
|
||||
Environment::shipState.velocity = 0.0f;
|
||||
Environment::shipState.rotation = Eigen::Matrix3f::Identity();
|
||||
Environment::inverseShipMatrix = Eigen::Matrix3f::Identity();
|
||||
Environment::zoom = DEFAULT_ZOOM;
|
||||
Environment::tapDownHold = false;
|
||||
uiManager.popMenu();
|
||||
std::cerr << "Game restarted\n";
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
||||
Environment::exitGameLoop = true;
|
||||
});
|
||||
|
||||
uiGameOverShown = true;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to load game_over.json\n";
|
||||
}
|
||||
}
|
||||
menuManager.showGameOver();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1643,14 +1458,14 @@ namespace ZL
|
||||
|
||||
// update velocity text
|
||||
if (shipAlive && !gameOver) {
|
||||
auto velocityTv = uiManager.findTextView("velocityText");
|
||||
auto velocityTv = menuManager.uiManager.findTextView("velocityText");
|
||||
if (velocityTv) {
|
||||
std::string velocityStr = "Velocity: " + std::to_string(static_cast<int>(Environment::shipState.velocity));
|
||||
uiManager.setText("velocityText", velocityStr);
|
||||
menuManager.uiManager.setText("velocityText", velocityStr);
|
||||
}
|
||||
}
|
||||
|
||||
uiManager.update(static_cast<float>(delta));
|
||||
menuManager.uiManager.update(static_cast<float>(delta));
|
||||
lastTickCount = newTickCount;
|
||||
}
|
||||
}
|
||||
@ -1763,14 +1578,14 @@ namespace ZL
|
||||
// Обработка ввода текста
|
||||
if (event.type == SDL_KEYDOWN) {
|
||||
if (event.key.keysym.sym == SDLK_BACKSPACE) {
|
||||
uiManager.onKeyBackspace();
|
||||
menuManager.uiManager.onKeyBackspace();
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type == SDL_TEXTINPUT) {
|
||||
// Пропускаем ctrl+c и другие команды
|
||||
if ((event.text.text[0] & 0x80) == 0) { // ASCII символы
|
||||
uiManager.onKeyPress((unsigned char)event.text.text[0]);
|
||||
menuManager.uiManager.onKeyPress((unsigned char)event.text.text[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1903,41 +1718,7 @@ namespace ZL
|
||||
shipAlive = false;
|
||||
gameOver = true;
|
||||
Environment::shipState.velocity = 0.0f;
|
||||
|
||||
if (!uiGameOverShown) {
|
||||
if (uiManager.pushMenuFromFile("resources/config/game_over.json",
|
||||
this->renderer, CONST_ZIP_FILE)) {
|
||||
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
||||
std::cout << "Client: Restart button clicked, sending RESPAWN" << std::endl;
|
||||
|
||||
std::string respawnMsg = "RESPAWN:" + std::to_string(networkClient->GetClientId());
|
||||
networkClient->Send(respawnMsg);
|
||||
|
||||
this->shipAlive = true;
|
||||
this->gameOver = false;
|
||||
this->uiGameOverShown = false;
|
||||
this->showExplosion = false;
|
||||
this->explosionEmitter.setEmissionPoints(std::vector<Vector3f>());
|
||||
this->deadRemotePlayers.clear();
|
||||
|
||||
Environment::shipState.position = Vector3f{ 0, 0, 45000.f };
|
||||
Environment::shipState.velocity = 0.0f;
|
||||
Environment::shipState.rotation = Eigen::Matrix3f::Identity();
|
||||
Environment::inverseShipMatrix = Eigen::Matrix3f::Identity();
|
||||
Environment::zoom = DEFAULT_ZOOM;
|
||||
Environment::tapDownHold = false;
|
||||
|
||||
uiManager.popMenu();
|
||||
std::cerr << "Game restarted\n";
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
||||
Environment::exitGameLoop = true;
|
||||
});
|
||||
|
||||
uiGameOverShown = true;
|
||||
}
|
||||
}
|
||||
menuManager.showGameOver();
|
||||
}
|
||||
else {
|
||||
deadRemotePlayers.insert(d.targetId);
|
||||
@ -1998,22 +1779,22 @@ namespace ZL
|
||||
int uiX = mx;
|
||||
int uiY = Environment::height - my;
|
||||
|
||||
uiManager.onMouseDown(uiX, uiY);
|
||||
menuManager.uiManager.onMouseDown(uiX, uiY);
|
||||
|
||||
bool uiHandled = false;
|
||||
|
||||
for (const auto& button : uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
|
||||
for (const auto& button : menuManager.uiManager.findButton("") ? std::vector<std::shared_ptr<UiButton>>{} : std::vector<std::shared_ptr<UiButton>>{}) {
|
||||
(void)button;
|
||||
}
|
||||
|
||||
auto pressedSlider = [&]() -> std::shared_ptr<UiSlider> {
|
||||
for (const auto& slider : uiManager.findSlider("") ? std::vector<std::shared_ptr<UiSlider>>{} : std::vector<std::shared_ptr<UiSlider>>{}) {
|
||||
for (const auto& slider : menuManager.uiManager.findSlider("") ? std::vector<std::shared_ptr<UiSlider>>{} : std::vector<std::shared_ptr<UiSlider>>{}) {
|
||||
(void)slider;
|
||||
}
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
if (!uiManager.isUiInteraction()) {
|
||||
if (!menuManager.uiManager.isUiInteraction()) {
|
||||
Environment::tapDownHold = true;
|
||||
|
||||
Environment::tapDownStartPos(0) = mx;
|
||||
@ -2029,9 +1810,9 @@ namespace ZL
|
||||
int uiX = mx;
|
||||
int uiY = Environment::height - my;
|
||||
|
||||
uiManager.onMouseUp(uiX, uiY);
|
||||
menuManager.uiManager.onMouseUp(uiX, uiY);
|
||||
|
||||
if (!uiManager.isUiInteraction()) {
|
||||
if (!menuManager.uiManager.isUiInteraction()) {
|
||||
Environment::tapDownHold = false;
|
||||
}
|
||||
}
|
||||
@ -2041,9 +1822,9 @@ namespace ZL
|
||||
int uiX = mx;
|
||||
int uiY = Environment::height - my;
|
||||
|
||||
uiManager.onMouseMove(uiX, uiY);
|
||||
menuManager.uiManager.onMouseMove(uiX, uiY);
|
||||
|
||||
if (Environment::tapDownHold && !uiManager.isUiInteraction()) {
|
||||
if (Environment::tapDownHold && !menuManager.uiManager.isUiInteraction()) {
|
||||
Environment::tapDownCurrentPos(0) = mx;
|
||||
Environment::tapDownCurrentPos(1) = my;
|
||||
}
|
||||
|
||||
19
src/Game.h
19
src/Game.h
@ -14,19 +14,13 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <render/TextRenderer.h>
|
||||
#include "MenuManager.h"
|
||||
#include "Space.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
|
||||
struct BoxCoords
|
||||
{
|
||||
Vector3f pos;
|
||||
Matrix3f m;
|
||||
};
|
||||
|
||||
|
||||
class Game {
|
||||
public:
|
||||
Game();
|
||||
@ -43,6 +37,8 @@ namespace ZL {
|
||||
MainThreadHandler mainThreadHandler;
|
||||
|
||||
std::unique_ptr<INetworkClient> networkClient;
|
||||
|
||||
|
||||
private:
|
||||
int64_t getSyncTimeMs();
|
||||
void processTickCount();
|
||||
@ -100,7 +96,8 @@ namespace ZL {
|
||||
SparkEmitter projectileEmitter;
|
||||
SparkEmitter explosionEmitter;
|
||||
PlanetObject planetObject;
|
||||
UiManager uiManager;
|
||||
|
||||
MenuManager menuManager;
|
||||
|
||||
std::vector<std::unique_ptr<Projectile>> projectiles;
|
||||
std::shared_ptr<Texture> projectileTexture;
|
||||
@ -115,12 +112,10 @@ namespace ZL {
|
||||
std::vector<bool> boxAlive;
|
||||
float shipCollisionRadius = 15.0f;
|
||||
float boxCollisionRadius = 2.0f;
|
||||
bool uiGameOverShown = false;
|
||||
//bool uiGameOverShown = false;
|
||||
bool showExplosion = false;
|
||||
uint64_t lastExplosionTime = 0;
|
||||
const uint64_t explosionDurationMs = 500;
|
||||
bool firePressed = false;
|
||||
|
||||
|
||||
bool serverBoxesApplied = false;
|
||||
|
||||
|
||||
196
src/MenuManager.cpp
Normal file
196
src/MenuManager.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
#include "MenuManager.h"
|
||||
|
||||
|
||||
namespace ZL {
|
||||
|
||||
MenuManager::MenuManager(Renderer& iRenderer) :
|
||||
renderer(iRenderer)
|
||||
{
|
||||
}
|
||||
|
||||
void MenuManager::setupMenu()
|
||||
{
|
||||
|
||||
uiManager.loadFromFile("resources/config/main_menu.json", renderer, CONST_ZIP_FILE);
|
||||
|
||||
uiSavedRoot = loadUiFromFile("resources/config/ui.json", renderer, CONST_ZIP_FILE);
|
||||
|
||||
settingsSavedRoot = loadUiFromFile("resources/config/settings.json", renderer, CONST_ZIP_FILE);
|
||||
|
||||
multiplayerSavedRoot = loadUiFromFile("resources/config/multiplayer_menu.json", renderer, CONST_ZIP_FILE);
|
||||
|
||||
gameOverSavedRoot = loadUiFromFile("resources/config/game_over.json", renderer, CONST_ZIP_FILE);
|
||||
|
||||
std::function<void()> loadGameplayUI;
|
||||
loadGameplayUI = [this]() {
|
||||
uiManager.replaceRoot(uiSavedRoot);
|
||||
|
||||
auto velocityTv = uiManager.findTextView("velocityText");
|
||||
if (velocityTv) {
|
||||
velocityTv->rect.x = 10.0f;
|
||||
velocityTv->rect.y = static_cast<float>(Environment::height) - velocityTv->rect.h - 10.0f;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to find velocityText in UI" << std::endl;
|
||||
}
|
||||
|
||||
uiManager.startAnimationOnNode("backgroundNode", "bgScroll");
|
||||
static bool isExitButtonAnimating = false;
|
||||
uiManager.setAnimationCallback("settingsButton", "buttonsExit", [this]() {
|
||||
std::cerr << "Settings button animation finished -> переход в настройки" << std::endl;
|
||||
if (uiManager.pushMenuFromSavedRoot(settingsSavedRoot)) {
|
||||
uiManager.setButtonCallback("Opt1", [this](const std::string& n) {
|
||||
std::cerr << "Opt1 pressed: " << n << std::endl;
|
||||
});
|
||||
uiManager.setButtonCallback("Opt2", [this](const std::string& n) {
|
||||
std::cerr << "Opt2 pressed: " << n << std::endl;
|
||||
});
|
||||
uiManager.setButtonCallback("backButton", [this](const std::string& n) {
|
||||
uiManager.stopAllAnimations();
|
||||
uiManager.popMenu();
|
||||
});
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to open settings menu after animations" << std::endl;
|
||||
}
|
||||
});
|
||||
|
||||
uiManager.setAnimationCallback("exitButton", "bgScroll", []() {
|
||||
std::cerr << "Exit button bgScroll animation finished" << std::endl;
|
||||
g_exitBgAnimating = false;
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("playButton", [this](const std::string& name) {
|
||||
std::cerr << "Play button pressed: " << name << std::endl;
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("settingsButton", [this](const std::string& name) {
|
||||
std::cerr << "Settings button pressed: " << name << std::endl;
|
||||
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("exitButton", "buttonsExit");
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("exitButton", [this](const std::string& name) {
|
||||
std::cerr << "Exit button pressed: " << name << std::endl;
|
||||
|
||||
if (!g_exitBgAnimating) {
|
||||
std::cerr << "start repeat anim bgScroll on exitButton" << std::endl;
|
||||
g_exitBgAnimating = true;
|
||||
uiManager.startAnimationOnNode("exitButton", "bgScroll");
|
||||
}
|
||||
else {
|
||||
std::cerr << "stop repeat anim bgScroll on exitButton" << std::endl;
|
||||
g_exitBgAnimating = false;
|
||||
uiManager.stopAnimationOnNode("exitButton", "bgScroll");
|
||||
|
||||
auto exitButton = uiManager.findButton("exitButton");
|
||||
if (exitButton) {
|
||||
exitButton->animOffsetX = 0.0f;
|
||||
exitButton->animOffsetY = 0.0f;
|
||||
exitButton->animScaleX = 1.0f;
|
||||
exitButton->animScaleY = 1.0f;
|
||||
exitButton->buildMesh();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("shootButton", [this](const std::string& name) {
|
||||
firePressed = true;
|
||||
});
|
||||
uiManager.setButtonCallback("shootButton2", [this](const std::string& name) {
|
||||
firePressed = true;
|
||||
});
|
||||
uiManager.setSliderCallback("velocitySlider", [this](const std::string& name, float value) {
|
||||
int newVel = roundf(value * 10);
|
||||
/*if (newVel > 2)
|
||||
{
|
||||
newVel = 2;
|
||||
}*/
|
||||
|
||||
if (newVel != Environment::shipState.selectedVelocity) {
|
||||
onVelocityChanged(newVel);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
uiManager.setButtonCallback("singleButton", [loadGameplayUI](const std::string& name) {
|
||||
std::cerr << "Single button pressed: " << name << " -> load gameplay UI\n";
|
||||
loadGameplayUI();
|
||||
});
|
||||
/*uiManager.setButtonCallback("multiplayerButton", [loadGameplayUI](const std::string& name) {
|
||||
std::cerr << "Multiplayer button pressed: " << name << " -> load gameplay UI\n";
|
||||
loadGameplayUI();
|
||||
});*/
|
||||
|
||||
uiManager.setButtonCallback("multiplayerButton", [this](const std::string& name) {
|
||||
std::cerr << "Multiplayer button pressed → opening multiplayer menu\n";
|
||||
|
||||
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("multiplayerButton", "buttonsExit");
|
||||
uiManager.startAnimationOnNode("exitButton", "buttonsExit");
|
||||
|
||||
if (uiManager.pushMenuFromSavedRoot(multiplayerSavedRoot)) {
|
||||
|
||||
// Callback для кнопки подключения
|
||||
uiManager.setButtonCallback("connectButton", [this](const std::string& buttonName) {
|
||||
std::string serverAddress = uiManager.getTextFieldValue("serverInputField");
|
||||
|
||||
if (serverAddress.empty()) {
|
||||
uiManager.setText("statusText", "Please enter server address");
|
||||
return;
|
||||
}
|
||||
|
||||
uiManager.setText("statusText", "Connecting to " + serverAddress + "...");
|
||||
std::cerr << "Connecting to server: " << serverAddress << std::endl;
|
||||
|
||||
// Здесь добавить вашу логику подключения к серверу
|
||||
// connectToServer(serverAddress);
|
||||
});
|
||||
|
||||
// Callback для кнопки назад
|
||||
uiManager.setButtonCallback("backButton", [this](const std::string& buttonName) {
|
||||
uiManager.popMenu();
|
||||
});
|
||||
|
||||
// Callback для отслеживания ввода текста
|
||||
uiManager.setTextFieldCallback("serverInputField",
|
||||
[this](const std::string& fieldName, const std::string& newText) {
|
||||
std::cout << "Server input field changed to: " << newText << std::endl;
|
||||
});
|
||||
|
||||
std::cerr << "Multiplayer menu loaded successfully\n";
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to load multiplayer menu\n";
|
||||
}
|
||||
});
|
||||
uiManager.setButtonCallback("exitButton", [](const std::string& name) {
|
||||
std::cerr << "Exit from main menu pressed: " << name << " -> exiting\n";
|
||||
Environment::exitGameLoop = true;
|
||||
});
|
||||
}
|
||||
|
||||
void MenuManager::showGameOver()
|
||||
{
|
||||
if (!uiGameOverShown) {
|
||||
if (uiManager.pushMenuFromSavedRoot(gameOverSavedRoot)) {
|
||||
uiManager.setButtonCallback("restartButton", [this](const std::string& name) {
|
||||
uiGameOverShown = false;
|
||||
uiManager.popMenu();
|
||||
onRestartPressed();
|
||||
});
|
||||
|
||||
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string& name) {
|
||||
Environment::exitGameLoop = true;
|
||||
});
|
||||
|
||||
uiGameOverShown = true;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Failed to load game_over.json\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/MenuManager.h
Normal file
38
src/MenuManager.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
#include "render/Renderer.h"
|
||||
#include "Environment.h"
|
||||
#include "render/TextureManager.h"
|
||||
#include "UiManager.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
extern const char* CONST_ZIP_FILE;
|
||||
extern bool g_exitBgAnimating;
|
||||
extern bool firePressed;
|
||||
|
||||
class MenuManager
|
||||
{
|
||||
protected:
|
||||
Renderer& renderer;
|
||||
bool uiGameOverShown = false;
|
||||
|
||||
std::shared_ptr<UiNode> uiSavedRoot;
|
||||
std::shared_ptr<UiNode> gameOverSavedRoot;
|
||||
std::shared_ptr<UiNode> settingsSavedRoot;
|
||||
std::shared_ptr<UiNode> multiplayerSavedRoot;
|
||||
|
||||
public:
|
||||
UiManager uiManager;
|
||||
|
||||
MenuManager(Renderer& iRenderer);
|
||||
|
||||
void setupMenu();
|
||||
|
||||
void showGameOver();
|
||||
|
||||
std::function<void()> onRestartPressed;
|
||||
std::function<void(float)> onVelocityChanged;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
0
src/Space.cpp
Normal file
0
src/Space.cpp
Normal file
152
src/Space.h
Normal file
152
src/Space.h
Normal file
@ -0,0 +1,152 @@
|
||||
#pragma once
|
||||
|
||||
#include "render/Renderer.h"
|
||||
#include "Environment.h"
|
||||
#include "render/TextureManager.h"
|
||||
#include "SparkEmitter.h"
|
||||
#include "planet/PlanetObject.h"
|
||||
#include "UiManager.h"
|
||||
#include "Projectile.h"
|
||||
#include "utils/TaskManager.h"
|
||||
#include "network/NetworkInterface.h"
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <render/TextRenderer.h>
|
||||
#include "MenuManager.h"
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace ZL {
|
||||
|
||||
|
||||
struct BoxCoords
|
||||
{
|
||||
Vector3f pos;
|
||||
Matrix3f m;
|
||||
};
|
||||
|
||||
/*
|
||||
class Space {
|
||||
public:
|
||||
Space(Renderer& iRenderer, TaskManager& iTaskManager, MainThreadHandler& iMainThreadHandler);
|
||||
~Space();
|
||||
|
||||
void setup();
|
||||
void update();
|
||||
void render();
|
||||
|
||||
bool shouldExit() const { return Environment::exitGameLoop; }
|
||||
|
||||
Renderer& renderer;
|
||||
TaskManager& taskManager;
|
||||
MainThreadHandler& mainThreadHandler;
|
||||
|
||||
private:
|
||||
int64_t getSyncTimeMs();
|
||||
void processTickCount();
|
||||
void drawScene();
|
||||
void drawCubemap(float skyPercent);
|
||||
void drawShip();
|
||||
void drawBoxes();
|
||||
void drawBoxesLabels();
|
||||
void drawUI();
|
||||
void drawRemoteShips();
|
||||
void drawRemoteShipsLabels();
|
||||
void fireProjectiles();
|
||||
|
||||
bool worldToScreen(const Vector3f& world, float& outX, float& outY, float& outDepth) const;
|
||||
|
||||
void handleDown(int mx, int my);
|
||||
void handleUp(int mx, int my);
|
||||
void handleMotion(int mx, int my);
|
||||
|
||||
SDL_Window* window;
|
||||
SDL_GLContext glContext;
|
||||
|
||||
|
||||
|
||||
int64_t newTickCount;
|
||||
int64_t lastTickCount;
|
||||
|
||||
std::vector<BoxCoords> boxCoordsArr;
|
||||
std::vector<VertexRenderStruct> boxRenderArr;
|
||||
|
||||
std::vector<std::string> boxLabels;
|
||||
std::unique_ptr<TextRenderer> textRenderer;
|
||||
|
||||
//std::unordered_map<int, ClientStateInterval> latestRemotePlayers;
|
||||
std::unordered_map<int, ClientState> remotePlayerStates;
|
||||
|
||||
float newShipVelocity = 0;
|
||||
|
||||
static const size_t CONST_TIMER_INTERVAL = 10;
|
||||
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
||||
|
||||
std::shared_ptr<Texture> sparkTexture;
|
||||
std::shared_ptr<Texture> spaceshipTexture;
|
||||
std::shared_ptr<Texture> cubemapTexture;
|
||||
VertexDataStruct spaceshipBase;
|
||||
VertexRenderStruct spaceship;
|
||||
|
||||
|
||||
VertexRenderStruct cubemap;
|
||||
|
||||
std::shared_ptr<Texture> boxTexture;
|
||||
VertexDataStruct boxBase;
|
||||
|
||||
SparkEmitter sparkEmitter;
|
||||
SparkEmitter projectileEmitter;
|
||||
SparkEmitter explosionEmitter;
|
||||
PlanetObject planetObject;
|
||||
|
||||
MenuManager menuManager;
|
||||
|
||||
std::vector<std::unique_ptr<Projectile>> projectiles;
|
||||
std::shared_ptr<Texture> projectileTexture;
|
||||
float projectileCooldownMs = 500.0f;
|
||||
int64_t lastProjectileFireTime = 0;
|
||||
int maxProjectiles = 32;
|
||||
std::vector<Vector3f> shipLocalEmissionPoints;
|
||||
|
||||
|
||||
bool shipAlive = true;
|
||||
bool gameOver = false;
|
||||
std::vector<bool> boxAlive;
|
||||
float shipCollisionRadius = 15.0f;
|
||||
float boxCollisionRadius = 2.0f;
|
||||
//bool uiGameOverShown = false;
|
||||
bool showExplosion = false;
|
||||
uint64_t lastExplosionTime = 0;
|
||||
const uint64_t explosionDurationMs = 500;
|
||||
|
||||
bool serverBoxesApplied = false;
|
||||
|
||||
static constexpr float MAX_DIST_SQ = 10000.f * 10000.f;
|
||||
static constexpr float FADE_START = 6000.f;
|
||||
static constexpr float FADE_RANGE = 4000.f;
|
||||
static constexpr float BASE_SCALE = 140.f;
|
||||
static constexpr float PERSPECTIVE_K = 0.05f; // Tune
|
||||
static constexpr float MIN_SCALE = 0.4f;
|
||||
static constexpr float MAX_SCALE = 0.8f;
|
||||
static constexpr float CLOSE_DIST = 600.0f;
|
||||
|
||||
std::unordered_set<int> deadRemotePlayers;
|
||||
|
||||
// --- Target HUD (brackets + offscreen arrow) ---
|
||||
int trackedTargetId = -1;
|
||||
bool targetWasVisible = false;
|
||||
float targetAcquireAnim = 0.0f; // 0..1 схлопывание (0 = далеко, 1 = на месте)
|
||||
|
||||
// временный меш для HUD (будем перезаливать VBO маленькими порциями)
|
||||
VertexRenderStruct hudTempMesh;
|
||||
|
||||
// helpers
|
||||
bool projectToNDC(const Vector3f& world, float& ndcX, float& ndcY, float& ndcZ, float& clipW) const;
|
||||
void drawTargetHud(); // рисует рамку или стрелку
|
||||
int pickTargetId() const; // выбирает цель (пока: ближайший живой удаленный игрок)
|
||||
};*/
|
||||
|
||||
|
||||
} // namespace ZL
|
||||
@ -182,60 +182,7 @@ namespace ZL {
|
||||
}
|
||||
}
|
||||
|
||||
void UiManager::loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
|
||||
std::string content;
|
||||
try {
|
||||
if (zipFile.empty()) {
|
||||
content = readTextFile(path);
|
||||
}
|
||||
else {
|
||||
auto buf = readFileFromZIP(path, zipFile);
|
||||
if (buf.empty()) {
|
||||
std::cerr << "UiManager: failed to read " << path << " from zip " << zipFile << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
content.assign(buf.begin(), buf.end());
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "UiManager: failed to open " << path << " : " << e.what() << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
json j;
|
||||
try {
|
||||
j = json::parse(content);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "UiManager: json parse error: " << e.what() << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
if (!j.contains("root") || !j["root"].is_object()) {
|
||||
std::cerr << "UiManager: root node missing or invalid" << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
root = parseNode(j["root"], renderer, zipFile);
|
||||
layoutNode(root);
|
||||
buttons.clear();
|
||||
sliders.clear();
|
||||
textViews.clear();
|
||||
textFields.clear();
|
||||
collectButtonsAndSliders(root);
|
||||
|
||||
nodeActiveAnims.clear();
|
||||
|
||||
for (auto& b : buttons) {
|
||||
b->buildMesh();
|
||||
}
|
||||
for (auto& s : sliders) {
|
||||
s->buildTrackMesh();
|
||||
s->buildKnobMesh();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<UiNode> UiManager::parseNode(const json& j, Renderer& renderer, const std::string& zipFile) {
|
||||
std::shared_ptr<UiNode> parseNode(const json& j, Renderer& renderer, const std::string& zipFile) {
|
||||
auto node = std::make_shared<UiNode>();
|
||||
if (j.contains("type") && j["type"].is_string()) node->type = j["type"].get<std::string>();
|
||||
if (j.contains("name") && j["name"].is_string()) node->name = j["name"].get<std::string>();
|
||||
@ -416,6 +363,76 @@ namespace ZL {
|
||||
return node;
|
||||
}
|
||||
|
||||
std::shared_ptr<UiNode> loadUiFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile)
|
||||
{
|
||||
std::shared_ptr<UiNode> root;
|
||||
|
||||
std::string content;
|
||||
try {
|
||||
if (zipFile.empty()) {
|
||||
content = readTextFile(path);
|
||||
}
|
||||
else {
|
||||
auto buf = readFileFromZIP(path, zipFile);
|
||||
if (buf.empty()) {
|
||||
std::cerr << "UiManager: failed to read " << path << " from zip " << zipFile << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
content.assign(buf.begin(), buf.end());
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "UiManager: failed to open " << path << " : " << e.what() << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
json j;
|
||||
try {
|
||||
j = json::parse(content);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "UiManager: json parse error: " << e.what() << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
if (!j.contains("root") || !j["root"].is_object()) {
|
||||
std::cerr << "UiManager: root node missing or invalid" << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
root = parseNode(j["root"], renderer, zipFile);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
void UiManager::replaceRoot(std::shared_ptr<UiNode> newRoot) {
|
||||
root = newRoot;
|
||||
layoutNode(root);
|
||||
buttons.clear();
|
||||
sliders.clear();
|
||||
textViews.clear();
|
||||
textFields.clear();
|
||||
collectButtonsAndSliders(root);
|
||||
|
||||
nodeActiveAnims.clear();
|
||||
|
||||
for (auto& b : buttons) {
|
||||
b->buildMesh();
|
||||
}
|
||||
for (auto& s : sliders) {
|
||||
s->buildTrackMesh();
|
||||
s->buildKnobMesh();
|
||||
}
|
||||
}
|
||||
|
||||
void UiManager::loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
|
||||
|
||||
std::shared_ptr<UiNode> newRoot = loadUiFromFile(path, renderer, zipFile);
|
||||
replaceRoot(newRoot);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UiManager::layoutNode(const std::shared_ptr<UiNode>& node) {
|
||||
for (auto& child : node->children) {
|
||||
child->rect.x += node->rect.x;
|
||||
@ -553,7 +570,8 @@ namespace ZL {
|
||||
return tf->text;
|
||||
}
|
||||
|
||||
bool UiManager::pushMenuFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
|
||||
bool UiManager::pushMenuFromSavedRoot(std::shared_ptr<UiNode> newRoot)
|
||||
{
|
||||
MenuState prev;
|
||||
prev.root = root;
|
||||
prev.buttons = buttons;
|
||||
@ -579,17 +597,22 @@ namespace ZL {
|
||||
}
|
||||
}
|
||||
|
||||
loadFromFile(path, renderer, zipFile);
|
||||
replaceRoot(newRoot);
|
||||
menuStack.push_back(std::move(prev));
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "UiManager: pushMenuFromFile failed to load " << path << " : " << e.what() << std::endl;
|
||||
std::cerr << "UiManager: pushMenuFromFile failed to load from root : " << e.what() << std::endl;
|
||||
animCallbacks = prev.animCallbacks;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool UiManager::pushMenuFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile) {
|
||||
auto newRoot = loadUiFromFile(path, renderer, zipFile);
|
||||
return pushMenuFromSavedRoot(newRoot);
|
||||
}
|
||||
|
||||
bool UiManager::popMenu() {
|
||||
if (menuStack.empty()) {
|
||||
std::cerr << "UiManager: popMenu called but menu stack is empty" << std::endl;
|
||||
|
||||
@ -136,10 +136,15 @@ namespace ZL {
|
||||
std::map<std::string, AnimSequence> animations;
|
||||
};
|
||||
|
||||
std::shared_ptr<UiNode> parseNode(const json& j, Renderer& renderer, const std::string& zipFile);
|
||||
std::shared_ptr<UiNode> loadUiFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
||||
|
||||
|
||||
class UiManager {
|
||||
public:
|
||||
UiManager() = default;
|
||||
|
||||
void replaceRoot(std::shared_ptr<UiNode> newRoot);
|
||||
void loadFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
||||
|
||||
void draw(Renderer& renderer);
|
||||
@ -186,6 +191,7 @@ namespace ZL {
|
||||
std::string getTextFieldValue(const std::string& name);
|
||||
|
||||
bool pushMenuFromFile(const std::string& path, Renderer& renderer, const std::string& zipFile = "");
|
||||
bool pushMenuFromSavedRoot(std::shared_ptr<UiNode> newRoot);
|
||||
bool popMenu();
|
||||
void clearMenuStack();
|
||||
|
||||
@ -196,7 +202,6 @@ namespace ZL {
|
||||
bool setAnimationCallback(const std::string& nodeName, const std::string& animName, std::function<void()> cb);
|
||||
|
||||
private:
|
||||
std::shared_ptr<UiNode> parseNode(const json& j, Renderer& renderer, const std::string& zipFile);
|
||||
void layoutNode(const std::shared_ptr<UiNode>& node);
|
||||
void collectButtonsAndSliders(const std::shared_ptr<UiNode>& node);
|
||||
|
||||
|
||||
@ -239,7 +239,7 @@ namespace ZL {
|
||||
for (size_t bi = 0; bi < serverBoxes.size(); ++bi) {
|
||||
if (serverBoxes[bi].destroyed) continue;
|
||||
|
||||
Eigen::Vector3f boxWorld = serverBoxes[bi].position + Eigen::Vector3f(0.0f, 6.0f, 45000.0f);
|
||||
Eigen::Vector3f boxWorld = serverBoxes[bi].position + Eigen::Vector3f(0.0f, 0.0f, 45000.0f);
|
||||
|
||||
for (size_t pi = 0; pi < projectiles.size(); ++pi) {
|
||||
const auto& pr = projectiles[pi];
|
||||
@ -387,8 +387,8 @@ namespace ZL {
|
||||
}
|
||||
|
||||
const std::vector<Eigen::Vector3f> localOffsets = {
|
||||
Eigen::Vector3f(-1.5f, 0.9f, 5.0f),
|
||||
Eigen::Vector3f(1.5f, 0.9f, 5.0f)
|
||||
Eigen::Vector3f(-1.5f, 0.9f - 6.f, 5.0f),
|
||||
Eigen::Vector3f(1.5f, 0.9f - 6.f, 5.0f)
|
||||
};
|
||||
|
||||
uint64_t now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user