8 directional movement right-up idle animation problem

“idle_rightUp” animation can not run. Is there a way to run an idle animation for the “right-up” direction?

function on_input(self, action_id, action)
    if action_id == hash("right")  and action.released then                  
       movement = 0 --right
       sprite.play_flipbook("#sprite", "idle_right")
    elseif action_id == hash("right") and hash("up")  and action.released then
       movement = 1 --rightUp
       sprite.play_flipbook("#sprite", "idle_rightUp")
    elseif action_id == hash("up") and action.released then
       movement = 2 --up
       sprite.play_flipbook("#sprite", "idle_up")
    --...
    end
end

In another method I tried. Walking motion animation works successfully for 8 directions. Idle animation works only “right, up, left, down” directions but idle animation not working for intermediate (up-right, …) directions. it is necessary to release the up and right keys at the same time. but this is not possible. This is not possible for other intermediate directions either too. Thanks for your help?

function update(self, dt)
pos=go.get_position()
go.set_position(pos + self.direction * self.speed * dt)
end

function on_input(self, action_id, action)
if action_id == hash("right") then
	b_r = 1
	play_animation(self)
elseif action_id == hash("up") then
	b_u = 1
	play_animation(self)
elseif action_id == hash("left") then
	b_l = 1
	play_animation(self)
elseif action_id == hash("down") then
	b_d = 1
	play_animation(self)
end

elseif action.released then
	if action_id == hash("right") then
		b_r = 0
		play_animation(self)
	elseif action_id == hash("up") then
		b_u = 0
		play_animation(self)
	elseif action_id == hash("left") then
		b_l = 0
		play_animation(self)
	elseif action_id == hash("down") then
		b_d = 0
		play_animation(self)
	end
  end
end

local function play_animation(self)
if b_r==1 and b_u==0 and b_l==0 and b_d==0 then
	--sprite.play_flipbook("#player", "r_w")
	self.direction.x=1
	self.direction.y=0
	plYon=0
elseif b_r==1 and b_u==1 and b_l==0 and b_d==0 then
	--sprite.play_flipbook("#player", "ur_w")
	self.direction.x=1
	self.direction.y=1
	plYon=1
elseif b_r==0 and b_u==1 and b_l==0 and b_d==0 then
	--sprite.play_flipbook("#player", "u_w")
	self.direction.x=0
	self.direction.y=1
	plYon=2
elseif b_r==0 and b_u==1 and b_l==1 and b_d==0 then
	--sprite.play_flipbook("#player", "ul_w")
	self.direction.x=-1
	self.direction.y=1
	plYon=3
elseif b_r==0 and b_u==0 and b_l==1 and b_d==0 then
	--sprite.play_flipbook("#player", "l_w")
	self.direction.x=-1
	self.direction.y=0
	plYon=4
elseif b_r==0 and b_u==0 and b_l==1 and b_d==1 then
	--sprite.play_flipbook("#player", "dl_w")
	self.direction.x=-1
	self.direction.y=-1
	plYon=5
elseif b_r==0 and b_u==0 and b_l==0 and b_d==1 then
	--sprite.play_flipbook("#player", "d_w")
	self.direction.x=0
	self.direction.y=-1
	plYon=6
elseif b_r==1 and b_u==0 and b_l==0 and b_d==1 then
	--sprite.play_flipbook("#player", "dr_w")
	self.direction.x=1
	self.direction.y=-1
	plYon=7
end

if b_r==1 or b_u==1 or b_l==1 or b_d==1 then
	if plYon==0 then sprite.play_flipbook("#player", "r_w")
	elseif plYon==1 then sprite.play_flipbook("#player", "ur_w")
	elseif plYon==2 then sprite.play_flipbook("#player", "u_w")
	elseif plYon==3 then sprite.play_flipbook("#player", "ul_w")
	elseif plYon==4 then sprite.play_flipbook("#player", "l_w")
	elseif plYon==5 then sprite.play_flipbook("#player", "dl_w")
	elseif plYon==6 then sprite.play_flipbook("#player", "d_w")
	elseif plYon==7 then sprite.play_flipbook("#player", "dr_w")
	end
