How-To: Smooth Animation

Here's how I did smooth animation or "decimal draw" as we call it, for the game I'm working on.

space_dreamer
Space Dreamer!

The variables you'll need:

on load do
  // This will prevent the player sprite from lagging behind when the button is held
  config.inputRepeatDelay = 0.2
  config.inputRepeatBetween = 0.2

  // This will be the target position that the sprite will be moving to
  playerX = 0

  // This will be the position our sprite will be drawn
  playerDecimalX = playerX

  // How much the sprite will move every frame in "pixels"
  movementSpeed = 0.25
end

The movement speed variable only has a few values that work. It must also be able to add up to a whole number; if not, it will cause jittering of the player sprite.

For the movement of the player:

on update do
  if event.dx==1 then
    playerX++
  elseif event.dx==-1 then
    playerX--
  end
end

The player might also lag behind when the button is repeatedly pressed, so you might have to do this instead:

on update do
  frameElapsedMoveCheck = event.frame
  frameElapsedMoveCheck -= frameElapsedMove
	
  // This is calculated by the delay in secs 
  // 0.2 secs (config.inputRepeatBetween's value) * 20 frames = 4 frame delay
  if frameElapsedMoveCheck>=4 then
    if event.dx==1 then
      playerX++
      frameElapsedMove = event.frame
    elseif event.dx==-1 then
      playerX--
      frameElapsedMove = event.frame
    end
  end
end

To achieve smooth animation:

on draw do
  // The playerDecimalX will be increased/decreased as long as it isn't equivalent to playerX
  if playerDecimalX<playerX then
    playerDecimalX += movementSpeed
  elseif playerDecimalX>playerX then
    playerDecimalX -= movementSpeed
  else
    playerDecimalX = playerX
  end

  draw "player" at playerDecimalX, 7
end

The y-axis could be done easily by doing the same thing. For the game I'm making, I only have to use the x-axis.

The result of the code thus far will be this.
artifacts
Yeah, it doesn't look good.

Because it isn't meant for Pulp, a trail of artifacts / rectangles are created when moving. To fix this, there are two ways:

First, is to update the tile in the background and draw it before the player.

on draw do
  // Since the trail is behind the player you'll have to do this
  x = playerX
  x--

  // Gets the name of the tile behind the player sprite and draws it, cleaning the artifacts
  checkTileName = name x,7
  
  draw checkTileName  at x,7

  // Then draw the player
  if playerDecimalX<playerX then
    playerDecimalX += movementSpeed
  elseif playerDecimalX>playerX then
    playerDecimalX -= movementSpeed
  else
    playerDecimalX = playerX
  end

  draw "player" at playerDecimalX, 7
on

If your player sprite has transparency in the middle or has a slower speed, you'll have to clean both behind and in front of the player.

Pro:

  • Optimizable Performance

Cons:

  • A lot of code to write*
  • Many bugs

There might be a lot of code to write, especially if you have many sprites; you'll have to write code to clean the artifacts for every single one. The loss of performance for this method scales with how much it is used, but with a bit of optimization and also depending on the kind of game you're making, it could be a better option.

Second, is to use a tile for a background that will update every frame.


2 frames with 20 fps

Pro:

  • No code required

Cons:

  • Overall decrease in performance
  • Animating tiles in 20 fps

This is what I used for my game. It requires the least amount of effort, and because my game will have many entities and enemies that will be drawn on the screen, I don't have to write code for them. However, the tiles will always be updated even though there's no sprite being drawn, resulting to a loss in performance.

And that's it! There's a lot more going on in the example gifs, but that's basically how to do smooth animation in Pulp. I look forward to seeing more amazing games that utilize this.

6 Likes

Brilliant! Thanks for making this

2 Likes

This is a great writeup, thanks for taking the time!

2 Likes