Page 1 of 3

What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Sat Feb 26, 2022 6:34 pm
by Yolwoocle
Hi.
I come from a background of making games on PICO-8, and its API has two functions, called "btn" and "btnp", which respectively return whether a button is down or if it's just been pressed (i.e. for the first frame). I have used myself to think about input in terms of checking it in the "update" function. However, LÖVE seems to have a "love.keypressed" function, which is, as far as I know, the only way to check if a button has been just been pressed (as opposed to checking if it's down continuously).
Imagine I have a game with different weapons, some of which are automatic, where you have to hold the "fire" button to fire, while others are manual, where you have to press on this button repeatedly to fire.
What is a helpful way to think about this? Use "love.keyboard.isDown" in my player's update method, and have separate code for "love.keypressed"? Seems weird to me that the same action should be put in different places in the code.
Thanks

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Sat Feb 26, 2022 6:40 pm
by MrFariator
Personally, I use love.keypressed for any actual in-game utility, and love.keyboard.isDown for any debug/development cheats or tools. Generally, my player code doesn't check the inputs, but rather uses the observer pattern to receive inputs: the input handling code grabs the currently pressed/held/released keys, and sends out signals to any objects that may have an active listener. In this way, they are pretty agnostic as to where the inputs are coming from. Enables easy way to do something like input playback from replay files or similar.

For some small menus, however, where it would be more bothersome to activate/deactivate listeners, they use simple "isGameButtonXPressed/Down/Released" query functions, that simply check the stuff the input handler is keeping track of.

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Sun Feb 27, 2022 12:34 am
by BrotSagtMist
I am using this code:

Code: Select all

love.keypressed= function( k )
 if KL[k] then KD[KL[k]]= 1 end
end
love.keyreleased= function( k )
 if KL[k] then KD[KL[k]]= nil end
end
Which looks easy enough but changes the way you do buttons quite dramatically.
First you get a layer to define your own keybinding:

Code: Select all

KL.up="up"
KL.w="up"
KL.space="fire"
will set booth w and the arrow key to be up, nice for arcade games. I do that in a config file.
Next you use it like

Code: Select all

if KD.up then 
 x=x+speed*KD.up*dt  
end
if KD.fire then 
 blah()
 KD.fire=nil
end
The lookup in a table is way cooler than using keyboard.isDown() and by niling the value after checking for it we can decide if we want to use it for continuous motions like a move or a single shot.
And since KD.up is a number value we can add analog joysticks instantly.
Even more we could also decrease the value as part of the physics, say for jumping so that

Code: Select all

KD.up= KD.up-dt
will give you a nice 1 second jump phase.

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Sun Feb 27, 2022 4:05 pm
by nehu
if you want to use something similar to the love.keypressed in love.update, you could use something like this:

Code: Select all

local keyPress = '' --sets the variable keyPress to an empty string

function love.update(dt)

    if keyPress == 'a' then --uses the keyPress var to detect the key that just got pressed
        
        print('fire')

    end

    keyPress = ''  --sets the keyPress to '' at the end of the code, so it only detects just when a key is pressed

end

function love.keypressed(key)

    keyPress = key --sets the keyPress to the key you just pressed
    
end
this basically makes a variable that stores the key you pressed and in the end of the love.update function it sets that var to '' (empty string)
so you just need to do something like:

Code: Select all

if keyPress == 'w' then
	--insert code
end
this should be less annoying than having to split your code in love.update and love.keyboardpressed :) !

and also you dont need to make a list of the keys you will use :P

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Mon Feb 28, 2022 4:13 am
by BrotSagtMist
@nehu, your code will fail for more than one button because two at the same frame will overwrite each other.

If you want to have a cleaner access to isKeydown() you can simply wrap this around, for example using metatables:

Code: Select all

K= setmetatable({},{__index=function(_,k) return(love.keyboard.isDown(k))  end})
KP={}
KS= setmetatable({},{__index=function(_,k,r) r=KP[k] KP[k]= K[k] return not r and K[k] or false end})

love.draw=function()
 if K.space then  print("pressed") end --continious check
 if KS.a then  print("fire") end --one time check
end
But thats rather complicating stuff.
nehu wrote: Sun Feb 27, 2022 4:05 pm and also you dont need to make a list of the keys you will use :P
Note that a keylist is a big plus to have. I cant even play games on my computer without that since i do not have a qwerty keyboard. Such list is vital for configuring and it will bite you in the ass later if you want to add joypad or multiplayer modes and have no abstraction layer for the key input.

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Mon Feb 28, 2022 4:28 am
by zorg
BrotSagtMist wrote: Mon Feb 28, 2022 4:13 amI cant even play games on my computer without that since i do not have a qwerty keyboard.
Time for the daily reminder that keyconstants are useless and one should use Scancodes instead since those are irrespective of keyboard layout.

Code: Select all

local keys = {}

function love.keypressed(k,s)
  keys[s] = 0
end

function love.keyreleased(k,s)
  keys[s] = false
end

function love.update(dt)
  for k,v in pairs(keys) do
    if love.keyboard.isScancodeDown(k) then
      keys[k] = keys[k] + 1 -- or + dt if you want time elapsed in seconds and not frames.
    end
  end
end

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Mon Feb 28, 2022 4:36 am
by BrotSagtMist
Then youll end up with a situation that the documentation wont match.
"press x"
"where the heck is x?"
Edit: also forgot that in the custom keyboard scene scanncodes are altered too on the hardware site.

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Mon Feb 28, 2022 6:03 am
by ReFreezed
zorg wrote: Mon Feb 28, 2022 4:28 am keyconstants are useless and one should use Scancodes
Only for controls. For keyboard shortcuts (like e.g. Ctrl+C to copy) keyconstants ought to be used.

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Mon Feb 28, 2022 1:26 pm
by Yolwoocle
BrotSagtMist wrote: Mon Feb 28, 2022 4:36 am Then youll end up with a situation that the documentation wont match.
"press x"
"where the heck is x?"
Edit: also forgot that in the custom keyboard scene scanncodes are altered too on the hardware site.
Isn't there love.keyboard.getKeyFromScancode for this very purpose? Scancodes are great for people like me who use a French keyboard layout :P

Re: What is a helpful way to think about input? love.keypressed or love.keyboard.isDown?

Posted: Mon Feb 28, 2022 2:05 pm
by MrFariator
Yeah, when you load the controls configurations, use love.keyboard.getKeyFromScancode to find out where they physically end up on the user's keyboard, and then display the appropriate character to the player in UI if necessary. This can be a bit of a headache to implement at first, but it's well worth it so that players don't complain about the default controls. A game having three action buttons at ZXC or ASD (on a qwerty keyboard layout) is relatively common in small indie games, but these don't make sense on a French keyboard, for instance.

I'm sure there may still be some edge-cases, but so long you give players the ability to rebind keys, many of those issues can be fixed.