end
--here is the problem. When I release the right and up button, 
--the plYon value should be 1. But I cannot release 2 buttons 
--at the same time. The last released button is either right button or up
--button. plYon=0 or plYon=2
if b_r==0 and b_u==0 and b_l==0 and b_d==0 then
	self.direction.x=0
	self.direction.y=0
	if plYon==0 then sprite.play_flipbook("#player", "r_i")
	elseif plYon==0 then sprite.play_flipbook("#player", "r_i")
	elseif plYon==1 then sprite.play_flipbook("#player", "ur_i")
	elseif plYon==2 then sprite.play_flipbook("#player", "u_i")
	elseif plYon==3 then sprite.play_flipbook("#player", "ul_i")
	elseif plYon==4 then sprite.play_flipbook("#player", "l_i")
	elseif plYon==5 then sprite.play_flipbook("#player", "dl_i")
	elseif plYon==6 then sprite.play_flipbook("#player", "d_i")
	elseif plYon==7 then sprite.play_flipbook("#player", "dr_i")
	end
  end
 ...
end

maybe you need

pprint(action_id) and press right+up or right+down and other combination

Any component that is on the stack containing an on_input() function will have that function called, once for each input action during the frame

You are correct that you will not be able to detect multiple input actions in the same conditional for the above reason. You need to track the input in on_input() and process the logic somewhere else (e.g. in update()).

1 Like

You can see an example of dealing with 8-way movement in this tutorial: Walking astronaut tutorial

1 Like

Walking Astr. tutorial contains direction walking animations and 1 idle animation. This example doesn’t answer my question. My player includes 8 direction walking animations and 8 idle animations. My question is about idle animation of 4 intermediate directions (left/up, left/down, right/up, right/down). For example, I press 2 keys for the right/up direction walking animation. When I release these two keys, the right/up idle animation should play, but either the up key or the right key animation becomes active. Either the right idle animation or the up idle animation is activated. I want the right/up idle animation to play. Please check the code above.

How about using a timer delay 0.1 when releasing either up or right key while you are in up-right direction?

Minimum distance condition or timer delay may be the solution. I will try. Thank u.

Well, I shared that tutorial since it does indeed have 8-way movement, although not 8 way idle animations. Here’s my take on a solution:

-- Create an animation name based on a base animation id and a direction
-- Examples: "walk", "walkup", "walkleft", "walkleftup" etc
-- Note: there's probably a better way to do this to avoid string concatenations
local function direction_to_anim(dir, base_anim_id)
	local leftright = ""
	if dir.x == -1 then
		leftright = "left"
	elseif dir.x == 1 then
		leftright = "right"
	end
	local updown = ""
	if dir.y == -1 then
		updown = "down"
	elseif dir.y == 1 then
		updown = "up"
	end
	return base_anim_id .. leftright .. updown
end

-- Play a flipbook animation on the sprite, ignoring the same animation
-- played twice
local function play_animation(self, anim)
	if self.current_animation == anim then
		return
	end
	self.current_animation = anim
	sprite.play_flipbook("#sprite", anim)
end

function init(self)
	msg.post(".", "acquire_input_focus")
	self.current_animation = nil
	self.movement_direction = vmath.vector3()
	self.facing = vmath.vector3()
end


function update(self, dt)
	-- play idle animation if not moving in any direction
	if vmath.length(self.movement_direction) == 0 then
		play_animation(self, direction_to_anim(self.facing, "idle"))
		return
	end

	-- move object
	local pos = go.get_position()
	pos = pos + self.movement_direction * 100 * dt
	go.set_postion(pos)

	-- play walk animation
	play_animation(self, direction_to_anim(self.movement_direction, "walk"))

	-- update facing
	self.facing = self.movement_direction
end

function on_input(self, action, action_id)
	if action_id == hash("left") then
		self.movement_direction.x = -action.value
	elseif action_id == hash("right") then
		self.movement_direction.x = action.value
	elseif action_id == hash("up") then
		self.movement_direction.y = action.value
	elseif action_id == hash("down") then
		self.movement_direction.y = -action.value
	end
end
1 Like