Unexpected behavior on movement code

Hello and welcome to my first ever post on here! Defold is a very clean machine and I look forward to learning it after I master Lua and Love2d. Although master is a strong word, I do intend to use frameworks as ‘ankle weights’ so to speak.

I am a little pedantic about something that I can fix in most other engines and frameworks I’ve tried, and I am confident that there is a quick fix to my issue.

The movement code that this site provides works as is, however I am concerned about when I press left and right at the same time. The behavior is not symmetrical, pressing left and right at the same time makes the character jerk around a bit, and it’ll just straight up ignore the other key being pressed but not the other way around.

Whereas in a framework like Love2d, it can be fixed to where if you press left and right at the same time the player will just stop and maintain the direction of the first key pressed, no extra variables.

This asymmetrical type of glitch, if I can call it that, does not break the game for most, but it does however, mildly irks me because I cannot fix this in the same way as I can on Love2d.

if love.keyboard.isDown(“left”) and not love.keyboard.isDown(“right”) then
(Movement code)
end

If I use the ‘and’ and ‘not’ logical operators in Defold for its movement code, the player ceases to move at all, or they only go in one direction not the other depending on how I try to tweak it.

If action_id == hash(“left”) and not action_id == hash(“right”) then
(Movement code)

I’ve tried this variant and a few others, at one point I accidentally made the main spaceman character from the tutorial sink into the earth! Poor guy

Thank you for your time, I apologize on my formatting I am doing this from mobile and not sure how to put that code in a code format for better viewing.

Welcome to Defold!

Indeed, this will not work. on_input() is called once for each action_id, so your code can never be true.

There are many ways to skin a cat, but the way I tend to handle this is to store everything that happens in on_input(), then process it in the next update(), then reset and go again.

So your left/right movement code would capture whether left is pressed and whether right is pressed and then apply the appropriate movement (which as you desire might end up being none at all).

4 Likes

Thank you for the response, I appreciate you taking time out of the day to help a noobie!

Now when you say store and process in the next update(), do you mean, store the action_id in a variable/table? And then make an if statement in update() ?

Or do you mean call the on_input() inside update() ?

I feel like I may be missing the forest for its trees with this type of issue beckoning me, but it does put me in a mental block with programming in general with this engine in particular.

1 Like

Yes.

(This answer is already implied, but…)
No!

Here’s an example from one of my games. I’ve stripped it back to its core, just to act as an example. It’s missing a lot of parts so it won’t work if just copied.

local function move_to_target(self, dt)

	if self.thrust.UP > 0 then
		self.velocity.y = self.velocity.y + self.acceleration * self.thrust.UP * dt
	end
	if self.thrust.DOWN > 0 then
		self.velocity.y = self.velocity.y - self.acceleration * self.thrust.DOWN * dt
	end
	if self.thrust.RIGHT > 0 then
		self.velocity.x = self.velocity.x + self.acceleration * self.thrust.RIGHT * dt
	end
	if self.thrust.LEFT > 0 then
		self.velocity.x = self.velocity.x - self.acceleration * self.thrust.LEFT * dt
	end

	local friction = 0.99

	self.velocity = self.velocity * friction^(dt)

	go.set_position(go.get_position() + self.velocity * dt)
end

function init(self)

	self.thrust = {UP = 0, DOWN = 0, RIGHT = 0, LEFT = 0}

end

function update(self, dt)

	move_to_target(self,dt)
	
end

function on_input(self, action_id, action)

	if action_id == MOVE_UP then
			self.thrust.UP = action.value
		if action.released then
			self.thrust.UP = 0
		end
	end
	if action_id == MOVE_DOWN then
			self.thrust.DOWN = action.value
		if action.released then
			self.thrust.DOWN = 0
		end
	end
	if action_id == MOVE_LEFT then
			self.thrust.LEFT = action.value
		if action.released then
			self.thrust.LEFT = 0
		end
	end
	if action_id == MOVE_RIGHT then
			self.thrust.RIGHT = action.value
		if action.released then
			self.thrust.RIGHT = 0
		end
	end

end

I am sure it can be done much more elegantly than this! What I am trying to illustrate with this is the principle of capturing the player’s intent in on_input(), and then translating that intent in update() into results.

2 Likes