feat: implement game-tick input handling and per-frame edge detection
This commit is contained in:
@@ -131,9 +131,11 @@ void Input::tick(LocalPlayer *player)
|
|||||||
// Mouse look (added after stick-based turn)
|
// Mouse look (added after stick-based turn)
|
||||||
if (iPad == 0 && KMInput.IsCaptured())
|
if (iPad == 0 && KMInput.IsCaptured())
|
||||||
{
|
{
|
||||||
float mouseSensitivity = 1.25f;
|
float mouseSensitivity = 0.5f;
|
||||||
float mdx = KMInput.GetMouseDeltaX() * mouseSensitivity;
|
float rawDx, rawDy;
|
||||||
float mdy = -KMInput.GetMouseDeltaY() * mouseSensitivity;
|
KMInput.ConsumeMouseDelta(rawDx, rawDy);
|
||||||
|
float mdx = rawDx * mouseSensitivity;
|
||||||
|
float mdy = -rawDy * mouseSensitivity;
|
||||||
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
|
if (app.GetGameSettings(iPad, eGameSetting_ControlInvertLook))
|
||||||
mdy = -mdy;
|
mdy = -mdy;
|
||||||
player->interpolateTurn(mdx, mdy);
|
player->interpolateTurn(mdx, mdy);
|
||||||
|
|||||||
@@ -1456,11 +1456,11 @@ void Minecraft::run_middle()
|
|||||||
// Keyboard/mouse button presses for player 0
|
// Keyboard/mouse button presses for player 0
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
if (KMInput.IsKeyPressed(VK_ESCAPE)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_PAUSEMENU;
|
if (KMInput.ConsumeKeyPress(VK_ESCAPE)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_PAUSEMENU;
|
||||||
if (KMInput.IsKeyPressed('E')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_INVENTORY;
|
if (KMInput.ConsumeKeyPress('E')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_INVENTORY;
|
||||||
if (KMInput.IsKeyPressed('Q')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_DROP;
|
if (KMInput.ConsumeKeyPress('Q')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_DROP;
|
||||||
if (KMInput.IsKeyPressed('C')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_CRAFTING;
|
if (KMInput.ConsumeKeyPress('C')) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_CRAFTING;
|
||||||
if (KMInput.IsKeyPressed(VK_F5)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON;
|
if (KMInput.ConsumeKeyPress(VK_F5)) localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_RENDER_THIRD_PERSON;
|
||||||
// In flying mode, Shift held = sneak/descend
|
// In flying mode, Shift held = sneak/descend
|
||||||
if (localplayers[i]->abilities.flying && KMInput.IsKeyDown(VK_SHIFT))
|
if (localplayers[i]->abilities.flying && KMInput.IsKeyDown(VK_SHIFT))
|
||||||
localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE;
|
localplayers[i]->ullButtonsPressed |= 1LL<<MINECRAFT_ACTION_SNEAK_TOGGLE;
|
||||||
@@ -3197,7 +3197,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
|||||||
// Mouse scroll wheel for hotbar
|
// Mouse scroll wheel for hotbar
|
||||||
if (iPad == 0)
|
if (iPad == 0)
|
||||||
{
|
{
|
||||||
int kbWheel = KMInput.GetScrollDelta();
|
int kbWheel = KMInput.ConsumeScrollDelta();
|
||||||
if (kbWheel > 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL)) wheel += 1;
|
if (kbWheel > 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_LEFT_SCROLL)) wheel += 1;
|
||||||
else if (kbWheel < 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_RIGHT_SCROLL)) wheel -= 1;
|
else if (kbWheel < 0 && gameMode->isInputAllowed(MINECRAFT_ACTION_RIGHT_SCROLL)) wheel -= 1;
|
||||||
|
|
||||||
@@ -3206,7 +3206,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
|||||||
{
|
{
|
||||||
for (int k = '1'; k <= '9'; k++)
|
for (int k = '1'; k <= '9'; k++)
|
||||||
{
|
{
|
||||||
if (KMInput.IsKeyPressed(k))
|
if (KMInput.ConsumeKeyPress(k))
|
||||||
{
|
{
|
||||||
player->inventory->selected = k - '1';
|
player->inventory->selected = k - '1';
|
||||||
app.SetOpacityTimer(iPad);
|
app.SetOpacityTimer(iPad);
|
||||||
@@ -3248,7 +3248,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures)
|
|||||||
player->lastClickTick[0] = ticks;
|
player->lastClickTick[0] = ticks;
|
||||||
}
|
}
|
||||||
#ifdef _WINDOWS64
|
#ifdef _WINDOWS64
|
||||||
else if (iPad == 0 && KMInput.IsCaptured() && KMInput.IsMousePressed(0))
|
else if (iPad == 0 && KMInput.IsCaptured() && KMInput.ConsumeMousePress(0))
|
||||||
{
|
{
|
||||||
player->handleMouseClick(0);
|
player->handleMouseClick(0);
|
||||||
player->lastClickTick[0] = ticks;
|
player->lastClickTick[0] = ticks;
|
||||||
|
|||||||
Binary file not shown.
@@ -7,11 +7,8 @@
|
|||||||
KeyboardMouseInput KMInput;
|
KeyboardMouseInput KMInput;
|
||||||
|
|
||||||
KeyboardMouseInput::KeyboardMouseInput()
|
KeyboardMouseInput::KeyboardMouseInput()
|
||||||
: m_mouseDeltaX(0.0f)
|
: m_mouseDeltaXAccum(0.0f)
|
||||||
, m_mouseDeltaY(0.0f)
|
|
||||||
, m_mouseDeltaXAccum(0.0f)
|
|
||||||
, m_mouseDeltaYAccum(0.0f)
|
, m_mouseDeltaYAccum(0.0f)
|
||||||
, m_scrollDelta(0)
|
|
||||||
, m_scrollDeltaAccum(0)
|
, m_scrollDeltaAccum(0)
|
||||||
, m_captured(false)
|
, m_captured(false)
|
||||||
, m_hWnd(NULL)
|
, m_hWnd(NULL)
|
||||||
@@ -21,6 +18,8 @@ KeyboardMouseInput::KeyboardMouseInput()
|
|||||||
memset(m_keyStatePrev, 0, sizeof(m_keyStatePrev));
|
memset(m_keyStatePrev, 0, sizeof(m_keyStatePrev));
|
||||||
memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
|
memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
|
||||||
memset(m_mouseButtonsPrev, 0, sizeof(m_mouseButtonsPrev));
|
memset(m_mouseButtonsPrev, 0, sizeof(m_mouseButtonsPrev));
|
||||||
|
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
|
||||||
|
memset(m_mousePressedAccum, 0, sizeof(m_mousePressedAccum));
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyboardMouseInput::~KeyboardMouseInput()
|
KeyboardMouseInput::~KeyboardMouseInput()
|
||||||
@@ -47,16 +46,6 @@ void KeyboardMouseInput::Init(HWND hWnd)
|
|||||||
|
|
||||||
void KeyboardMouseInput::Tick()
|
void KeyboardMouseInput::Tick()
|
||||||
{
|
{
|
||||||
// Snapshot accumulated mouse deltas
|
|
||||||
m_mouseDeltaX = m_mouseDeltaXAccum;
|
|
||||||
m_mouseDeltaY = m_mouseDeltaYAccum;
|
|
||||||
m_mouseDeltaXAccum = 0.0f;
|
|
||||||
m_mouseDeltaYAccum = 0.0f;
|
|
||||||
|
|
||||||
// Snapshot scroll delta
|
|
||||||
m_scrollDelta = m_scrollDeltaAccum;
|
|
||||||
m_scrollDeltaAccum = 0;
|
|
||||||
|
|
||||||
// Keep cursor pinned to center while captured
|
// Keep cursor pinned to center while captured
|
||||||
if (m_captured)
|
if (m_captured)
|
||||||
CenterCursor();
|
CenterCursor();
|
||||||
@@ -65,7 +54,7 @@ void KeyboardMouseInput::Tick()
|
|||||||
void KeyboardMouseInput::EndFrame()
|
void KeyboardMouseInput::EndFrame()
|
||||||
{
|
{
|
||||||
// Advance previous state for next frame's edge detection.
|
// Advance previous state for next frame's edge detection.
|
||||||
// Must be called AFTER all consumers have read IsKeyPressed/Released etc.
|
// Must be called AFTER all per-frame consumers have read IsKeyPressed/Released etc.
|
||||||
memcpy(m_keyStatePrev, m_keyState, sizeof(m_keyState));
|
memcpy(m_keyStatePrev, m_keyState, sizeof(m_keyState));
|
||||||
memcpy(m_mouseButtonsPrev, m_mouseButtons, sizeof(m_mouseButtons));
|
memcpy(m_mouseButtonsPrev, m_mouseButtons, sizeof(m_mouseButtons));
|
||||||
}
|
}
|
||||||
@@ -74,6 +63,7 @@ void KeyboardMouseInput::OnKeyDown(WPARAM vk)
|
|||||||
{
|
{
|
||||||
if (vk < 256)
|
if (vk < 256)
|
||||||
{
|
{
|
||||||
|
if (!m_keyState[vk]) m_keyPressedAccum[vk] = true;
|
||||||
m_keyState[vk] = true;
|
m_keyState[vk] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,6 +102,7 @@ void KeyboardMouseInput::OnMouseButton(int button, bool down)
|
|||||||
{
|
{
|
||||||
if (button >= 0 && button < 3)
|
if (button >= 0 && button < 3)
|
||||||
{
|
{
|
||||||
|
if (down && !m_mouseButtons[button]) m_mousePressedAccum[button] = true;
|
||||||
m_mouseButtons[button] = down;
|
m_mouseButtons[button] = down;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,12 +116,14 @@ void KeyboardMouseInput::ClearAllState()
|
|||||||
{
|
{
|
||||||
memset(m_keyState, 0, sizeof(m_keyState));
|
memset(m_keyState, 0, sizeof(m_keyState));
|
||||||
memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
|
memset(m_mouseButtons, 0, sizeof(m_mouseButtons));
|
||||||
|
memset(m_keyPressedAccum, 0, sizeof(m_keyPressedAccum));
|
||||||
|
memset(m_mousePressedAccum, 0, sizeof(m_mousePressedAccum));
|
||||||
m_mouseDeltaXAccum = 0.0f;
|
m_mouseDeltaXAccum = 0.0f;
|
||||||
m_mouseDeltaYAccum = 0.0f;
|
m_mouseDeltaYAccum = 0.0f;
|
||||||
m_scrollDeltaAccum = 0;
|
m_scrollDeltaAccum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key queries
|
// Per-frame key queries
|
||||||
bool KeyboardMouseInput::IsKeyDown(int vk) const
|
bool KeyboardMouseInput::IsKeyDown(int vk) const
|
||||||
{
|
{
|
||||||
if (vk < 0 || vk >= 256) return false;
|
if (vk < 0 || vk >= 256) return false;
|
||||||
@@ -149,7 +142,7 @@ bool KeyboardMouseInput::IsKeyReleased(int vk) const
|
|||||||
return !m_keyState[vk] && m_keyStatePrev[vk];
|
return !m_keyState[vk] && m_keyStatePrev[vk];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mouse button queries
|
// Per-frame mouse button queries
|
||||||
bool KeyboardMouseInput::IsMouseDown(int btn) const
|
bool KeyboardMouseInput::IsMouseDown(int btn) const
|
||||||
{
|
{
|
||||||
if (btn < 0 || btn >= 3) return false;
|
if (btn < 0 || btn >= 3) return false;
|
||||||
@@ -168,10 +161,37 @@ bool KeyboardMouseInput::IsMouseReleased(int btn) const
|
|||||||
return !m_mouseButtons[btn] && m_mouseButtonsPrev[btn];
|
return !m_mouseButtons[btn] && m_mouseButtonsPrev[btn];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delta queries
|
// Game-tick consume methods
|
||||||
float KeyboardMouseInput::GetMouseDeltaX() const { return m_mouseDeltaX; }
|
bool KeyboardMouseInput::ConsumeKeyPress(int vk)
|
||||||
float KeyboardMouseInput::GetMouseDeltaY() const { return m_mouseDeltaY; }
|
{
|
||||||
int KeyboardMouseInput::GetScrollDelta() const { return m_scrollDelta; }
|
if (vk < 0 || vk >= 256) return false;
|
||||||
|
bool pressed = m_keyPressedAccum[vk];
|
||||||
|
m_keyPressedAccum[vk] = false;
|
||||||
|
return pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyboardMouseInput::ConsumeMousePress(int btn)
|
||||||
|
{
|
||||||
|
if (btn < 0 || btn >= 3) return false;
|
||||||
|
bool pressed = m_mousePressedAccum[btn];
|
||||||
|
m_mousePressedAccum[btn] = false;
|
||||||
|
return pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardMouseInput::ConsumeMouseDelta(float &dx, float &dy)
|
||||||
|
{
|
||||||
|
dx = m_mouseDeltaXAccum;
|
||||||
|
dy = m_mouseDeltaYAccum;
|
||||||
|
m_mouseDeltaXAccum = 0.0f;
|
||||||
|
m_mouseDeltaYAccum = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int KeyboardMouseInput::ConsumeScrollDelta()
|
||||||
|
{
|
||||||
|
int delta = m_scrollDeltaAccum;
|
||||||
|
m_scrollDeltaAccum = 0;
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
// Mouse capture
|
// Mouse capture
|
||||||
void KeyboardMouseInput::SetCapture(bool capture)
|
void KeyboardMouseInput::SetCapture(bool capture)
|
||||||
|
|||||||
@@ -30,20 +30,20 @@ public:
|
|||||||
void OnMouseWheel(int delta);
|
void OnMouseWheel(int delta);
|
||||||
void ClearAllState();
|
void ClearAllState();
|
||||||
|
|
||||||
// Key state queries (call after Tick)
|
// Per-frame edge detection (for UI / per-frame logic like Alt toggle)
|
||||||
bool IsKeyDown(int vk) const;
|
bool IsKeyDown(int vk) const;
|
||||||
bool IsKeyPressed(int vk) const;
|
bool IsKeyPressed(int vk) const;
|
||||||
bool IsKeyReleased(int vk) const;
|
bool IsKeyReleased(int vk) const;
|
||||||
|
|
||||||
// Mouse button queries: 0=left, 1=right, 2=middle
|
|
||||||
bool IsMouseDown(int btn) const;
|
bool IsMouseDown(int btn) const;
|
||||||
bool IsMousePressed(int btn) const;
|
bool IsMousePressed(int btn) const;
|
||||||
bool IsMouseReleased(int btn) const;
|
bool IsMouseReleased(int btn) const;
|
||||||
|
|
||||||
// Mouse deltas (consumed each Tick)
|
// Game-tick consume methods: accumulate across frames, clear on read.
|
||||||
float GetMouseDeltaX() const;
|
// Use these from code that runs at game tick rate (20Hz).
|
||||||
float GetMouseDeltaY() const;
|
bool ConsumeKeyPress(int vk);
|
||||||
int GetScrollDelta() const;
|
bool ConsumeMousePress(int btn);
|
||||||
|
void ConsumeMouseDelta(float &dx, float &dy);
|
||||||
|
int ConsumeScrollDelta();
|
||||||
|
|
||||||
// Mouse capture for FPS look
|
// Mouse capture for FPS look
|
||||||
void SetCapture(bool capture);
|
void SetCapture(bool capture);
|
||||||
@@ -52,18 +52,21 @@ public:
|
|||||||
private:
|
private:
|
||||||
void CenterCursor();
|
void CenterCursor();
|
||||||
|
|
||||||
|
// Per-frame double-buffered state (for IsKeyPressed/Released per-frame edge detection)
|
||||||
bool m_keyState[256];
|
bool m_keyState[256];
|
||||||
bool m_keyStatePrev[256];
|
bool m_keyStatePrev[256];
|
||||||
|
|
||||||
bool m_mouseButtons[3];
|
bool m_mouseButtons[3];
|
||||||
bool m_mouseButtonsPrev[3];
|
bool m_mouseButtonsPrev[3];
|
||||||
|
|
||||||
float m_mouseDeltaX;
|
// Sticky press accumulators (persist until consumed by game tick)
|
||||||
float m_mouseDeltaY;
|
bool m_keyPressedAccum[256];
|
||||||
|
bool m_mousePressedAccum[3];
|
||||||
|
|
||||||
|
// Mouse delta accumulators (persist until consumed by game tick)
|
||||||
float m_mouseDeltaXAccum;
|
float m_mouseDeltaXAccum;
|
||||||
float m_mouseDeltaYAccum;
|
float m_mouseDeltaYAccum;
|
||||||
|
|
||||||
int m_scrollDelta;
|
// Scroll accumulator (persists until consumed by game tick)
|
||||||
int m_scrollDeltaAccum;
|
int m_scrollDeltaAccum;
|
||||||
|
|
||||||
bool m_captured;
|
bool m_captured;
|
||||||
|
|||||||
Reference in New Issue
Block a user