Sprite animation

Hello,

I'm on a Mac, trying to animate my player sprite when the A button is tapped. I'm copying the code I found in the 2020 example for the plane explosion animation.
The problem I have is that only the first of my 3 frames is showing.

This is my code:

function attackAnimation()
   local s = gfx.sprite.new()
   s.frame = 1
   local img = gfx.image.new("images/animation/attack/"..s.frame)
   s:setImage(img) 
   -- TODO: move animation to wherever the player is
   local x, y = playerSprite:getPosition()
   s:moveTo(x, y)
   
   function s:update()
      s.frame += 1
      if s.frame > 3 then
          s:remove()
      else
          local imageFolder = "images/animation/attack/"
          local img = gfx.image.new(imageFolder..s.frame)
          -- print("image is "..imageFolder..s.frame)
      end
   end
   
   s:setZIndex(2000)
   s:add()
end    

When I uncomment the print function it does print out images 1 through 3.

My attack() function is called inside update() and has this to show the animation:

function attack()
    if playdate.buttonIsPressed(playdate.kButtonA) then
        attackAnimation()
    end
end

Thanks in advance

This bit says after 3 frames remove the sprite.

1 Like

Indeed it does. I only have 3 frames. If I increase that to 20, the first frame will stay longer after you press the A button but will never show more than that first sprite.

Oh, sorry, both Nic and I misread your post. I thought you meant only your first 3 frames were showing.

The problem is that attackAnimation is being called every update if the button is pressed (because you're using buttonIsPressed) and current frame is being reset to 1 every time.

One solution would be to make sure to only call attackAnimation once per button press. In other words to not call it if you've already called it on that button press.

playdate.buttonJustPressed(button)

Returns true for just one update cycle if button was pressed. buttonJustPressed will not return true again until the button is released and pressed again. This is useful for, say, a player "jump" action, so the jump action is taken only once and not on every single update.

https://sdk.play.date/inside-playdate/#f-buttonJustPressed

But there are other solutions depending on where in your code you want to solve the problem, or how you want the game to behave.

1 Like

After you load your new frame, you need to assign it to the sprite

function s:update()
      s.frame += 1
      if s.frame > 3 then
          s:remove()
      else
          local imageFolder = "images/animation/attack/"
          local img = gfx.image.new(imageFolder..s.frame)
          s:setImage(img)
          -- print("image is "..imageFolder..s.frame)
      end
   end
1 Like

After you load your new frame, you need to assign it to the sprite

Yes, it's assigned at the end of the function

Ah, cheers for that. Unfortunately, changing it to buttonJustPressed still shows me the first frame only.

Nic is correct here.

Ah, I see the issue now! You're absolutely right. Complete oversight on my part.

Cheers both!

2 Likes