Fixing bugs, unify velocity

This commit is contained in:
Vladislav Khorev committed 2026-01-17 12:43:41 +03:00
1 parent fbc420e894
commit f967807296
7 files changed
+153 -54

No files matched your search

+103 -29
View File
@@ -3,12 +3,16 @@
#include <Eigen/Dense>
#define _USE_MATH_DEFINES
#include <math.h>
#include <iostream>
using std::min;
using std::max;
constexpr float ANGULAR_ACCEL = 0.005f * 1000.0f;
constexpr float SHIP_ACCEL = 1.0f * 1000.0f;
constexpr float ROTATION_SENSITIVITY = 0.002f;
struct ClientState {
int id;
Eigen::Vector3f position = { 0, 0, 45000.0f };
@@ -22,13 +26,70 @@ struct ClientState {
// Для расчета лага
std::chrono::steady_clock::time_point lastUpdateServerTime;
void simulate_physics(float dt_s) {
void simulate_physics(size_t delta) {
// Константы из Game.cpp, приведенные к секундам (умножаем на 1000)
const float ANGULAR_ACCEL = 0.005f * 1000.0f;
const float ROTATION_SENSITIVITY = 0.002f * 1000.0f;
const float SHIP_ACCEL = 1.0f * 1000.0f; // CONST_ACCELERATION
//const float ANGULAR_ACCEL = 0.005f * 1000.0f;
//const float ROTATION_SENSITIVITY = 0.002f;
//const float SHIP_ACCEL = 1.0f * 1000.0f; // CONST_ACCELERATION
// 1. Вычисляем targetAngularVelocity на лету из дискретных значений
if (discreteMag > 0.01f)
{
float rad = static_cast<float>(discreteAngle) * static_cast<float>(M_PI) / 180.0f;
// Целевая угловая скорость (дискретная сила определяет модуль вектора)
// Вектор {cos, sin, 0} дает нам направление отклонения джойстика
Eigen::Vector3f targetAngularVelDir(sinf(rad), cosf(rad), 0.0f);
Eigen::Vector3f targetAngularVelocity = targetAngularVelDir * discreteMag;
Eigen::Vector3f diffVel = targetAngularVelocity - currentAngularVelocity;
float diffLen = diffVel.norm();
if (diffLen > 0.0001f) {
// Вычисляем, на сколько мы можем изменить скорость в этом кадре
float maxChange = ANGULAR_ACCEL * static_cast<float>(delta);
if (diffLen <= maxChange) {
// Если до цели осталось меньше, чем шаг ускорения — просто прыгаем в цель
currentAngularVelocity = targetAngularVelocity;
}
else {
// Линейно двигаемся в сторону целевого вектора
currentAngularVelocity += (diffVel / diffLen) * maxChange;
}
}
}
else
{
float currentSpeed = currentAngularVelocity.norm();
if (currentSpeed > 0.0001f) {
float drop = ANGULAR_ACCEL * static_cast<float>(delta);
if (currentSpeed <= drop) {
currentAngularVelocity = Eigen::Vector3f::Zero();
}
else {
// Уменьшаем модуль вектора, сохраняя направление
currentAngularVelocity -= (currentAngularVelocity / currentSpeed) * drop;
}
}
}
float speedScale = currentAngularVelocity.norm();
if (speedScale > 0.0001f) {
// Коэффициент чувствительности вращения
float deltaAlpha = speedScale * static_cast<float>(delta) * ROTATION_SENSITIVITY;
Eigen::Vector3f axis = currentAngularVelocity.normalized();
Eigen::Quaternionf rotateQuat(Eigen::AngleAxisf(deltaAlpha, axis));
rotation = rotation * rotateQuat.toRotationMatrix();
}
/*
Eigen::Vector3f targetAngularVelocity = Eigen::Vector3f::Zero();
if (discreteMag > 0.001f) {
@@ -61,8 +122,9 @@ struct ClientState {
else {
currentAngularVelocity -= (currentAngularVelocity / currentSpeed) * drop;
}
}
}*/
/*
// 3. Применение вращения к матрице (Интеграция)
float speedScale = currentAngularVelocity.norm();
if (speedScale > 0.0001f) {
@@ -71,50 +133,62 @@ struct ClientState {
Eigen::Quaternionf rotateQuat(Eigen::AngleAxisf(deltaAlpha, axis));
rotation = rotation * rotateQuat.toRotationMatrix();
}
}*/
// 4. Линейное изменение линейной скорости
float shipDesiredVelocity = static_cast<float>(selectedVelocity) * 100.f;
float speedDiff = shipDesiredVelocity - velocity;
if (std::abs(speedDiff) > 0.001f) {
float speedStep = SHIP_ACCEL * dt_s;
if (std::abs(speedDiff) <= speedStep) {
velocity = shipDesiredVelocity;
}
else {
velocity += (speedDiff > 0 ? 1.0f : -1.0f) * speedStep;
}
}
float shipDesiredVelocity = selectedVelocity * 100.f;
// 5. Обновление позиции
if (std::abs(velocity) > 0.01f) {
// Движение вперед по локальной оси Z (в твоем коде это {0, 0, -1})
Eigen::Vector3f localMove(0.0f, 0.0f, -velocity * dt_s);
position += rotation * localMove;
if (velocity < shipDesiredVelocity)
{
velocity += delta * SHIP_ACCEL;
if (velocity > shipDesiredVelocity)
{
velocity = shipDesiredVelocity;
}
}
else if (velocity > shipDesiredVelocity)
{
velocity -= delta * SHIP_ACCEL;
if (velocity < shipDesiredVelocity)
{
velocity = shipDesiredVelocity;
}
}
std::cout << "velocity=" << velocity << " delta=" << delta << std::endl;
if (fabs(velocity) > 0.01f)
{
Eigen::Vector3f velocityDirection = { 0,0, -velocity * delta / 1000.f };
Eigen::Vector3f velocityDirectionAdjusted = rotation * velocityDirection;
position = position + velocityDirectionAdjusted;
}
}
void apply_lag_compensation(std::chrono::steady_clock::time_point nowTime) {
// 1. Получаем текущее время сервера в той же шкале (мс)
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
/*uto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch()
).count();
long long deltaMs = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch() - lastUpdateServerTime
).count();*/
// 2. Вычисляем задержку
float lag_ms = 0.0;
long long deltaMs = 0;
if (nowTime > lastUpdateServerTime) {
lag_ms = std::chrono::duration<float>(nowTime - lastUpdateServerTime).count();
deltaMs = std::chrono::duration_cast<std::chrono::milliseconds>(nowTime - lastUpdateServerTime).count();
}
// 3. Защита от слишком больших скачков (Clamp)
// Если лаг более 500мс, ограничиваем его, чтобы избежать резких рывков
float final_lag_s = min(lag_ms, 0.5f);
long long final_lag_ms = min(deltaMs, 500ll);
if (final_lag_s > 0.001f) {
if (final_lag_ms > 0) {
// Доматываем симуляцию на величину задержки
// Мы предполагаем, что за это время параметры управления не менялись
simulate_physics(final_lag_s);
simulate_physics(final_lag_ms);
}
}
+1
View File
@@ -13,5 +13,6 @@ namespace ZL {
virtual bool IsConnected() const = 0;
virtual void Poll() = 0; // Äëÿ îáðàáîòêè âõîäÿùèõ ïàêåòîâ
virtual std::unordered_map<int, ClientState> getRemotePlayers() = 0;
virtual void updateRemotePlayers(const std::unordered_map<int, ClientState>& newRemotePlayers) = 0;
};
}
+8 -5
View File
@@ -69,8 +69,10 @@ namespace ZL {
void WebSocketClient::Poll() {
std::lock_guard<std::mutex> lock(queueMutex);
auto nowTime = std::chrono::steady_clock::now();
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch()
nowTime.time_since_epoch()
).count();
while (!messageQueue.empty()) {
@@ -99,21 +101,22 @@ namespace ZL {
// --- ÊÎÌÏÅÍÑÀÖÈß ËÀÃÀ ---
// Âû÷èñëÿåì çàäåðæêó â ñåêóíäàõ
float lag_s = static_cast<float>(now_ms - sentTime) / 1000.0f;
long long lag_s = now_ms - sentTime;
// Çàùèòà îò îòðèöàòåëüíîãî ëàãà (ðàçíèöà ÷àñîâ) èëè ñëèøêîì îãðîìíîãî
lag_s = std::max(0.0f, std::min(lag_s, 1.0f));
lag_s = std::max(0ll, std::min(lag_s, 1000ll));
if (lag_s > 0.001f) {
if (lag_s > 0) {
// "Äîêðó÷èâàåì" ôèçèêó êîíêðåòíîãî èãðîêà íà âåëè÷èíó çàäåðæêè
// Â ClientState.h simulate_physics äîëæåí èñïîëüçîâàòü
// àêòóàëüíûå discreteAngle/Mag
rp.simulate_physics(lag_s);
}
// Îáíîâëÿåì ìåòêó âðåìåíè, ÷òîáû îáû÷íàÿ ýêñòðàïîëÿöèÿ â Game.cpp
// çíàëà, ÷òî ñîñòîÿíèå óæå àêòóàëüíî íà ìîìåíò now_ms
rp.lastUpdateServerTime = std::chrono::steady_clock::now();
rp.lastUpdateServerTime = nowTime;
}
}
else if (msg.rfind("WORLD_UPDATE|", 0) == 0) {
+9
View File
@@ -53,5 +53,14 @@ namespace ZL {
std::lock_guard<std::mutex> lock(playersMutex);
return remotePlayers;
}
void updateRemotePlayers(const std::unordered_map<int, ClientState>& newRemotePlayers) override {
std::lock_guard<std::mutex> lock(playersMutex);
for (const auto& [id, newPlayer] : newRemotePlayers) {
remotePlayers[id] = newPlayer;
}
}
};
}