player controls in love.update vs. love.keypressed/released

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.
User avatar
sanjiv
Citizen
Posts: 88
Joined: Mon Feb 27, 2012 5:11 am

player controls in love.update vs. love.keypressed/released

Post by sanjiv »

I've often handled player controls in love.update, using functions like love.keyboard.isDown. Is that better or worse than using love.keypressed and love.keyreleased, in terms of demands on the hardware? I'm currently trying the later for a change.

I.e. when 'move' key is pressed, player.move=true.
when 'move' key is released, player.move=false.

I'm thinking this might make some of the logic stuff easier to write and keep track of.
User avatar
Ragzouken
Citizen
Posts: 84
Joined: Fri Aug 10, 2012 7:59 am
Contact:

Re: player controls in love.update vs. love.keypressed/relea

Post by Ragzouken »

Neither method is particularly demanding at all. Use whichever allows you to write the nicest code.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: player controls in love.update vs. love.keypressed/relea

Post by micha »

Some events only happen once, when a key is pressed, then use keypressed() (e.g. jumping). Other events happen continuously, as long as a key is held down, in this case put it into update(dt) (e.g. walking).
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: player controls in love.update vs. love.keypressed/relea

Post by kikito »

My rules are:
  • Use love.keyboard.isDown for doing quick and dirty 1-off prototypes that I'm going to throw away that same afternoon.
  • For anything else (any "real game"), use love.keypressed/released + boolean variables (player.wantsUp etc)
The reasoning is: love.keyboard.isDown is faster to type, and its also less lines of code, but it's also very inflexible. Your code will get very ugly if you want to allow the player to customize their keys, for example. Or use a joystick instead of the keyboard.

Using love.keypressed/released + boolean variables makes the code a bit longer and convoluted, but separates concerns better, which means more flexibility.

If your player update function only checks the boolean variables (player.wantsUp instead of love.keyboard.isDown('w')), it will not contain any keyboard/joystick/mouse or even network code. This means that it will not have to change at all when the player changes the keyboard configuration, or decides to use a joystick. You could make the player temporarily controlled by an Enemy AI, or via another player via the network, and have the same player:update function. It's a small investment upfront for a big potential benefit later on.
When I write def I mean function.
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: player controls in love.update vs. love.keypressed/relea

Post by T-Bone »

It seems like a strange question to me. They're good for different things and in almost all cases you need both of them.

I absolutely agree with Kikito about abstracting the controls in some way, because it makes it so much more flexible.

One nice way is to create a simple event queue of sorts. So that when the player presses a button or does something, a string is added to the queue, which is emptied and executed every love.update. So if I press the jump button, I add "jump" to the queue, and in the next love.update, I read that string and jump the character. If you decide later on to control the character in another way, you just add the same strings in the queue.
User avatar
Username
Citizen
Posts: 54
Joined: Mon Jan 28, 2013 1:25 pm

Re: player controls in love.update vs. love.keypressed/relea

Post by Username »

micha wrote:Some events only happen once, when a key is pressed, then use keypressed() (e.g. jumping). Other events happen continuously, as long as a key is held down, in this case put it into update(dt) (e.g. walking).

The problem when using love.keyboard.isDown is that you cannot control the repeat timing due to the different dt's that may have different computers, so in a slow computer I may press left arrow key to walk and the character will move relatively slow, while an user with a top-end computer may do the same and the character will move at light speed. The only solution to this is to limit the framerate to a fixed amount.

I would definitely use only love.keypressed plus keyrepeat.
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: player controls in love.update vs. love.keypressed/relea

Post by micha »

Username wrote:The problem when using love.keyboard.isDown is that you cannot control the repeat timing due to the different dt's that may have different computers, so in a slow computer I may press left arrow key to walk and the character will move relatively slow, while an user with a top-end computer may do the same and the character will move at light speed. The only solution to this is to limit the framerate to a fixed amount.

I would definitely use only love.keypressed plus keyrepeat.
Sorry, I don't understand how this is related to keypressed and isDown. What you talk about is just a matter of correctly using dt. Or do you mean something different?
Also the wiki says about keyrepeat:
Please note that a generally better way to move an object would be to put code in love.update() which uses love.keyboard.isDown.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: player controls in love.update vs. love.keypressed/relea

