Fixing bugs, unify velocity
This commit is contained in:
1 parent
fbc420e894
commit
f967807296
7 files changed
+153
-54
No files matched your search
+103
-29
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user