Trouble with play_animation

I am very new to Defold and am trying to do the extensions of the War Battles Tutorial.

I am stuck on the first extension, adding animations for all the movement directions.

I have added all the animations to sprites.atlas and my code for the on_input function in player.script is below:

function init(self)
	msg.post(".", "acquire_input_focus")

	self.moving = false
	self.firing = false
	
	self.input = vmath.vector3()
	self.dir = vmath.vector3()
	self.speed = 50
end

function final(self)
	msg.post(".", "release_input_focus")
end

local function update_animation(self)
	if self.input.x == 1 then
		play_animation("#Player", "player-left")
	elseif self.input.x == -1 then
		play_animation("#Player", "player-right")
	elseif self.input.y == 1 then
		play_animation("#Player", "player-up")
	elseif self.input.y == -1 then
		play_animation("#Player", "player-down")
	end
end

function update(self, dt)
	if self.moving then
		local pos = go.get_position()
		pos = pos + self.dir * self.speed * dt
		go.set_position(pos)
	end

	if self.firing then
		local angle = math.atan2(self.dir.y, self.dir.x)
		local rot = vmath.quat_rotation_z(angle)
		local props = { dir = self.dir }  
		factory.create("#rocketfactory", nil, rot, props)
	end

	self.input.x = 0
	self.input.y = 0

	self.moving = false
	self.firing = false       
end

function on_input(self, action_id, action)
	if action_id == hash("up") then
		self.input.y = 1
		update_animation(self)
	elseif action_id == hash("down") then
		self.input.y = -1
		update_animation(self)
	elseif action_id == hash("left") then
		self.input.x = -1
		update_animation(self)
	elseif action_id == hash("right") then
		self.input.x = 1
		update_animation(self)
	elseif action_id == hash("fire") and action.pressed then
		self.firing = true
	end

	if vmath.length(self.input) > 0 then
		self.moving = true
		self.dir = vmath.normalize(self.input)
	end
end

The player will not move and the error is as follows:
“ERROR:SCRIPT: main/player.script:20: attempt to call global ‘play_animation’ (a nil value)
stack traceback:
main/player.script:20: in function update_animation
main/player.script:58: in function <main/player.script:49>”

Any help will be appreciated! :slight_smile:

You need sprite.play_flipbook instead of play_animation.

1 Like

Thank you! The player is now moving but the animation stays at the same frame for each movement direction. How would I fix this?

1 Like

Hmmm… it looks like the animation gets played over and over again as long as the key is pressed, therefore it only shows the first frame. I would do something like this:

local current_animation
local function update_animation(self, anim)
    if anim ~= current_animation then
        sprite.play_animation("#Player", anim)
        current_animation = anim
    end
end

And then within on_input:

if action_id == hash("up") then
	self.input.y = 1
	update_animation(self, "player-up")
elseif action_id == hash("down") then
	self.input.y = -1
	update_animation(self, "player-down")
elseif action_id == hash("left") then
	self.input.x = -1
	update_animation(self, "player-left")
elseif action_id == hash("right") then
	self.input.x = 1
	update_animation(self, "player-right")
elseif action_id == hash("fire") and action.pressed then
	self.firing = true
end
3 Likes

Thank you so much! This works but the animations for left and right are the wrong way round. I think I flipped the wrong one horizontally in sprites.atlas

1 Like

That happens to me all the time.

You could also use only one animation and set the horizontal flip in code:

sprite.play_animation("#Player", anim)
sprite.set_hflip("#Player, self.input.x == -1)

self.input.x == -1 will resolve as true when facing left and false when facing right, meaning the sprite will get flipped horizontally when facing left, so the shared animation should be facing right.

But it might be needlessly complicated, plus the sprite would keep its flipped status even if you started moving up or down. Which might not be an issue, not sure.

Using separate animations works just as well and doesn’t cost you anything.

2 Likes