oma-tank/game/input.lua
2026-04-18 11:35:06 +01:00

136 lines
3.4 KiB
Lua

-- Input abstraction: normalises keyboard (classic dual-track / modern simplified)
-- and gamepad (always dual-stick) into a pair of track values in [-1, 1].
local Input = {}
local SETTINGS_FILE = "oma-tank_settings.dat"
local STICK_DEADZONE = 0.18
local mode = "modern"
local joystick = nil
local function clamp(v)
if v < -1 then return -1 end
if v > 1 then return 1 end
return v
end
local function keyPair(positive, negative)
local v = 0
if love.keyboard.isDown(positive) then v = v + 1 end
if love.keyboard.isDown(negative) then v = v - 1 end
return v
end
local function modernTracks()
-- Up/Down drive both tracks, Left/Right split them
local fwd = 0
if love.keyboard.isDown("up", "w") then fwd = fwd + 1 end
if love.keyboard.isDown("down", "s") then fwd = fwd - 1 end
local turn = 0
if love.keyboard.isDown("right", "d") then turn = turn + 1 end
if love.keyboard.isDown("left", "a") then turn = turn - 1 end
-- Reverse at 50% feel: matches the prior simplified control
if fwd < 0 then fwd = fwd * 0.5 end
local left = clamp(fwd + turn)
local right = clamp(fwd - turn)
return left, right
end
local function classicTracks()
-- W/S = left track, I/K = right track
local left = keyPair("w", "s")
local right = keyPair("i", "k")
return clamp(left), clamp(right)
end
local function applyDeadzone(v)
if math.abs(v) < STICK_DEADZONE then return 0 end
return v
end
local function gamepadTracks()
if not joystick then return 0, 0 end
-- Stick Y axis is positive down on most gamepads; flip so "forward" on the stick = +1
local left = -applyDeadzone(joystick:getGamepadAxis("lefty"))
local right = -applyDeadzone(joystick:getGamepadAxis("righty"))
return clamp(left), clamp(right)
end
function Input.tracks()
local kl, kr
if mode == "classic" then
kl, kr = classicTracks()
else
kl, kr = modernTracks()
end
local gl, gr = gamepadTracks()
-- If either source is pushing a stick, prefer gamepad values for that track
local left = (gl ~= 0) and gl or kl
local right = (gr ~= 0) and gr or kr
return left, right
end
function Input.setMode(newMode)
if newMode == "classic" or newMode == "modern" then
mode = newMode
Input.save()
end
end
function Input.getMode()
return mode
end
function Input.toggleMode()
mode = (mode == "classic") and "modern" or "classic"
Input.save()
end
function Input.label()
return (mode == "classic") and "CLASSIC DUAL-TRACK" or "MODERN SIMPLIFIED"
end
function Input.save()
pcall(function()
love.filesystem.write(SETTINGS_FILE, "mode=" .. mode .. "\n")
end)
end
function Input.load()
if love.filesystem.getInfo(SETTINGS_FILE) then
local ok, content = pcall(love.filesystem.read, SETTINGS_FILE)
if ok and content then
local m = content:match("mode=(%w+)")
if m == "classic" or m == "modern" then mode = m end
end
end
end
function Input.attachJoystick()
local joysticks = love.joystick.getJoysticks()
for _, js in ipairs(joysticks) do
if js:isGamepad() then
joystick = js
return
end
end
joystick = nil
end
function Input.joystickAdded(js)
if js:isGamepad() and not joystick then
joystick = js
end
end
function Input.joystickRemoved(js)
if joystick == js then
joystick = nil
Input.attachJoystick()
end
end
return Input