Log In  

Cart #simpleinputsystem-0 | 2020-12-02 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
3

Simple input system, to manage key/button presses.

Registers pressed and release buttons.
Horizontal axis, vertical axis, O and X buttons are all independent of each other.

The code is commented, so you can follow along what it is doing (and possibly improve it, if you wish).

As is, it is good enough and does the job, but I wouldn't be surprised if there is a more efficient way of doing this.

P#84964 2020-12-02 21:06 ( Edited 2020-12-02 21:06)

2

This is very cool. I like how the code is commented as very well optimized. One improvement I would suggest is adding player 2 inputs to the system. (Player 2 inputs: s,f,e,d,tab & x)

P#84969 2020-12-02 23:12
1

Hey, this is some great code. Thanks for sharing this. Here is how I did it.

Cart #robsinputsystem-1 | 2021-04-10 | Code ▽ | Embed ▽ | No License
1

We cannot use the built-in functions alone for checking button released. We need to create a table so that we can know what buttons were pressed on the last frame and what buttons were pressed on the frame before it.

I went with string players but numeric buttons. The table looks something like this:

buttons = {
 player0 = {
  {isdown = false, isup = false},
  {isdown = false, isup = false},
  {isdown = false, isup = false},
  {isdown = false, isup = false},
  {isdown = false, isup = false},
  {isdown = false, isup = false}
 },
  player1 = {
  {isdown = false, isup = false},
  {isdown = false, isup = false},
  {isdown = false, isup = false},
  {isdown = false, isup = false},
  {isdown = false, isup = false},
  {isdown = false, isup = false}
 },
}

The function I have for checking button state is basically same as the one you have given. Let's check the buttons in one function and then select values in a different function. Here is how I'm checking buttons, calling this within each call to _update60()

function updatebuttons()
    for i=0,5 do
        if not btn(i) then
            buttons.p0[i].isup = buttons.p0[i].isdown
        end
        if not btn(i, 1) then
            buttons.p1[i].isup = buttons.p1[i].isdown
        end 
        buttons.p0[i].isdown = btn(i)
        buttons.p1[i].isdown = btn(i, 1)
    end 
end

The important part is btnr(i, [p]).

--btnr([i, [p]]) -- true when the button was released the frame before the last frame;
function btnr(i, p)
    p = p or 0

    local b
    if p == 1 then
        b = buttons.p1
    else
        b = buttons.p0
    end 
    return b[i].isup
end

So, to recap, all you need to copy n paste from my cart is

  • function initbuttons()
  • function updatebuttons()
  • function btnr(i, p)

It appears to take the exact amount of tokens as the OP cart, that's 139 tokens.

P#90322 2021-04-10 16:45 ( Edited 2022-04-29 02:01)
1

If you only care about released last frame and are already assuming a function call every update, this way uses less tokens (84 at minimum). I'm not sure about speed though. Also, it's not quite accurate. If btnr() is called with a player index above 1 it seems to correctly check the the button but not necessarily for the correct player

function initbuttons()
  btnrt={}
  for i=1,12 do btnrt[i]=0 end
end

function updatebuttons()
  for i=0,11 do 
    btnrt[i+1]=max(btnrt[i+1]-1,0) 
    if (btn(i%6,i\6)) btnrt[i+1]=2
  end
end

function btnr(i, p)
  if (p==1) i+=6
  return btnrt[i+1]==1
end
P#90329 2021-04-10 20:30
2

Since the button-released info seems to be the main thing this offers that standard functions don't, I just made a small function that does that. Only 32 tokens including initializing the 'previous button state' variable.

--place in _init()--
btn_old=0

function btnr(n)
 local v,r=2^n
 if(btn_old&v>btn()&v) r=1
 return r
end

--FIX, place in end of _update()--
btn_old=btn()

Or you can even get by without using a separate function at all, but this would only simplify things if you just need to test if certain buttons are released, as with O and X here. (27 tokens, and no function calls required).

--place in _init()--
btn_old=0

--place in _update()--
if(btn_old&16>btn()&16)...
if(btn_old&32>btn()&32)...
btn_old=btn()
P#90360 2021-04-11 17:12 ( Edited 2021-04-12 21:05)
1

@JadeLombax The 32 token version doesn't use the same paradigm as the btnp(i, p) function (which makes it counter-intuitive to use), wouldn't be able to handle player 2 with arrow symbols replacing the numbers, and would only work correctly if used exactly once per update for only one input.

Rather than setting btn_old equal to btn(), it should be setting just the one bit being checked. Otherwise the rest of the code has to figure out which single button was relevant to check for release. Even then, it would still require exactly one use per relevant input each frame. As such, I think requiring btn_old to be set equal to btn() at the end of the _update function would be best.

Using a single number as a bitmask is a good optimization, but I don't think it's a good idea to avoid the input system needing to be updated in _update(). If a game later turns out to need repeated checks or more usage than initially expected, being able to just call btnr() more times could save a lot of hassle.

P#90387 2021-04-12 02:42
1

Oh, okay, I see your point, that was an oversight on my part. As with the second bit of code, setting btn_old equal to btn() should come after all the inputs, I'll fix that.

P#90390 2021-04-12 04:23 ( Edited 2021-04-12 14:24)

I really love how you fellas came up with more efficient ways to do this, reading all these comments helped me a lot!!!

P#92261 2021-05-21 04:15

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 18:17:13 | 0.027s | Q:30