[Lua] Call table keys as functions?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Psi Amp
Prole
Posts: 2
Joined: Sat May 10, 2014 9:32 pm

[Lua] Call table keys as functions?

Post by Psi Amp »

Hey LÖVE forums, first post.

This is more of a theoretical question than a problem: does anyone know if I use functions as keys to a table if there is a way to call the function given that I have a reference to the key? The question arose with my key binding system, where I have a table of keys that are bound with their associated function and modifier keys, and a table of functions with their associated key and category (eg. "System", "Player"). Here's snippet of the implementation:

Code: Select all

function Keybindings:add(key, func, mods, cat)
    -- Required
    assert(key and type(key) == "string")
    assert(func and type(func) == "function")
    -- Optional
    assert(not mods or type(mods) == "table")
    assert(not cat or type(cat) == "string")

    self.keys[key] = {
        func = func,
        mods = mods
    }

    self.functions[func] = {
        key = key,
        cat = cat
    }
end
Lets say I have a reference to an index of the function table.

Code: Select all

local keybindings = Keybindings()
keybindings:add("escape", love.event.quit)

local index = keybindings.functions[keybindings.keys["escape"].function]
So now index refers to the table for "love.event.quit" in the "keybindings.functions" table. Is there any way I could call the function used as the key via the key itself?

Thanks in advance.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: [Lua] Call table keys as functions?

Post by micha »

Hi and welcome to our forum.

After running the code you posted, the variable index holds a reference to a table with this content:

Code: Select all

{key = 'escape'}
However, the variable index does not know that in the table keybindings.functions there exists also an entry with a reference to the same table. So if you want to access the associated function you have two options:
  • Use the reversed table (you called it keybindings.keys) that holds the functions as values or
  • traverse the keybindings.functions table until you find the key-value-pair that has the value you are looking for. That could look like this:

    Code: Select all

    for k,v in pairs(keybindings.functions= do
      if v == index then
        k()
      end
    end
Psi Amp
Prole
Posts: 2
Joined: Sat May 10, 2014 9:32 pm

Re: [Lua] Call table keys as functions?

Post by Psi Amp »

Hey, thanks for the quick reply micha

The method you went over is pretty much exactly what I'm doing at the moment, and probably the best option asside from adopting a different implementation. I'm starting to get frustrated over brainstorming the best implementation for my project. What do you (or anyone else for that matter) do for handling global keybindings, especially if you want them to be user rebindable?

Also, in retrospect, my question seems a little dumb; if I wanted to call the function that's being used as a key to my table, and I have a reference to that index at that key, then that must mean that I have a reference to that function. So I guess that settles that.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: [Lua] Call table keys as functions?

Post by micha »

For my game, I don't need many buttons. For each button I came up with a name, what it is doing ('left','right',...,'jump', 'special') and then I simply store the associated button as a string:

Code: Select all

keys.left = 'left'
keys.jump = ' '
keys.special = 'a'
and so on. Next, this key information is needed in two possible places: love.keypressed and love.keyboard.isDown. In the love.keypressed I simply put a lengthy if-statement:

Code: Select all

function love.keypressed(key)
  if key == keys.jump then
    -- do stuff
  elseif key == keys.special then
    -- do other stuff
  end
  -- and the other keys
end
And for the love.keyboard.isDown I wrote a function that in the beginning of each frame, checks the love.keybaord.isDown for all keys I have and stores the values somewhere:

Code: Select all

function checkInput()
  game.isLeft = love.keyboard.isDown(keys.left)
  game.isJump = love.keyboard.isDown(keys.jump)
  -- and so on
end
This is called in the beginning of love.update and then all subsequent functions can access game.isLeft to check if the button is held down.

There is a lot of hard-cording involved, but as I only have about 8 buttons, this works pretty good. In this solution there are not specific functions attached to each button.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 7 guests