diff --git a/src/Space.cpp b/src/Space.cpp index acff0dd..1336b35 100644 --- a/src/Space.cpp +++ b/src/Space.cpp @@ -858,41 +858,38 @@ namespace ZL Vector3f shooterVel = ForwardFromRotation(Environment::shipState.rotation) * Environment::shipState.velocity; Vector3f targetVel = ForwardFromRotation(st.rotation) * st.velocity; - // условие "если враг не движется — круг не рисуем" const float minTargetSpeed = 0.5f; // подобрать (в твоих единицах) bool targetMoving = (targetVel.norm() > minTargetSpeed); + + // альфа круга + float leadAlpha = targetMoving ? 1.0f : 0.5f; Vector3f leadWorld = shipWorld; bool haveLead = false; - //if (targetMoving) { - // float tLead = 0.0f; - // if (SolveLeadInterceptTime(shooterPos, shooterVel, shipWorld, targetVel, projectileSpeed, tLead)) { - // // ограничим случаи, чтобы круг не улетал далеко - // if (tLead > 0.0f && tLead < 8.0f) { - // // подобрать максимум (сек) - // leadWorld = shipWorld + targetVel * tLead; - // haveLead = true; - // } - // } - //} + // чтобы круг не улетал далеко : максимум 4 секунды(подстрой под игру) + float distToTarget = (Environment::shipState.position - shipWorld).norm(); + float maxLeadTime = std::clamp((distToTarget / projectileSpeed) * 1.2f, 0.05f, 4.0f); - if (targetMoving) { + if (!targetMoving) { + // Цель стоит: рисуем lead прямо на ней, но полупрозрачный + leadWorld = shipWorld; + haveLead = true; + } + else { float tLead = 0.0f; - float distToTarget = (Environment::shipState.position - shipWorld).norm(); - const float leadMaxDist = 2500.0f; // максимум - float allowedDist = min(distToTarget, leadMaxDist); + // 1) Пытаемся “правильное” решение перехвата + bool ok = SolveLeadInterceptTime(shooterPos, shooterVel, shipWorld, targetVel, projectileSpeed, tLead); - // + небольшой запас 10–20% чтобы не моргало на границе - const float maxLeadTime = (allowedDist / projectileSpeed) * 1.2f; - - if (SolveLeadInterceptTime(shooterPos, shooterVel, shipWorld, targetVel, projectileSpeed, tLead)) { - if (tLead > 0.0f && tLead < maxLeadTime) { - leadWorld = shipWorld + targetVel * tLead; - haveLead = true; - } + // 2) Если решения нет / оно плохое — fallback (чтобы круг не пропадал при пролёте "вбок") + // Это ключевое изменение: lead всегда будет. + if (!ok || !(tLead > 0.0f) || tLead > maxLeadTime) { + tLead = std::clamp(distToTarget / projectileSpeed, 0.05f, maxLeadTime); } + + leadWorld = shipWorld + targetVel * tLead; + haveLead = true; } // 2) проекция @@ -965,6 +962,10 @@ namespace ZL renderer.PushMatrix(); renderer.LoadIdentity(); + // базовый цвет для HUD (скобки/стрелка) — непрозрачный + Eigen::Vector4f hudColor = enemyColor; + renderer.RenderUniform4fv("uColor", hudColor.data()); + // рисуем кружок упреждения (только если есть решение) if (haveLead) { float leadNdcX, leadNdcY, leadNdcZ, leadClipW; @@ -981,9 +982,16 @@ namespace ZL float innerR = max(1.0f, r - thicknessPx); float outerR = r + thicknessPx; + // для lead indicator alpha: 1.0 если движется, 0.5 если стоит + Eigen::Vector4f leadColor = enemyColor; + leadColor.w() = leadAlpha; + renderer.RenderUniform4fv("uColor", leadColor.data()); + VertexDataStruct ring = MakeRing2D(lx, ly, innerR, outerR, 0.0f, 32, enemyColor); hudTempMesh.AssignFrom(ring); renderer.DrawVertexRenderStruct(hudTempMesh); + + renderer.RenderUniform4fv("uColor", hudColor.data()); } } }