Working on list of players

This commit is contained in:
Vladislav Khorev committed 2026-03-09 23:04:48 +03:00
1 parent a8ded217df
commit 785b96ce82
10 files changed
+544 -13

No files matched your search

+182 -7
View File
@@ -332,6 +332,10 @@ namespace ZL
firePressed = true;
};
menuManager.onShowPlayersPressed = [this]() {
buildAndShowPlayerList();
};
menuManager.onTakeButtonPressed = [this]() {
if (Environment::shipState.shipType != 1) return;
if (!networkClient) return;
@@ -1001,6 +1005,16 @@ namespace ZL
int Space::pickTargetId() const
{
// Use manually selected target if it's still alive and in range
if (manualTrackedTargetId >= 0) {
auto it = remotePlayerStates.find(manualTrackedTargetId);
if (it != remotePlayerStates.end() && !deadRemotePlayers.count(manualTrackedTargetId)) {
float d2 = (Environment::shipState.position - it->second.position).squaredNorm();
if (d2 <= TARGET_MAX_DIST_SQ) return manualTrackedTargetId;
}
// Target no longer valid — fall through to auto-pick
}
int bestId = -1;
float bestDistSq = 1e30f;
@@ -1008,8 +1022,8 @@ namespace ZL
if (deadRemotePlayers.count(id)) continue;
float d2 = (Environment::shipState.position - st.position).squaredNorm();
if (d2 > TARGET_MAX_DIST_SQ) continue; // слишком далеко
if (d2 > TARGET_MAX_DIST_SQ) continue;
if (d2 < bestDistSq) {
bestDistSq = d2;
@@ -1728,6 +1742,7 @@ namespace ZL
std::cerr << "GAME OVER: collision with planet (moved back and exploded)\n";
clearPlayerListIfVisible();
menuManager.showGameOver(this->playerScore);
}
else {
@@ -1803,6 +1818,7 @@ namespace ZL
planetObject.planetStones.statuses[collidedTriIdx] = ChunkStatus::Empty;
}
clearPlayerListIfVisible();
menuManager.showGameOver(this->playerScore);
}
}
@@ -1885,6 +1901,7 @@ namespace ZL
gameOver = true;
Environment::shipState.velocity = 0.0f;
std::cout << "Client: Lost connection to server\n";
clearPlayerListIfVisible();
menuManager.showConnectionLost();
}
@@ -1923,6 +1940,7 @@ namespace ZL
}
}
}
// Обработка событий смерти, присланных сервером
auto deaths = networkClient->getPendingDeaths();
if (!deaths.empty()) {
@@ -1947,10 +1965,12 @@ namespace ZL
shipAlive = false;
gameOver = true;
Environment::shipState.velocity = 0.0f;
clearPlayerListIfVisible();
menuManager.showGameOver(this->playerScore);
}
else {
deadRemotePlayers.insert(d.targetId);
if (d.targetId == manualTrackedTargetId) manualTrackedTargetId = -1;
std::cout << "Marked remote player " << d.targetId << " as dead" << std::endl;
}
if (d.killerId == localId) {
@@ -1959,6 +1979,7 @@ namespace ZL
}
}
rebuildPlayerListIfVisible();
}
auto respawns = networkClient->getPendingRespawns();
@@ -1976,6 +1997,7 @@ namespace ZL
std::cout << "Client: Remote player " << respawnId << " respawned, removed from dead list" << std::endl;
}
}
rebuildPlayerListIfVisible();
auto disconnects = networkClient->getPendingDisconnects();
for (int pid : disconnects) {
@@ -1986,9 +2008,11 @@ namespace ZL
trackedTargetId = -1;
targetAcquireAnim = 0.f;
}
if (pid == manualTrackedTargetId) manualTrackedTargetId = -1;
std::cout << "Client: Remote player " << pid << " left the game, removed from scene\n";
}
rebuildPlayerListIfVisible();
auto boxDestructions = networkClient->getPendingBoxDestructions();
if (!boxDestructions.empty()) {
std::cout << "Game: Received " << boxDestructions.size() << " box destruction events" << std::endl;
@@ -2051,13 +2075,15 @@ namespace ZL
void Space::handleDown(int mx, int my)
{
Environment::tapDownHold = true;
if (playerListVisible) return;
Environment::tapDownStartPos(0) = mx;
Environment::tapDownStartPos(1) = my;
Environment::tapDownHold = true;
Environment::tapDownCurrentPos(0) = mx;
Environment::tapDownCurrentPos(1) = my;
Environment::tapDownStartPos(0) = mx;
Environment::tapDownStartPos(1) = my;
Environment::tapDownCurrentPos(0) = mx;
Environment::tapDownCurrentPos(1) = my;
}
void Space::handleUp(int mx, int my)
@@ -2068,6 +2094,8 @@ namespace ZL
void Space::handleMotion(int mx, int my)
{
if (playerListVisible) return;
if (Environment::tapDownHold) {
Environment::tapDownCurrentPos(0) = mx;
Environment::tapDownCurrentPos(1) = my;
@@ -2105,4 +2133,151 @@ namespace ZL
}*/
std::shared_ptr<UiNode> Space::buildPlayerListRoot()
{
const float btnW = 400;
const float btnH = 50.0f;
// Collect alive remote players
std::vector<std::pair<int, std::string>> players;
for (auto& kv : remotePlayerStates) {
if (!deadRemotePlayers.count(kv.first))
players.push_back({ kv.first, kv.second.nickname });
}
// Root: FrameLayout match_parent x match_parent
auto root = std::make_shared<UiNode>();
root->name = "playerListRoot";
root->layoutType = LayoutType::Frame;
root->width = -1.0f; // match_parent
root->height = -1.0f;
// List container: LinearLayout vertical, centered
float listH = btnH * (float)players.size();
auto listNode = std::make_shared<UiNode>();
listNode->name = "playerList";
listNode->layoutType = LayoutType::Linear;
listNode->orientation = Orientation::Vertical;
listNode->width = btnW;
listNode->height = listH;
listNode->layoutSettings.hGravity = HorizontalGravity::Center;
listNode->layoutSettings.vGravity = VerticalGravity::Center;
for (auto& [pid, nick] : players) {
auto btnNode = std::make_shared<UiNode>();
btnNode->name = "playerBtn_" + std::to_string(pid);
btnNode->layoutType = LayoutType::Frame;
btnNode->width = btnW;
btnNode->height = btnH;
auto tb = std::make_shared<UiTextButton>();
tb->name = btnNode->name;
tb->text = nick;
tb->fontSize = 20;
tb->color = { 1.f, 1.f, 1.f, 1.f };
tb->textCentered = true;
tb->textRenderer = std::make_unique<TextRenderer>();
if (!tb->textRenderer->init(renderer, tb->fontPath, tb->fontSize, CONST_ZIP_FILE)) {
std::cerr << "Failed to init TextRenderer for TextField: " << tb->name << std::endl;
}
//tb->texNormal = std::make_unique<Texture>(CreateTextureDataFromPng("resources/black.png", ""));
btnNode->textButton = tb;
/*auto button = std::make_shared<UiButton>();
button->name = "Hello";
button->texNormal = std::make_unique<Texture>(CreateTextureDataFromPng("resources/loading.png", ""));
btnNode->button = button;*/
listNode->children.push_back(btnNode);
}
// Backdrop: invisible full-screen TextButton — placed LAST so player buttons get priority
auto backdropNode = std::make_shared<UiNode>();
backdropNode->name = "playerListBackdrop";
backdropNode->layoutType = LayoutType::Frame;
backdropNode->width = -1.0f;
backdropNode->height = -1.0f;
auto backdropTb = std::make_shared<UiTextButton>();
backdropTb->name = "playerListBackdrop";
backdropNode->textButton = backdropTb;
/*
auto backgroundNode = std::make_shared<UiNode>();
backgroundNode->name = "playerListBackground";
backgroundNode->layoutType = LayoutType::Frame;
backgroundNode->width = btnW;
backgroundNode->height = listH;
backgroundNode->layoutSettings.hGravity = HorizontalGravity::Center;
backgroundNode->layoutSettings.vGravity = VerticalGravity::Center;
auto backdropImage = std::make_shared<UiStaticImage>();
backdropImage->name = "playerListBackgroundImage";
backdropImage->texture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/blue_transparent.png", ""));
backgroundNode->staticImage = backdropImage;
*/
root->children.push_back(listNode);
root->children.push_back(backdropNode);
//root->children.push_back(backgroundNode);
return root;
}
void Space::buildAndShowPlayerList()
{
auto listRoot = buildPlayerListRoot();
menuManager.uiManager.pushMenuFromSavedRoot(listRoot);
menuManager.uiManager.updateAllLayouts();
playerListVisible = true;
for (auto& kv : remotePlayerStates) {
if (deadRemotePlayers.count(kv.first)) continue;
int pid = kv.first;
std::string btnName = "playerBtn_" + std::to_string(pid);
menuManager.uiManager.setTextButtonCallback(btnName, [this, pid](const std::string&) {
manualTrackedTargetId = pid;
closePlayerList();
});
}
menuManager.uiManager.setTextButtonCallback("playerListBackdrop", [this](const std::string&) {
closePlayerList();
});
}
void Space::closePlayerList()
{
menuManager.uiManager.popMenu();
menuManager.uiManager.updateAllLayouts();
playerListVisible = false;
}
void Space::rebuildPlayerListIfVisible()
{
if (!playerListVisible) return;
auto listRoot = buildPlayerListRoot();
menuManager.uiManager.replaceRoot(listRoot);
for (auto& kv : remotePlayerStates) {
if (deadRemotePlayers.count(kv.first)) continue;
int pid = kv.first;
std::string btnName = "playerBtn_" + std::to_string(pid);
menuManager.uiManager.setTextButtonCallback(btnName, [this, pid](const std::string&) {
manualTrackedTargetId = pid;
closePlayerList();
});
}
menuManager.uiManager.setTextButtonCallback("playerListBackdrop", [this](const std::string&) {
closePlayerList();
});
}
void Space::clearPlayerListIfVisible()
{
if (!playerListVisible) return;
menuManager.uiManager.clearMenuStack();
playerListVisible = false;
}
} // namespace ZL