Page 1 of 1

Controllers.lua

Posted: Thu Jun 12, 2014 6:29 pm
by Automatik
Hi!

GitHub : https://github.com/Felix-Du/Controllers.lua
Download : https://raw.githubusercontent.com/Felix ... ollers.lua
ReadMe : https://github.com/Felix-Du/Controllers ... /README.md

So, this is a small project I've worked on, and I'm at this point where it seems to be improvable, but it's has basically all the features I need and a bit more, so I'm releasing it now.
Controllers.lua is a small lib(1 file!) that aim to replace, simplify, and enhance how Löve manage user-input. I think it's a really cool and simple. :)
You give it a list of "buttons" or "axes" (like "game_walk" or "menu_up"), you optionally define some "players" so that you don't have to copy-paste the same list of buttons each time you want to add a new place for a player. Then you place the needed callbacks and here you go! Then, if you want to know if a button is pressed, you can just use "Controllers:isDown("name_of_button")". You don't have to care about what is actually pressed(The keyboard, a button of a gamepad, an axis, the mouse). And if callbacks are your things, then you're in luck, because Controllers.lua allow you to set some callbacks (Once again, it's device-agnostic).

Here's a not actually runnable example, just so that you can get how it work:

Code: Select all

require('controllers')
function love.load()
    Controllers:init({
     menu_up = {type="button", default={'kb_up','gpb_dpup','gpa_lefty_-'}}
    ,menu_down = {type="button", default={'kb_down','gpb_dpdown','gpa_lefty_+'}}
    ,menu_select = {type="button", default={'kb_return','kb_ ','gpb_a'}}
    ,menu_back = {type="button", default={'kb_escape','gpb_start'}}

    ,game_jump = {type="button", per_player=true, default={'kb_ ','gpb_a'}}
    ,game_walk = {type="axis", exclusive="press", per_player=true, default={'kb_left_-','kb_right_+','gpa_leftx'}}
    })
    Controllers:setPlayer('player_1','joystick',1)
end

function love.update(dt)
    Controllers:pre_update(dt)

    if pause then
        for i=1, Controllers:isPressed('menu_up') do
            menu_select = menu_select - 1
        end
        for i=1, Controllers:isPressed('menu_down') do
            menu_select = menu_select + 1
        end
    end

    if Controllers:isPressed('menu_back') then
        pause = not pause
    end

    if Controllers:isDown('game_jump','player_1') and player:onGround() then
        player:jump()
    end
    player.speedx = Controllers:getAxis('game_walk','player_1') * player.walk_speed

    Controllers:post_update(dt)
end

function love.mousepressed(x,y,button)
    Controllers:mousePressed(x,y,button)
end
function love.mousereleased(x,y,button)
    Controllers:mouseReleased(x,y,button)
end

function love.keypressed(key,unicode)
    Controllers:keyPressed(key)
end
function love.keyreleased(key,unicode)
    Controllers:keyReleased(key)
end

function love.joystickpressed(joystick,key)
    Controllers:joystickPressed(joystick,key)
end
function love.joystickreleased(joystick,key)
    Controllers:joystickReleased(joystick,key)
end

Re: Controllers.lua

Posted: Thu Jun 12, 2014 9:13 pm
by Roland_Yonaba
Hi, nice job.

I would like to share my two cents.
You might want to change the actual implementation so that, instead of creating a plain global table neamed "Controllers", requiring it would rather return a local. This had lots of benefits: first, it does not pollute the global namespace, and lots of Lua purists will thank you for that. This is a general pattern that Lua module writers tend to stick to. Second, because it returns a local, the user of your module can name it the way he wants inside his code, instead of being forced to use the name "Controllers", which can be long to type for some people.

Also, I am not really confortable with the way you init a new instance. Actually, it looks kind of weird to use the colon syntax to init a new instance. "Controllers" is a class, so the class should not init itself (IMHO) to spawn a new object. I will suggest using a dot call for this instead. You can refactor the init method like this:

Code: Select all

local Controllers = {}
Controllers.__index = Controllers

function Controllers.init(controls_table)
  local newController = {} -- a new instance
  --- some code
  return setmetatable(newController, Controllers) -- set Controllers as a metatable to the new instance.
end

-- other methods here, defined with the colon syntax
function Controllers:method1(...)
  -- some code
end

return Controllers -- return the module
A way to use this:

Code: Select all

local Controller = require 'Controllers'
local aNewController = Controller.init(controls_table)
-- etc etc
One minor trick, you can make use of the __call metamethod to provide a nicer syntax to init a new controller.
At the end of your module, instead of returning the table "Controller", have this instead:

Code: Select all

return setmetatable(Controllers, {__call = function(t, ...) return Controllers.init(...) end})
With this, a user can still init a controller with init, or use a function call style:

Code: Select all

local Controller = require 'Controllers'
local aNewController = Controller(controls_table) -- same as Controller(controls_table)
-- etc etc
Hope this helps.

Re: Controllers.lua

Posted: Fri Jun 13, 2014 9:44 am
by Automatik
Thanks! I pushed two commits for this. The Controllers object was never meant to be a class(Which is why :init() doesn't return a new instance, but rather initialize the lib itself), but now it's possible to create an instance with Controllers(controls_table), Controllers:new(controls_table), and Controllers.new(controls_table), for those who want !

Re: Controllers.lua

Posted: Fri Jun 13, 2014 10:07 am
by Roland_Yonaba
Well, if it was not meant to be a class and provide instances, then it would be best to provide a single syntax, and design it as a singleton.
In other words, all methods would use dot-style:

Code: Select all

local Controllers = {}

function Controllers.init(...) -- some code return ... end
function Controlllers.method1(...) --some code end
function Controlllers.method2(...) --some code end

return Controllers

Re: Controllers.lua

Posted: Fri Jun 13, 2014 10:34 am
by Automatik
Fixed.