Page 1 of 2

Best practice for key inputs? keypressed, isDown

Posted: Mon Oct 08, 2012 6:20 pm
by stout
Trying to understand the best way to set up my keyboard inputs. I have a turn-based and menu-driven game (nothing realtime). What I'd like to do is sequester sets of inputs into their related functions, like so:

Code: Select all

function viewTitle()    --main menu screen
     love.graphics.print("'N'ew Game",100,100)
     --and here would be the code for pressing 'N' to switch the view and thus draw a new screen
end
I could use isDown for this kind of function, but then I have to mess with key repeat rates (not necessarily on this particular screen, but you get the idea). But if I use keypressed then I have to have all possible commands for all possible states in one giant function, sequestered from their related functions, and that seems ugly and clunky to me. I tried passing a function to keypressed, like this:

Code: Select all

function love.keypressed(key)
     titleKeys()
end

function titleKeys()
		if key == "n" then
			view = "map"
      end
end
..so that I could at least have titleKeys() near viewTitle() in the code, but that doesn't work.

So what's the best way to handle keyboard inputs? What's efficient + readable?

Re: Best practice for key inputs? keypressed, isDown

Posted: Mon Oct 08, 2012 8:38 pm
by Kadoba
You're going to need a mix of both. One is for instant actions and the other is for ongoing actions. For example, in a platforming game you would use love.keypressed for a jump action and love.keyboard.isDown() for walking.

Re: Best practice for key inputs? keypressed, isDown

Posted: Mon Oct 08, 2012 8:46 pm
by stout
Hmm, so I'll probably be doing mostly keypressed then. Which leaves the question of how to organize and pretty up the code; really hate having to have so many weird and elaborate if chains in one giant function.

Re: Best practice for key inputs? keypressed, isDown

Posted: Mon Oct 08, 2012 8:56 pm
by Kadoba
stout wrote:Hmm, so I'll probably be doing mostly keypressed then. Which leaves the question of how to organize and pretty up the code; really hate having to have so many weird and elaborate if chains in one giant function.
That's what gamestates and subscriber structures are for. You just make a list of stuff that needs keyboard input. That way you have lots of small manageable functions instead of one huge one.

Code: Select all

-- keypressed functions
local functs = {}

-- forward parameters to all keypressed functions
function love.keypressed(...)
   for _,funct in pairs(functs) do
      funct(...)
   end
end

-- player movement
functs[ #functs+1 ] = function(k)
  if k == "up" then
    moveUp()
  end
  if k == "down" then
    moveDown()
  end
  -- ...
end

-- menu controls
functs[ #functs+1 ] = function(k)
  if k == "enter" then
    confirm()
  end
  if k == "escape" then
    cancel()
  end
  -- ...
end

Re: Best practice for key inputs? keypressed, isDown

Posted: Mon Oct 08, 2012 8:59 pm
by stout
Ahhh. I haven't done the multi-arguement functions yet (that's the ... right?), but that shows me how to pass other functions to keypressed (which was part of my question but maybe not elegantly expressed). Thanks!

Re: Best practice for key inputs? keypressed, isDown

Posted: Mon Oct 08, 2012 9:00 pm
by Roland_Yonaba
Well, you can also try to write an input management system, that would allow, when entering a new state of the game, to bind callback functions to specific event with specific key.
So that when the state runs, you do not have to care about inputs, as the input system will automatically register all inputs events, and spawn callbacks accordingly.
I had to write something similar for a little study case for love2d I was working on last week.

EDIT: Hijacked by Kadoba. Too much ninjas over here...

Re: Best practice for key inputs? keypressed, isDown

Posted: Sat Oct 13, 2012 3:07 pm
by stout
I'm using Kadoba's code and am running into a couple of issues.

Code: Select all

functs[ #functs+1 ] = 

	function(key)
			selectorY = 45 
			if key == "up" then 
				if selectorY > 45 then
					selectorY = selectorY-50
				end
			end

			if key == "down" then
				if selectorY < 95 then
					selectorY = selectorY+50
				end
			end
     end
selectorY is a variable used in drawing a rectangle, a basic selection/highlight box. This SEEMED to work; I had two positions on the screen, I could move my box between them, and it wouldn't go "over". So I added a third position, and changed the down key code from 95 to 145. But the box won't move down to the third position; I checked with a quick output of selectorY and it won't go higher than 95, even though it should be within the parameters. Furthermore, the up key works fine, but EVERY KEY does so as well! If the box is in the second (lower) position, any other key pressed (except down) will result in the box moving up.

These things are weird and I have no idea why they are happening.

EDIT: okay after writing this I thought of some things to try. If I change the up key parameter from 45 to 15, the box now jumps between 95 and -5. Which is 100 point difference, which is 50 * 2, so I understand where that number is coming from but not WHY. So I am making some kind of basic Lua mistake on that front.

Still don't know why every key on the keyboard acts as up, though.

Re: Best practice for key inputs? keypressed, isDown

Posted: Sat Oct 13, 2012 5:24 pm
by Robin
It's this line:

Code: Select all

selectorY = 45 
Every time you press a key, selectorY gets reset to 45. All your other problems originate from that. You'll probably want to move that line to a place like love.load().

Re: Best practice for key inputs? keypressed, isDown

Posted: Sat Oct 13, 2012 10:52 pm
by stout
HAH! Thanks. Hopefully I won't make that mistake again.

Re: Best practice for key inputs? keypressed, isDown

Posted: Sun Oct 14, 2012 12:47 am
by stout
Aaaand now I'm home and can test the code change. I moved selectorY out of the input code so it's on its own. New problem!

Right now it looks like this:

Code: Select all

selectorY = 45

functs[ #functs+1 ] =

   function(key)
         if key == "up" then
            if selectorY > 45 then
               selectorY = selectorY-50
            end
         end

         if key == "down" then
            if selectorY < 145 then
               selectorY = selectorY+50
            end
         end
     end

Now it jumps between 45 and 145, skipping 95 entirely. But if I have selectorY where it was originally - within the funct addition, it goes between 45 and 95. Additionally, if I increase the "down" parameter - to, say, 150 - it begins to jump between 45 and 195. It's adding as many 50s as it can, all at once. But this is going back to keypressed, which shouldn't be doing that, so I am mystified.