mgba/res/scripts/analog-interpolate.lua

78 lines
1.9 KiB
Lua

local state = {}
state.period = 4
state.phase = 0
state.x = 0
state.y = 0
function state.update()
state.phase = state.phase + 1
if state.phase == state.period then
state.phase = 0
end
if state.phase == 0 then
if input.activeGamepad then
local x = input.activeGamepad.axes[1] / 30000
local y = input.activeGamepad.axes[2] / 30000
-- Map the circle onto a square, since we don't
-- want to have a duty of 1/sqrt(2) on the angles
local theta = math.atan(y, x)
local r = math.sqrt(x * x + y * y)
if theta < math.pi * -3 / 4 then
r = -r / math.cos(theta)
elseif theta < math.pi * -1 / 4 then
r = -r / math.sin(theta)
elseif theta < math.pi * 1 / 4 then
r = r / math.cos(theta)
elseif theta < math.pi * 3 / 4 then
r = r / math.sin(theta)
elseif theta < math.pi * 5 / 4 then
r = -r / math.cos(theta)
end
state.x = math.cos(theta) * r
state.y = math.sin(theta) * r
else
state.x = 0
state.y = 0
end
end
end
function state.read()
emu:clearKeys(0xF0)
if math.floor(math.abs(state.x) * state.period) > state.phase then
if state.x > 0 then
emu:addKey(C.GB_KEY.RIGHT)
else
emu:addKey(C.GB_KEY.LEFT)
end
end
if math.floor(math.abs(state.y) * state.period) > state.phase then
if state.y > 0 then
emu:addKey(C.GB_KEY.DOWN)
else
emu:addKey(C.GB_KEY.UP)
end
end
-- The duty cycle approach can confuse menus and the like,
-- so the POV hat setting should force a direction on
if input.activeGamepad and #input.activeGamepad.hats > 0 then
local hat = input.activeGamepad.hats[1]
if hat & C.INPUT_DIR.UP ~= 0 then
emu:addKey(C.GB_KEY.UP)
end
if hat & C.INPUT_DIR.DOWN ~= 0 then
emu:addKey(C.GB_KEY.DOWN)
end
if hat & C.INPUT_DIR.LEFT ~= 0 then
emu:addKey(C.GB_KEY.LEFT)
end
if hat & C.INPUT_DIR.RIGHT ~= 0 then
emu:addKey(C.GB_KEY.RIGHT)
end
end
end
callbacks:add("frame", state.update)
callbacks:add("keysRead", state.read)