Can't run two inputs at the same time (SOLVED)

I’m developing a game just for fun, but i came across a bug of the movement of the player that im just can’t understand. My knowledge of programming is pretty basic (i studied C in colege) and based in codes of forums that i found here.
Basically the bug is that the game does not accept two inputs at the same time.
Like, if im pressing the action D the player go to the right, and if i press the action A (with D still pressed) the player go to the left, but if i let go A the player just stops like any action is pressed.

function init(self)
	msg.post('.', 'acquire_input_focus')
	self.velocity_direction = vmath.vector3()
	self.velocity_module = 60
	self.direction = vmath.vector3()
end
function update(self, dt)
	self.current_position = go.get_position()
	self.new_position = self.current_position + self.velocity_direction * self.velocity_module * dt
	go.set_position(self.new_position)
end

function on_input(self, action_id, action)	
	if action_id == hash('left') and action.pressed then
		self.velocity_direction.x = -1
		self.direction.x = -1
		msg.post('player', "play_animation", {id = hash('player_run_left')})
	elseif action_id == hash('right') and action.pressed then
		self.velocity_direction.x = 1
		self.direction.x = 1
		msg.post('player', "play_animation", {id = hash('player_run_right')})
	end

	if action.released and self.direction.x == -1 then
		self.velocity_direction.x = 0
		msg.post('player', "play_animation", {id = hash('player_idle_left')})
	elseif action.released and self.direction.x == 1 then
		msg.post('player', "play_animation", {id = hash('player_idle_right')})
		self.velocity_direction.x = 0 
	end
end

The pressed value is only true for the first frame that the key is pressed down. Same goes for the “action.released”.

With that in mind, you’ll see that you have this sequence of values:

D pressed → dir.x = 1
A pressed → dir.x = -1
A released → dir.x = 0

At this point, the value is 0, and won’t affect the players position anymore.

3 Likes

The issue here is that you’re only setting the velocity direction when the action is first pressed. So what happens is you press A and D, set the velocity to whichever is pressed second, then when you release one of them it sets your velocity to 0 because of the action.released code you have, and it won’t be set to a direction again until you re-press the button.

Instead of checking for action.pressed, just zero your velocity on a release action of a movement key like you’re doing, and set the directional velocity for any non-release action.

2 Likes
function init(self)
    msg.post('.', 'acquire_input_focus')
    self.velocity_module = 60
    self.direction = vmath.vector3()
    self.velocity = 1
    self.left_down = false
    self.right_down = false
end
    function update(self, dt)
    self.current_position = go.get_position()
    self.new_position = self.current_position + self.direction * self.velocity * self.velocity_module * dt
    go.set_position(self.new_position)
end

function on_input(self, action_id, action)
if action.pressed then
	if action_id == hash('left') then
		self.left_down = true
		self.direction.x = -1
	elseif action_id == hash('right') then
		self.right_down = true
		self.direction.x = 1
	end
end

if action.released then
	if action_id == hash('left') then
		self.left_down = false
		if self.right_down then
			self.direction.x = 1
			msg.post('player', "play_animation", { id = hash('player_run_right') })
		end
	elseif action_id == hash('right') then
		self.right_down = false
		if self.left_down then
			self.direction.x = -1
			msg.post('player', "play_animation", { id = hash('player_run_left') })
		end
	end
end

if not self.left_down and not self.right_down then
	if self.direction == -1 then
		msg.post('player', "play_animation", { id = hash('player_idle_left') })
	elseif self.direction == 1 then
		msg.post('player', "play_animation", { id = hash('player_idle_right') })
	end
	self.direction.x = 0
elseif self.left_down and self.direction.x ~= -1 and not self.right_down then
	self.direction.x = -1
	msg.post('player', "play_animation", { id = hash('player_run_left') })
elseif self.right_down and self.direction.x ~= 1 and not self.left_down then
	self.direction.x = 1
	msg.post('player', "play_animation", { id = hash('player_run_right') })
end

end
2 Likes

Alternatively, you could try just removing the action.pressed check and decoupling your animation playback from your input. The great thing about programming is there’s always more than one way of doing things:

-- also good practice to prehash anything you're gonna reuse often, such as input ids
local h_player_run_left = hash("player_run_left")
local h_player_run_right = hash("player_run_right")
local h_player_idle_left = hash("player_idle_left")
local h_player_idle_right = hash("player_idle_right")

function play_animation(self, anim)
	if anim ~= self.current_animation then
		msg.post('player', "play_animation", {id = anim})
		self.current_animation = anim 
	end
end

function update(self, dt)
	if self.velocity_direction.x < 0 then
		play_animation(self, h_player_run_left)
	elseif self.velocity_direction.x > 0 then
		play_animation(self, h_player_run_right)
	elseif self.direction.x < 0 then
		play_animation(self, h_player_idle_left)
	else
		play_animation(self, h_player_idle_right)
	end
end

local h_left = hash("left")
local h_right = hash("right")

function on_input(self, action_id, action)
	if action_id == h_left then
		if action.released then 
			self.velocity_direction.x = 0
		else
			self.velocity_direction.x = -1
			self.direction.x = -1
		end
	elseif action_id == h_right then
		if action.released then
			self.velocity_direction.x = 0
		else
			self.velocity_direction.x = 1
			self.direction.x = 1
		end
	end
end
3 Likes

Thanks guys, i had to stop a bit to look some things of my colege. But now i understand what this action.released and action.pressed really means.