How to check if a button is being held down (SOLVED)

Hello, I’m following the crash course Defold tutorial and have previously watched the whole Defold tutorial series from Gamefromscratch. On there they make a script for moving the character but, when I press right it starts going right indefinitely until I press left when it starts going just left (even when the key is released). Tried some stuff on my own like “and action.released ~= true” etc but with no luck (probbably because I’m so new to Defold and Lua altogether. Can anyone help me? I want the character to stop and the idle anim to play when no keys are being pressed (at least not the right or left for now). The script can be found here

hi!

Put this code into your on_input

pprint(action) 

and you can see the action table in your console. Search in the console for a field called “released” and when released = true, then it means a key was released.

if action.released ~= true then

here, you are checking that action.released is NOT true. you need to write it like this

if action.released == true then

just to make that clear,

if action.released ~= true then 

means:

If action.released is unequal to true then

and you want to use ==, which means “equal to”

1 Like

Hi, thanks for the response. Where would I be checking for that? In the update or input (with a repeat untill released == true?)

the action table is only available in the on_input() function. The code on your tutorial would probably be better if it was something like this:

function on_input(self, action_id, action)

if action_id == hash(“MOVE_RIGHT”) and action.pressed then
self.speed.x = self.runSpeed
sprite.set_hflip("#sprite", false)
end

if action_id == hash(“MOVE_LEFT”) and action.pressed then
self.speed.x = self.runSpeed * -1
sprite.set_hflip("#sprite", true)
end

if action.released then --if any key is released…
self.speed.x = 0 …set the speed to zero (and also maybe set the idle anim?

end

end

2 Likes

If I understood correctly, while holding the button
In on_input

if action.repeated then
  --moving
end

The site also has great manuals.

action.repeated is something else which I can’t explain right now. But it’s not important at the moment, you just need action.pressed and action.released.

Remember, if you put pprint(action) at the top of your on_input section, you can see the Action Table in the console. That will show you what information is being used in the function.

Yes! That’s it! I can’t believe I didn’t think of that (I suppose for some reason I wasn’t thinking as released starting on_input too. Now just need to sort the animations. Thanks a lot. Can I choose the right answer, close the question or something like that on this forum?

you can edit the title to put (SOLVED) at the end.

Here’s also an example of eight way movement: https://defold.com/examples/input/move

And another example tracking key states and animations: https://github.com/britzl/publicexamples/tree/master/examples/play_animation

1 Like

Oh and this as well: https://github.com/britzl/publicexamples/tree/master/examples/top_down_movement

1 Like

Hey hey!

First post, so let me know if I’m breaking some rule. But in case anyone finds this in the future as I did from a google search, I’ve got a little bit of a small bugfix.

Doing the standard 8-way movement code worked in general, but I was running into this issue:

  1. Press and hold “right” (player moves right)
  2. Press “left” (player moves left)
  3. Let go of “left” while still holding “right” (player stands still)

The player should be moving right in this scenario. So I went around this like so:

in update(self, dt):

    		local pos = go.get_position()
		pos = pos + velocity * dt
		go.set_position(pos)

And in my on_input(self, action_id, action):

	if action_id == hash("left") then
		if action.pressed then
			velocity.x = velocity.x - self.speed
		elseif action.released then
			velocity.x = velocity.x + self.speed
		end
	elseif action_id == hash("right") then
		if action.pressed then
			velocity.x = velocity.x + self.speed
		elseif action.released then
			velocity.x = velocity.x - self.speed
		end
	elseif action_id == hash("up") then
		if action.pressed then
			velocity.y = velocity.y + self.speed
		elseif action.released then
			velocity.y = velocity.y - self.speed
		end
	elseif action_id == hash("down") then
		if action.pressed then
			velocity.y = velocity.y - self.speed
		elseif action.released then
			velocity.y = velocity.y + self.speed
		end
	end

It’s very unwieldy, but it gets the job done and doesn’t require processing repeated inputs. This is the first real, full-fledged game I’m working on, so if anyone happens to have a better way, do let me know!

You could do generic input tracking in on_input() and the check which keys are held down in update():

function init(self)
	self.actions = {}
end

function update(self, dt)
	local pos = go.get_position()

	if self.actions[hash("right")] then
		pos.x = pos.x + self.speed * dt
	elseif self.actions[hash("left")] then
		pos.x = pos.x - self.speed * dt
	elseif self.actions[hash("up")] then
		pos.y = pos.y + self.speed * dt
	elseif self.actions[hash("down")] then
		pos.y = pos.y - self.speed * dt
	end

	go.set_position(pos)
end

function on_input(self, action_id, action)
	if action_id then
		if action.pressed then
			self.actions[action_id] = true
		elseif action.released then
			self.actions[action_id] = false
		end
	end
end

I’m not sure if it is necessarily better, but at least it is a different solution that can be good to know about. :slight_smile:

1 Like