Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Controller support and Global keys #2389

Merged
merged 1 commit into from
May 24, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
118 changes: 102 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,28 @@ function InputController:isDown( action )
return false
end

if self.joystick then
if self.joystick:isGamepad() then
return self.joystick:isGamepadDown(key)
else
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 +216,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 +235,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