mobile spin fix
DramaticShape · 2026-08-02 ·
parent 9ef8644bff
mobile spin fix
Changed files
lib/FirstPerson.lua | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
Diff
diff --git a/lib/FirstPerson.lua b/lib/FirstPerson.lua
index 7722adb..d1019b4 100644
--- a/lib/FirstPerson.lua
+++ b/lib/FirstPerson.lua
@@ -528,13 +528,35 @@ function FirstPerson.install()
-- pair on the same class of device. Real gamepads are excluded -- they
-- already spoke through the mapped rightx/righty above, and their RAW
-- axis 3 is as likely a trigger as a stick.
+ --
+ -- Two more exclusions, both learned the hard way on Android, where this
+ -- wrap runs BEFORE the engine's own generic-joystick guards:
+ --
+ -- the accelerometer arrives as a joystick named for what it is, with
+ -- gravity pinning an axis well past any deadzone -- the same device
+ -- Game:joystickaxis refuses for movement (#459), refused here by the
+ -- same name test, or the view spins on its own the moment 1ST opens.
+ --
+ -- and a raw axis is only BELIEVED after it has been seen near centre
+ -- once. A stick at rest sits at zero, so a real one earns trust with
+ -- its first touch; a gravity-pinned sensor axis or a trigger resting
+ -- at an extreme never centres and so never steers the look.
+ local function isAccelerometer(joystick)
+ local ok, name = pcall(function() return joystick:getName() end)
+ return ok and type(name) == "string"
+ and name:lower():find("accelerometer", 1, true) ~= nil
+ end
+ local rawCentred = {}
do
local inner = Game.joystickaxis
function Game:joystickaxis(joystick, axis, value)
local mapped = joystick and joystick.isGamepad and joystick:isGamepad()
- if not mapped then
- if axis == 3 then stick.x = value
- elseif axis == 4 then stick.y = value end
+ if not mapped and (axis == 3 or axis == 4)
+ and not isAccelerometer(joystick) then
+ if math.abs(value) < 0.3 then rawCentred[axis] = true end
+ if rawCentred[axis] then
+ if axis == 3 then stick.x = value else stick.y = value end
+ end
end
return inner(self, joystick, axis, value)
end
@@ -675,6 +697,17 @@ function FirstPerson.install()
return inner(self, f)
end
end
+ -- a disconnected controller cannot send the centering event for whatever
+ -- its stick last held -- the engine drops all input state here, and the
+ -- look rate (plus the raw axes' earned trust) goes with it
+ do
+ local inner = Game.joystickremoved
+ function Game:joystickremoved(joystick)
+ stick.x, stick.y = 0, 0
+ rawCentred[3], rawCentred[4] = nil, nil
+ return inner(self, joystick)
+ end
+ end
end
return FirstPerson