fixed rotation moving

This commit is contained in:
Ariari04 2026-02-12 13:55:06 +06:00
parent fb4a860773
commit d76342f3fa
2 changed files with 104 additions and 49 deletions

View File

@ -687,48 +687,78 @@ namespace ZL
bool joystickActive = isUsingJoystick && joystick && joystick->isActive;
if (joystickActive) {
float joyX = -joystick->getDirectionX(); // -1..1
float joyY = joystick->getDirectionY(); // -1..1 (вверх обычно отрицательный)
float joyX = joystick->getDirectionX(); // <-- оставляем инверсию X
float joyY = joystick->getDirectionY();
float magnitude = joystick->getMagnitude();
const float deadzone = 0.1f;
Vector3f newMoveDir = Vector3f::Zero();
float newMag = 0.0f;
if (magnitude > deadzone) {
// forward/right из ТЕКУЩЕГО camYaw (без lock)
Vector3f forward(-sinf(camYaw), 0.0f, -cosf(camYaw));
Vector3f right(cosf(camYaw), 0.0f, -sinf(camYaw));
// Берём ориентацию камеры из view matrix:
// view = World -> View, значит Rcw = (Rwv)^T = View -> World
Matrix4f viewM = camera.getViewMatrix();
Matrix3f Rwv = viewM.block<3, 3>(0, 0);
Matrix3f Rcw = Rwv.transpose();
// joyY: если вверх = отрицательный, то "- forward * joyY" даёт движение вперёд при joyY<0
Vector3f worldMove = right * joyX - forward * joyY;
Vector3f camRight = (Rcw * Vector3f(1, 0, 0));
Vector3f camForward = (Rcw * Vector3f(0, 0, -1)); // куда смотрит камера в мире
if (camRight.squaredNorm() > 1e-6f) camRight.normalize();
if (camForward.squaredNorm() > 1e-6f) camForward.normalize();
// joystick: X = вправо/влево, Y = вверх/вниз
// joyY обычно отрицательный при "вверх", поэтому "- camForward * joyY" даёт "вперёд"
Vector3f worldMove = camRight * joyX - camForward * joyY;
if (worldMove.squaredNorm() > 1e-6f) {
worldMove.normalize();
float ang = atan2f(worldMove.x(), worldMove.z()); // 0 -> +Z
int a = (int)std::round(ang * 180.0f / (float)M_PI);
if (a < 0) a += 360;
a %= 360;
discreteAngle = a;
discreteMag = (std::min)(magnitude, 1.0f);
discreteMag = std::round(discreteMag * 10.0f) / 10.0f;
newMoveDir = worldMove.normalized();
newMag = (std::min)(magnitude, 1.0f);
newMag = std::round(newMag * 10.0f) / 10.0f;
}
}
// Применяем в shipState
bool changed = false;
if ((Environment::shipState.currentAngularVelocity - newMoveDir).norm() > 0.001f) {
Environment::shipState.currentAngularVelocity = newMoveDir; // <-- теперь это "moveDirWorld"
changed = true;
}
if (fabs(Environment::shipState.discreteMag - newMag) > 0.001f) {
Environment::shipState.discreteMag = newMag; // throttle
changed = true;
}
// discreteAngle больше не нужен для движения (можешь оставить -1)
if (Environment::shipState.discreteAngle != -1) {
Environment::shipState.discreteAngle = -1;
changed = true;
}
if (changed) {
std::string msg = "UPD:" + std::to_string(now_ms) + ":" + Environment::shipState.formPingMessageContent();
networkClient->Send(msg);
}
}
// Network Update
bool changed = false;
//bool changed = false;
if (discreteAngle != Environment::shipState.discreteAngle) {
Environment::shipState.discreteAngle = discreteAngle;
changed = true;
}
if (discreteMag != Environment::shipState.discreteMag) {
Environment::shipState.discreteMag = discreteMag;
changed = true;
}
//if (discreteAngle != Environment::shipState.discreteAngle) {
// Environment::shipState.discreteAngle = discreteAngle;
// changed = true;
//}
//if (discreteMag != Environment::shipState.discreteMag) {
// Environment::shipState.discreteMag = discreteMag;
// changed = true;
//}
// slider value применяем здесь (ты раньше только newShipVelocity менял)
//int newVelInt = (int)newShipVelocity;
@ -737,9 +767,27 @@ namespace ZL
// changed = true;
//}
if (changed) {
std::string msg = "UPD:" + std::to_string(now_ms) + ":" + Environment::shipState.formPingMessageContent();
networkClient->Send(msg);
//if (changed) {
// std::string msg = "UPD:" + std::to_string(now_ms) + ":" + Environment::shipState.formPingMessageContent();
// networkClient->Send(msg);
//}
// Network Update (только если НЕ используем джойстик)
if (!joystickActive) {
bool changed2 = false;
if (discreteAngle != Environment::shipState.discreteAngle) {
Environment::shipState.discreteAngle = discreteAngle;
changed2 = true;
}
if (discreteMag != Environment::shipState.discreteMag) {
Environment::shipState.discreteMag = discreteMag;
changed2 = true;
}
if (changed2) {
std::string msg = "UPD:" + std::to_string(now_ms) + ":" + Environment::shipState.formPingMessageContent();
networkClient->Send(msg);
}
}

View File

@ -46,11 +46,8 @@ void ClientState::simulate_physics(size_t deltaMs)
const float ROT_T = std::clamp(ROTATION_SENSITIVITY * static_cast<float>(deltaMs), 0.0f, 1.0f);
// -------------------------------------------
// We keep this for protocol compatibility, but it no longer affects anything.
currentAngularVelocity = Eigen::Vector3f::Zero();
// Input validity
const bool hasInput = (discreteAngle >= 0) && (discreteMag > 0.01f);
const bool hasInput = (discreteMag > 0.01f) && (currentAngularVelocity.squaredNorm() > 1e-6f);
// Speed command:
// - Prefer discreteMag (joystick magnitude)
@ -75,37 +72,47 @@ void ClientState::simulate_physics(size_t deltaMs)
// ang = atan2(worldMove.x, worldMove.z)
// So we reconstruct as:
// x = sin(rad), z = cos(rad)
const float rad = DegToRad(static_cast<float>(discreteAngle));
Eigen::Vector3f moveDirWorld = currentAngularVelocity.normalized();
Eigen::Vector3f veccc(0.0f, 0.0f, -1.0f);
Eigen::Vector3f veccc_rotated = rotation * veccc;
Eigen::Vector3f moveDirWorld(
sinf(rad),
0.0f,
cosf(rad)
);
if (moveDirWorld.squaredNorm() > 1e-6f) {
moveDirWorld.normalize();
}
else {
return;
}
// Move in world
position += moveDirWorld * (velocity * dt);
//position += moveDirWorld * (velocity * dt);
position += veccc_rotated * (velocity * dt);
// Rotate ship to face movement direction (optional).
// Ship local forward is (0,0,-1) (as in your fireProjectiles).
// We need yaw so that rotation * (0,0,-1) == moveDirWorld.
// That yaw is: yaw = atan2(-dir.x, -dir.z)
{
float desiredYaw = atan2f(-moveDirWorld.x(), -moveDirWorld.z());
Eigen::Vector3f worldUp(0.0f, 1.0f, 0.0f);
// local forward = (0,0,-1) => значит Z-ось мира должна смотреть в -moveDirWorld
Eigen::Vector3f zAxis = -moveDirWorld;
Eigen::Vector3f xAxis = worldUp.cross(zAxis);
if (xAxis.squaredNorm() < 1e-6f) xAxis = Eigen::Vector3f(1, 0, 0);
xAxis.normalize();
Eigen::Vector3f yAxis = zAxis.cross(xAxis).normalized();
Eigen::Matrix3f R;
R.col(0) = xAxis;
R.col(1) = yAxis;
R.col(2) = zAxis;
Eigen::Quaternionf qCur(rotation);
Eigen::Quaternionf qTar(Eigen::AngleAxisf(desiredYaw, Eigen::Vector3f::UnitY()));
Eigen::Quaternionf qTar(R);
Eigen::Quaternionf qNew = qCur.slerp(ROT_T, qTar).normalized();
rotation = qNew.toRotationMatrix();
}
}
void ClientState::apply_lag_compensation(std::chrono::system_clock::time_point nowTime)