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.

3


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)


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.


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

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()

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.


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.


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



[Please log in to post a comment]