diff --git a/src/Game.cpp b/src/Game.cpp index 0e8d9a3..5879c07 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -835,7 +835,7 @@ namespace ZL { if (!textRenderer) return; -#ifdef NETWORK +//#ifdef NETWORK // 2D поверх 3D glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); @@ -882,7 +882,7 @@ namespace ZL glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); -#endif +//#endif } void Game::processTickCount() { diff --git a/src/network/LocalClient.cpp b/src/network/LocalClient.cpp index e0a8d36..5869c6a 100644 --- a/src/network/LocalClient.cpp +++ b/src/network/LocalClient.cpp @@ -68,7 +68,7 @@ namespace ZL { Eigen::Vector3f LocalClient::generateRandomPosition() { std::random_device rd; std::mt19937 gen(rd()); - std::uniform_real_distribution<> distrib(-50.0, 50.0); + std::uniform_real_distribution<> distrib(-500.0, 500.0); return Eigen::Vector3f( (float)distrib(gen), @@ -79,26 +79,24 @@ namespace ZL { void LocalClient::initializeNPCs() { npcs.clear(); - for (int i = 0; i < 3; ++i) { LocalNPC npc; npc.id = 100 + i; - npc.speed = 20.0f + (i * 5.0f); npc.currentState.id = npc.id; npc.currentState.position = generateRandomPosition(); npc.currentState.rotation = Eigen::Matrix3f::Identity(); - npc.currentState.velocity = npc.speed; + npc.currentState.velocity = 0.0f; + npc.currentState.selectedVelocity = 0; + npc.currentState.discreteMag = 0.0f; + npc.currentState.discreteAngle = -1; + npc.currentState.currentAngularVelocity = Eigen::Vector3f::Zero(); + npc.targetPosition = generateRandomPosition(); npc.lastStateUpdateMs = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()).count(); npc.stateHistory.add_state(npc.currentState); npcs.push_back(npc); - - std::cout << "LocalClient: Created NPC with id=" << npc.id - << " at pos (" << npc.currentState.position.x() << ", " - << npc.currentState.position.y() << ", " - << npc.currentState.position.z() << ")" << std::endl; } } @@ -108,37 +106,76 @@ namespace ZL { for (auto& npc : npcs) { uint64_t deltaMs = now_ms - npc.lastStateUpdateMs; - float dt = deltaMs / 1000.0f; + if (deltaMs == 0) { + npc.lastStateUpdateMs = now_ms; + continue; + } npc.lastStateUpdateMs = now_ms; - Eigen::Vector3f direction = npc.targetPosition - npc.currentState.position; - float distance = direction.norm(); + Eigen::Vector3f toTarget = npc.targetPosition - npc.currentState.position; + float distance = toTarget.norm(); - if (distance < 5.0f) { + const float ARRIVAL_THRESHOLD = 100.0f; + + if (distance < ARRIVAL_THRESHOLD) { npc.targetPosition = generateRandomPosition(); - direction = npc.targetPosition - npc.currentState.position; - distance = direction.norm(); + toTarget = npc.targetPosition - npc.currentState.position; + distance = toTarget.norm(); } - if (distance > 0.001f) { - direction.normalize(); - npc.currentState.position += direction * npc.speed * dt; - npc.currentState.velocity = npc.speed; + Eigen::Vector3f forwardWorld = -npc.currentState.rotation.col(2); + forwardWorld.normalize(); - Eigen::Vector3f localForward(0.0f, 0.0f, -1.0f); - Eigen::Vector3f worldForward = direction; + Eigen::Vector3f desiredDir = (distance > 0.001f) ? toTarget.normalized() : Eigen::Vector3f::UnitZ(); + float dot = forwardWorld.dot(desiredDir); + float angleErrorRad = std::acos(std::clamp(dot, -1.0f, 1.0f)); - Eigen::Vector3f cross = localForward.cross(worldForward); - float dot = localForward.dot(worldForward); + const float ALIGN_TOLERANCE = 0.15f; - if (cross.norm() > 0.001f) { - float angle = std::atan2(cross.norm(), dot); - cross.normalize(); - Eigen::AngleAxisf aa(angle * 0.05f, cross); - npc.currentState.rotation = npc.currentState.rotation * aa.toRotationMatrix(); + const float HYSTERESIS_FACTOR = 1.35f; + const float SOFT_THRUST_ANGLE = ALIGN_TOLERANCE * HYSTERESIS_FACTOR; + + if (angleErrorRad < ALIGN_TOLERANCE) { + npc.currentState.selectedVelocity = 1; + npc.currentState.discreteMag = 0.0f; + } + else if (angleErrorRad < SOFT_THRUST_ANGLE) { + npc.currentState.selectedVelocity = 1; + npc.currentState.discreteMag = std::min(0.50f, (angleErrorRad - ALIGN_TOLERANCE) * 10.0f); + } + else { + npc.currentState.selectedVelocity = 0; + + Eigen::Vector3f localDesired = npc.currentState.rotation.transpose() * desiredDir; + float dx = localDesired.x(); + float dy = localDesired.y(); + float dz = localDesired.z(); + + float turnX = dy; + float turnY = -dx; + float turnLen = std::sqrt(turnX * turnX + turnY * turnY); + + if (turnLen > 0.0001f) { + turnX /= turnLen; + turnY /= turnLen; + + float rad = std::atan2(turnX, turnY); + int angleDeg = static_cast(std::round(rad * 180.0f / M_PI)); + if (angleDeg < 0) angleDeg += 360; + + npc.currentState.discreteAngle = angleDeg; + npc.currentState.discreteMag = std::min(1.0f, angleErrorRad * 2.2f); + } + else if (angleErrorRad > 0.1f) { + npc.currentState.discreteAngle = 0; + npc.currentState.discreteMag = 1.0f; + } + else { + npc.currentState.discreteMag = 0.0f; } } + npc.currentState.simulate_physics(static_cast(deltaMs)); npc.currentState.lastUpdateServerTime = std::chrono::system_clock::time_point( std::chrono::milliseconds(now_ms)); npc.stateHistory.add_state(npc.currentState); diff --git a/src/network/LocalClient.h b/src/network/LocalClient.h index d94a82d..32fe19a 100644 --- a/src/network/LocalClient.h +++ b/src/network/LocalClient.h @@ -29,7 +29,6 @@ namespace ZL { ClientState currentState; ClientStateInterval stateHistory; Eigen::Vector3f targetPosition; - float speed = 30.0f; uint64_t lastStateUpdateMs = 0; };