fixed rotation moving
This commit is contained in:
parent
fb4a860773
commit
d76342f3fa
108
src/Game.cpp
108
src/Game.cpp
@ -687,48 +687,78 @@ namespace ZL
|
|||||||
bool joystickActive = isUsingJoystick && joystick && joystick->isActive;
|
bool joystickActive = isUsingJoystick && joystick && joystick->isActive;
|
||||||
|
|
||||||
if (joystickActive) {
|
if (joystickActive) {
|
||||||
float joyX = -joystick->getDirectionX(); // -1..1
|
float joyX = joystick->getDirectionX(); // <-- оставляем инверсию X
|
||||||
float joyY = joystick->getDirectionY(); // -1..1 (вверх обычно отрицательный)
|
float joyY = joystick->getDirectionY();
|
||||||
float magnitude = joystick->getMagnitude();
|
float magnitude = joystick->getMagnitude();
|
||||||
|
|
||||||
const float deadzone = 0.1f;
|
const float deadzone = 0.1f;
|
||||||
|
|
||||||
|
Vector3f newMoveDir = Vector3f::Zero();
|
||||||
|
float newMag = 0.0f;
|
||||||
|
|
||||||
if (magnitude > deadzone) {
|
if (magnitude > deadzone) {
|
||||||
|
|
||||||
// forward/right из ТЕКУЩЕГО camYaw (без lock)
|
// Берём ориентацию камеры из view matrix:
|
||||||
Vector3f forward(-sinf(camYaw), 0.0f, -cosf(camYaw));
|
// view = World -> View, значит Rcw = (Rwv)^T = View -> World
|
||||||
Vector3f right(cosf(camYaw), 0.0f, -sinf(camYaw));
|
Matrix4f viewM = camera.getViewMatrix();
|
||||||
|
Matrix3f Rwv = viewM.block<3, 3>(0, 0);
|
||||||
|
Matrix3f Rcw = Rwv.transpose();
|
||||||
|
|
||||||
// joyY: если вверх = отрицательный, то "- forward * joyY" даёт движение вперёд при joyY<0
|
Vector3f camRight = (Rcw * Vector3f(1, 0, 0));
|
||||||
Vector3f worldMove = right * joyX - forward * joyY;
|
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) {
|
if (worldMove.squaredNorm() > 1e-6f) {
|
||||||
worldMove.normalize();
|
newMoveDir = worldMove.normalized();
|
||||||
|
newMag = (std::min)(magnitude, 1.0f);
|
||||||
float ang = atan2f(worldMove.x(), worldMove.z()); // 0 -> +Z
|
newMag = std::round(newMag * 10.0f) / 10.0f;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Применяем в 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
|
// Network Update
|
||||||
bool changed = false;
|
//bool changed = false;
|
||||||
|
|
||||||
if (discreteAngle != Environment::shipState.discreteAngle) {
|
//if (discreteAngle != Environment::shipState.discreteAngle) {
|
||||||
Environment::shipState.discreteAngle = discreteAngle;
|
// Environment::shipState.discreteAngle = discreteAngle;
|
||||||
changed = true;
|
// changed = true;
|
||||||
}
|
//}
|
||||||
if (discreteMag != Environment::shipState.discreteMag) {
|
//if (discreteMag != Environment::shipState.discreteMag) {
|
||||||
Environment::shipState.discreteMag = discreteMag;
|
// Environment::shipState.discreteMag = discreteMag;
|
||||||
changed = true;
|
// changed = true;
|
||||||
}
|
//}
|
||||||
|
|
||||||
// slider value применяем здесь (ты раньше только newShipVelocity менял)
|
// slider value применяем здесь (ты раньше только newShipVelocity менял)
|
||||||
//int newVelInt = (int)newShipVelocity;
|
//int newVelInt = (int)newShipVelocity;
|
||||||
@ -737,9 +767,27 @@ namespace ZL
|
|||||||
// changed = true;
|
// changed = true;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if (changed) {
|
//if (changed) {
|
||||||
std::string msg = "UPD:" + std::to_string(now_ms) + ":" + Environment::shipState.formPingMessageContent();
|
// std::string msg = "UPD:" + std::to_string(now_ms) + ":" + Environment::shipState.formPingMessageContent();
|
||||||
networkClient->Send(msg);
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
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
|
// Input validity
|
||||||
const bool hasInput = (discreteAngle >= 0) && (discreteMag > 0.01f);
|
const bool hasInput = (discreteMag > 0.01f) && (currentAngularVelocity.squaredNorm() > 1e-6f);
|
||||||
|
|
||||||
// Speed command:
|
// Speed command:
|
||||||
// - Prefer discreteMag (joystick magnitude)
|
// - Prefer discreteMag (joystick magnitude)
|
||||||
@ -75,37 +72,47 @@ void ClientState::simulate_physics(size_t deltaMs)
|
|||||||
// ang = atan2(worldMove.x, worldMove.z)
|
// ang = atan2(worldMove.x, worldMove.z)
|
||||||
// So we reconstruct as:
|
// So we reconstruct as:
|
||||||
// x = sin(rad), z = cos(rad)
|
// 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
|
// Move in world
|
||||||
position += moveDirWorld * (velocity * dt);
|
//position += moveDirWorld * (velocity * dt);
|
||||||
|
position += veccc_rotated * (velocity * dt);
|
||||||
|
|
||||||
// Rotate ship to face movement direction (optional).
|
// Rotate ship to face movement direction (optional).
|
||||||
// Ship local forward is (0,0,-1) (as in your fireProjectiles).
|
// Ship local forward is (0,0,-1) (as in your fireProjectiles).
|
||||||
// We need yaw so that rotation * (0,0,-1) == moveDirWorld.
|
// We need yaw so that rotation * (0,0,-1) == moveDirWorld.
|
||||||
// That yaw is: yaw = atan2(-dir.x, -dir.z)
|
// 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 qCur(rotation);
|
||||||
Eigen::Quaternionf qTar(Eigen::AngleAxisf(desiredYaw, Eigen::Vector3f::UnitY()));
|
Eigen::Quaternionf qTar(R);
|
||||||
|
|
||||||
Eigen::Quaternionf qNew = qCur.slerp(ROT_T, qTar).normalized();
|
Eigen::Quaternionf qNew = qCur.slerp(ROT_T, qTar).normalized();
|
||||||
rotation = qNew.toRotationMatrix();
|
rotation = qNew.toRotationMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientState::apply_lag_compensation(std::chrono::system_clock::time_point nowTime)
|
void ClientState::apply_lag_compensation(std::chrono::system_clock::time_point nowTime)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user