Skip to content

Commit

Permalink
Controller support
Browse files Browse the repository at this point in the history
  • Loading branch information
niamu committed May 24, 2015
1 parent bb26a5b commit 3b0b65c
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 40 deletions.
4 changes: 2 additions & 2 deletions src/conf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ function love.conf(t)
t.title = "Journey to the Center of Hawkthorne v0.0.0"
t.url = "http://projecthawkthorne.com"
t.author = "https://github.com/hawkthorne?tab=members"
t.version = "0.9.0"
t.version = "0.9.1"
t.identity = "hawkthorne"
t.window.width = 1056
t.window.height = 672
t.window.fullscreen = false
t.console = false
t.modules.physics = false
t.modules.joystick = false
t.modules.joystick = true
t.release = false
end
119 changes: 103 additions & 16 deletions src/inputcontroller.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local store = require 'hawk/store'
local utils = require "utils"

local db = store('controls-1')

Expand All @@ -7,15 +8,39 @@ InputController.__index = InputController

local DEFAULT_PRESET = 'actionmap'
local DEFAULT_ACTIONMAP = {
UP = 'up',
DOWN = 'down',
LEFT = 'left',
RIGHT = 'right',
SELECT = 's',
START = 'escape',
JUMP = ' ',
ATTACK = 'a',
INTERACT = 'd',
actionmap = {
UP = 'up',
DOWN = 'down',
LEFT = 'left',
RIGHT = 'right',
SELECT = 's',
START = 'escape',
JUMP = ' ',
ATTACK = 'a',
INTERACT = 'd',
},
gamepad = {
UP = 'dpup',
DOWN = 'dpdown',
LEFT = 'dpleft',
RIGHT = 'dpright',
SELECT = 'back',
START = 'start',
JUMP = 'a',
ATTACK = 'x',
INTERACT = 'y',
},
joystick = {
UP = 'dpup',
DOWN = 'dpdown',
LEFT = 'dpleft',
RIGHT = 'dpright',
SELECT = '1',
START = '4',
JUMP = '2',
ATTACK = '8',
INTERACT = '6',
}
}

local cached = {}
Expand All @@ -31,6 +56,25 @@ function InputController.new(name, actionmap)
return controller
end

function InputController:switch(joystick)
local controller_name = "actionmap"
if joystick and joystick:isGamepad() then
controller_name = joystick:getName() or "gamepad"
elseif joystick and not joystick:isGamepad() then
controller_name = joystick:getName() or "joystick"
end
if remapping then return end
if self.name ~= controller_name then
self.name = controller_name
if controller_name ~= "actionmap" then
self.joystick = joystick
else
self.joystick = nil
end
self:load(self.name)
end
end

-- Return cached global version if available, create otherwise
-- Unless trying to make a new or custom preset, just use this, not new
function InputController.get(name)
Expand All @@ -42,16 +86,30 @@ function InputController.get(name)
end

-- Classmethod to return a preset table from db
function InputController.getPreset(name)
function InputController:getPreset(name)
local function defaultMap(name)
if not DEFAULT_ACTIONMAP[name] then
if self.joystick and self.joystick:isGamepad() then
return DEFAULT_ACTIONMAP["gamepad"]
elseif self.joystick and not self.joystick:isGamepad() then
return DEFAULT_ACTIONMAP["joystick"]
end
end

return DEFAULT_ACTIONMAP[name]
end

local mapname = name or DEFAULT_PRESET
return db:get(mapname, DEFAULT_ACTIONMAP)
return db:get(mapname, defaultMap(name))
end

-- actionmap is optional param; if nil, we load preset with controller name
function InputController:load(actionmap)
-- Copy to avoid modifying external tables
local source = actionmap or self.getPreset(self.name)
if type(actionmap) ~= "table" then actionmap = nil end
local source = actionmap or self:getPreset(self.name)
self.actionmap = {}

for k, v in pairs(source) do
self.actionmap[k] = v
end
Expand Down Expand Up @@ -86,6 +144,8 @@ end

-- Get action for a given physical key
function InputController:getAction( key )
if key == "return" then return "JUMP" end
if key == "escape" then return "START" end
return self.keymap[key]
end

Expand All @@ -94,9 +154,7 @@ end
function InputController:getKey( action )
local key = self.actionmap[action]

if key == " " then
return "space"
end
if key == " " then return "space" end

return key
end
Expand All @@ -108,6 +166,29 @@ function InputController:isDown( action )
return false
end

if self.joystick then
if self.joystick:isGamepad() then
return self.joystick:isGamepadDown(key)
else
print("joystick:",type(key),key,action)
axisDir1, axisDir2, _ = self.joystick:getAxes()
if axisDir1 < 0 then
if action == "LEFT" then return true end
end
if axisDir1 > 0 then
if action == "RIGHT" then return true end
end
if axisDir2 < 0 then
if action == "UP" then return true end
end
if axisDir2 > 0 then
if action == "DOWN" then return true end
end
if type(tonumber(key)) ~= "number" then return false end
return self.joystick:isDown(tonumber(key))
end
end

return love.keyboard.isDown(key)
end

