feat: implement per-frame mouse look for reduced input latency on Windows
This commit is contained in:
@@ -128,17 +128,23 @@ void Input::tick(LocalPlayer *player)
|
|||||||
player->interpolateTurn(tx * abs(tx) * turnSpeed, ty * abs(ty) * turnSpeed);
|
player->interpolateTurn(tx * abs(tx) * turnSpeed, ty * abs(ty) * turnSpeed);
|
||||||
|
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
// Mouse look (added after stick-based turn)
|
// Mouse look is now handled per-frame in Minecraft::applyFrameMouseLook()
|
||||||
|
// to eliminate the 20Hz tick delay. Only flush any remaining delta here
|
||||||
|
// as a safety measure.
|
||||||
if (iPad == 0 && KMInput.IsCaptured())
|
if (iPad == 0 && KMInput.IsCaptured())
|
||||||
{
|
{
|
||||||
float mouseSensitivity = 0.5f;
|
|
||||||
float rawDx, rawDy;
|
float rawDx, rawDy;
|
||||||
KMInput.ConsumeMouseDelta(rawDx, rawDy);
|
KMInput.ConsumeMouseDelta(rawDx, rawDy);
|
||||||
float mdx = rawDx * mouseSensitivity;
|
// Delta should normally be 0 since applyFrameMouseLook() already consumed it
|
||||||
float mdy = -rawDy * mouseSensitivity;
|
if (rawDx != 0.0f || rawDy != 0.0f)
|
||||||
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
|
{
|
||||||
mdy = -mdy;
|
float mouseSensitivity = 0.5f;
|
||||||
player->interpolateTurn(mdx, mdy);
|
float mdx = rawDx * mouseSensitivity;
|
||||||
|
float mdy = -rawDy * mouseSensitivity;
|
||||||
|
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
|
||||||
|
mdy = -mdy;
|
||||||
|
player->interpolateTurn(mdx, mdy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1223,6 +1223,53 @@ void Minecraft::createPrimaryLocalPlayer(int iPad)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
void Minecraft::applyFrameMouseLook()
|
||||||
|
{
|
||||||
|
// Per-frame mouse look: consume mouse deltas every frame instead of waiting
|
||||||
|
// for the 20Hz game tick. Apply the same delta to both xRot/yRot AND xRotO/yRotO
|
||||||
|
// so the render interpolation instantly reflects the change without waiting for a tick.
|
||||||
|
if (level == NULL) return;
|
||||||
|
|
||||||
|
for (int i = 0; i < XUSER_MAX_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (localplayers[i] == NULL) continue;
|
||||||
|
int iPad = localplayers[i]->GetXboxPad();
|
||||||
|
if (iPad != 0) continue; // Mouse only applies to pad 0
|
||||||
|
|
||||||
|
if (!KMInput.IsCaptured()) continue;
|
||||||
|
if (localgameModes[iPad] == NULL) continue;
|
||||||
|
|
||||||
|
float rawDx, rawDy;
|
||||||
|
KMInput.ConsumeMouseDelta(rawDx, rawDy);
|
||||||
|
if (rawDx == 0.0f && rawDy == 0.0f) continue;
|
||||||
|
|
||||||
|
float mouseSensitivity = 0.5f;
|
||||||
|
float mdx = rawDx * mouseSensitivity;
|
||||||
|
float mdy = -rawDy * mouseSensitivity;
|
||||||
|
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
|
||||||
|
mdy = -mdy;
|
||||||
|
|
||||||
|
// Apply 0.15f scaling (same as Entity::interpolateTurn / Entity::turn)
|
||||||
|
float dyaw = mdx * 0.15f;
|
||||||
|
float dpitch = -mdy * 0.15f;
|
||||||
|
|
||||||
|
// Apply to both current and old rotation so render interpolation
|
||||||
|
// reflects the change immediately (no 50ms tick delay)
|
||||||
|
localplayers[i]->yRot += dyaw;
|
||||||
|
localplayers[i]->yRotO += dyaw;
|
||||||
|
localplayers[i]->xRot += dpitch;
|
||||||
|
localplayers[i]->xRotO += dpitch;
|
||||||
|
|
||||||
|
// Clamp pitch
|
||||||
|
if (localplayers[i]->xRot < -90.0f) localplayers[i]->xRot = -90.0f;
|
||||||
|
if (localplayers[i]->xRot > 90.0f) localplayers[i]->xRot = 90.0f;
|
||||||
|
if (localplayers[i]->xRotO < -90.0f) localplayers[i]->xRotO = -90.0f;
|
||||||
|
if (localplayers[i]->xRotO > 90.0f) localplayers[i]->xRotO = 90.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Minecraft::run_middle()
|
void Minecraft::run_middle()
|
||||||
{
|
{
|
||||||
static __int64 lastTime = 0;
|
static __int64 lastTime = 0;
|
||||||
|
|||||||
@@ -217,6 +217,9 @@ public:
|
|||||||
static Minecraft *GetInstance();
|
static Minecraft *GetInstance();
|
||||||
void run_middle();
|
void run_middle();
|
||||||
void run_end();
|
void run_end();
|
||||||
|
#ifdef _WINDOWS64
|
||||||
|
void applyFrameMouseLook(); // Per-frame mouse look to reduce input latency
|
||||||
|
#endif
|
||||||
|
|
||||||
void emergencySave();
|
void emergencySave();
|
||||||
|
|
||||||
|
|||||||
@@ -1077,6 +1077,7 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
|
|||||||
// Render game graphics.
|
// Render game graphics.
|
||||||
if(app.GetGameStarted())
|
if(app.GetGameStarted())
|
||||||
{
|
{
|
||||||
|
pMinecraft->applyFrameMouseLook(); // Per-frame mouse look (before ticks + render)
|
||||||
pMinecraft->run_middle();
|
pMinecraft->run_middle();
|
||||||
app.SetAppPaused( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 && ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()) );
|
app.SetAppPaused( g_NetworkManager.IsLocalGame() && g_NetworkManager.GetPlayerCount() == 1 && ui.IsPauseMenuDisplayed(ProfileManager.GetPrimaryPad()) );
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user