Post by kikito »

Username wrote:The only solution to this is to limit the framerate to a fixed amount.
That's a solution, but not the only one (in fact, it's not even a very good solution).

A better solution is using dt to calculate how much the player has moved on each update cycle, instead of assuming it moves "x pixels each frame". You can read more about dt here:

https://love2d.org/wiki/dt
When I write def I mean function.
User avatar
Username
Citizen
Posts: 54
Joined: Mon Jan 28, 2013 1:25 pm

Re: player controls in love.update vs. love.keypressed/relea

Post by Username »

micha wrote:
Username wrote:The problem when using love.keyboard.isDown is that you cannot control the repeat timing due to the different dt's that may have different computers, so in a slow computer I may press left arrow key to walk and the character will move relatively slow, while an user with a top-end computer may do the same and the character will move at light speed. The only solution to this is to limit the framerate to a fixed amount.

I would definitely use only love.keypressed plus keyrepeat.
Sorry, I don't understand how this is related to keypressed and isDown. What you talk about is just a matter of correctly using dt. Or do you mean something different?
Also the wiki says about keyrepeat:
Please note that a generally better way to move an object would be to put code in love.update() which uses love.keyboard.isDown.
The problem when using isDown plus messing with dt is that it will make the game movement to look jumpy if dt is not the same as the person that has designed the game. This does not happen with keypressed + keyrepeat

For example, lets say I do a game, and my game runs at dt = 0.01.

my character in screen moves with posX = posX + dt*100
The game in my computer makes the character to move 1 pixel each game cycle, which is 0.01 seconds for me.

Now, you may run the same game in your computer, but for some reason, your dt is 0.05, so you get posX = posX + 0.5*100
The character in your computer moves at 5 pixels per game tic, so if you need to stop movement at pixel number 3, you simply can't.


Now, using keypressed + keyrepeat, it doesn't mind the dt of the computers because the character movement amount is not modified by the time invested by the computer to complete one game cycle and the character will always move 1 pixel away while the key is pressed, so i can stop at pixel 3 if i want.


Run this piece of code and you will see what i mean.
Use left/right arrow keys to move the green line.
'd' to increase by 0.05 deltatime or retunr it to normal.
Now, with deltatime +0.05, try putting the green line over the large lines.
Next do the same but with your default deltatime that will probably be 0.01 or something.

Code: Select all

posX = 400
posY = 300
sleepTime = 0

function love.draw()
	love.graphics.setColor(100, 100, 100, 100)
	for i = 0, 800 do
		love.graphics.line( (i - 1)*32, 0, (i - 1)*32, 600 )
	end
	
	if math.mod(math.floor(posX), 32) == 0 then
		love.graphics.setColor(255, 0, 0, 255)
		love.graphics.line( posX, 0, posX, 600 )
	end
	
	love.graphics.setColor(0, 255, 0, 255)
	love.graphics.line( posX, 250, posX, 350 )
	
              love.graphics.print("FPS are " .. love.timer.getFPS() .. "\ndt is " .. love.timer.getDelta() .. "\nPress 'd' to toggle deltatime", 10, 10)
end

function love.update(dt)
	if love.keyboard.isDown("left") then
		posX = posX - dt*100
	end
	
	if love.keyboard.isDown("right") then
		posX = posX + dt*100
	end
	
	love.timer.sleep(sleepTime)
end

function love.keypressed(key, unicode)
	if unicode == 100 then
		if sleepTime == 0 then
			sleepTime = 0.05
			posX = 400
		else
			sleepTime = 0
			posX = 400
		end
	end
end
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: player controls in love.update vs. love.keypressed/relea

Post by Robin »

Username wrote:The character in your computer moves at 5 pixels per game tic, so if you need to stop movement at pixel number 3, you simply can't.
That is extremely fragile and I wouldn't recommend designing your game like that.
Help us help you: attach a .love.
Post Reply

Who is online

Users browsing this forum: No registered users and 10 guests