Expand Down Expand Up @@ -136,7 +217,13 @@ end
-- Reassigns key to action and returns true, or returns false if the key is unavailable.
-- Does not automatically save after modification.
function InputController:newAction(key, action)
if key == "return" and action ~= "JUMP" or
key == "escape" and action ~= "START" then
return false
end
if self:getAction(key) == action then
self.actionmap[action] = key
self:refreshKeymap()
return true
end

Expand All @@ -149,4 +236,4 @@ function InputController:newAction(key, action)
end
end

return InputController
return InputController
12 changes: 11 additions & 1 deletion src/instructions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ function state:draw()
for i, button in ipairs(menu.options) do
local y = self.top + self.spacing * (i - 1)
local key = controls:getKey(button)

-- Show default global keys if they aren't already assigned
if button == "START" and key ~= "escape" then key = key .. " / ESCAPE" end
if button == "JUMP" and key ~= "return" then key = key .. " / ENTER" end

love.graphics.print(descriptions[button], self.left_column, y, 0, 0.5)
love.graphics.print(key, self.right_column, y, 0, 0.5)
end
Expand All @@ -113,7 +118,12 @@ function state:remapKey(key)
self.statusText = "KEY IS ALREADY IN USE"
else
if key == ' ' then key = 'space' end
assert(controls:getKey(button) == key)
-- Don't bother checking for the RETURN or ESCAPE key as they are globals
if key ~= 'return' and key ~= 'escape' then
assert(controls:getKey(button) == key)
end
if button == "START" and key ~= "escape" then key = key .. " or ESCAPE" end
if button == "JUMP" and key ~= "return" then key = key .. " or ENTER" end
self.statusText = button .. ": " .. key
end
controls:disableRemap()
Expand Down
44 changes: 40 additions & 4 deletions src/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function love.load(arg)
error("invalid version label")
end

if(not love.version == "0.9.1") then
if love._version ~= "0.9.1" then
error("Love 0.9.1 is required")
end

Expand Down Expand Up @@ -206,7 +206,7 @@ function love.update(dt)
end
end

function love.keyreleased(key)
function buttonreleased(key)
if testing then return end
local action = controls:getAction(key)
if action then Gamestate.keyreleased(action) end
Expand All @@ -220,7 +220,7 @@ function love.keyreleased(key)
end
end

function love.keypressed(key)
function buttonpressed(key)
if testing then return end
if controls:isRemapping() then Gamestate.keypressed(key) return end
if key == 'f5' then debugger:toggle() end
Expand All @@ -238,6 +238,42 @@ function love.keypressed(key)
end
end

function love.keyreleased(key)
buttonreleased(key)
end

function love.keypressed(key)
controls:switch()
buttonpressed(key)
end

function love.gamepadreleased(joystick, key)
buttonreleased(key)
end

function love.gamepadpressed(joystick, key)
controls:switch(joystick)
buttonpressed(key)
end

function love.joystickreleased(joystick, key)
buttonreleased(tostring(key))
end

function love.joystickpressed(joystick, key)
controls:switch(joystick)
buttonpressed(tostring(key))
end

function love.joystickaxis(joystick, axis, value)
axisDir1, axisDir2, _ = joystick:getAxes()
controls:switch(joystick)
if axisDir1 < 0 then buttonpressed('dpleft') end
if axisDir1 > 0 then buttonpressed('dpright') end
if axisDir2 < 0 then buttonpressed('dpup') end
if axisDir2 > 0 then buttonpressed('dpdown') end
end

function love.draw()
if testing then return end

Expand Down Expand Up @@ -293,4 +329,4 @@ function love.graphics.newScreenshot()
local ss = newScreenshot()
window.dressing_visible = true
return ss
end
end
18 changes: 1 addition & 17 deletions src/vendor/gamestate.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ function GS.new()
mousereleased = __NULL__,
joystickpressed = __NULL__,
joystickreleased = __NULL__,
joystickaxis = __NULL__,
quit = __NULL__,
}
end
Expand All @@ -64,7 +65,6 @@ function GS.currentState()
return current
end


function GS.switch(to, ...)
assert(to, "Missing argument: Gamestate to switch to")

Expand All @@ -90,25 +90,10 @@ function GS.stack(to, ...)
return GS.switch(to, ...)
end


-- holds all defined love callbacks after GS.registerEvents is called
-- returns empty function on undefined callback
local registry = setmetatable({}, {__index = function() return __NULL__ end})

local all_callbacks = {
'update', 'draw', 'focus', 'keypressed', 'keyreleased',
'mousepressed', 'mousereleased', 'joystickpressed',
'joystickreleased', 'quit'
}

function GS.registerEvents(callbacks)
callbacks = callbacks or all_callbacks
for _, f in ipairs(callbacks) do
registry[f] = love[f]
love[f] = function(...) GS[f](...) end
end
end

-- forward any undefined functions
setmetatable(GS, {__index = function(_, func)
return function(...)
Expand All @@ -118,4 +103,3 @@ setmetatable(GS, {__index = function(_, func)
end})

return GS

0 comments on commit 3b0b65c

Please sign in to comment.