PICO-8
Animate a Sprite

Follow along to learn easy sprite animation!
In making this demo, we learn about drawing sprites, using coordinates X and Y, and decimals.
This lesson focuses on ANIMATION!
Challenges!
After following the lesson, take on some of these challenges to test your knowledge and skills!
1. Change the sprite to a different character!
2. Make the sprite move on the Y axis.
3. Instead of warping the sprite back to the left side, make him flip around and jump the other way.
How to animate a sprite!
[ Video Coming Soon! ]
Explanation of Code!
-
What is a sprite?
Here are the sprites we use in this example animation cartridge.
You can copy these sprites or make your own! Make sure you draw each of these sprites in the exact same place, because the code will look for their sprite number. But once you understand the code, you can draw as many sprites as you want, where ever you want!
This is where you will want to draw your sprites in the PICO-8 sprite editor.
(We try not to draw in the very first space (Sprite #0) because that is a default empty tile when using the map editor.)
-
What is a variable?
The first code we write at the top of the file are the variables. These help us set up the game and keep track of data.
When variables are set outside of any function, that means that they will be set before anything even starts running in the game. And that means any code written after these variables will be able to find and use them.
If you are using the
_init()
function, then that would be a good place to put these variables for each game object that you want to animate. Or if you are using tables to organize your game objects then these variables can be inside of the objects' tables. There is an example of that at the end of this page.sprite = 1 x = -8 y = 59 timing = 0.25
The first variable is named
sprite
. Then the equals sign tells the game to remember it with whatever we write next.sprite
holds a number and that number is the sprite-number of the first sprite in the sprite sheet.
What is a sprite?The next variables are named
x
andy
. Together these tell the game where the sprite is on the screen.x = -8
andy = 59
because the screen has 128 pixels from left-to-right and top-to-bottom (# 0-127). The X is where the sprite will start on the X-axis (horizontally) and -8 will be just to the left of the visible screen. The Y is where the sprite will start on the Y-axis (vertically) and 59 places the sprite in the middle of the screen.The next set of variables are for keeping track of the animation timing.
timing = 0.25
timing
is for setting a delay time between each animation (sprite change).
function _draw()
cls()
spr(sprite, x, y)
print(sprite)
end
_draw()
runs after _update and draws to the game screen 30 times every second.
cls()
clears the game screen.
spr()
draws a sprite at X and Y coordinates on the screen.
spr(sprite, x, y)
tells the SPR function to draw the sprite number at the X and Y variables we set above.
print(sprite)
will write the sprite variable to the screen. It will show as the number as it counts up by timing so you can see how fast the animation is happening.

function _update()
--animate
sprite += timing
if sprite >=5 then sprite = 1 end
--move
x += 1
if x > 127 then x = -8 end
end
The function _update()
makes changes to the game 30 times every second.
You can also use _update60()
to double that speed to 60 times per second.
But if you choose to do that, then the animation will move twice as fast, so you should cut the
timing
variable in half.
The first thing we will update is the sprite number to create the animation.
sprite += timing
increases the sprite-number by the number you set in the timing
variable.
Why should timing
be a decimal between 0 and 1.
Because the very next sprite is 1 sprite number away but if we add 1 every time _update() runs, then we will be changing the sprite way too fast. And obviously, if we add 0, then the sprite number will never change. So it has to be a decimal between those two.
Let's say we use 0.5 for our timing
number. That means 30 times a second (every time _update runs)
the sprite number will increase halfway towards the next sprite. And that means instead of changing the sprite
30 times every second, it will change the sprite 15 times every second. That is how we are controlling the timing
with this number.
So play around with this number to get the animation timing how you'd like it. The closer to 0 you make it will slow down the animation. The closer to 1 you make it will speed up the animation.
To make this work, you must draw your sprites next to each other in a row and slightly change each drawing, and that will create the look of one character being animated.
Now that we are increasing the sprite number, what happens when it gets to the last frame of our character's sprites?
Well that means we need to restart the animation loop. So let's check when the sprite number gets to the sprite beyond our last sprite in the animation frames, and reset it to the starting frame. It's as simple as this one line of code:
if sprite >= 5 then sprite = 1 end


The next thing we will update about this sprite animation is the position.
x += 1
will increase the X position by 1 pixel, making the sprite drawn 1 pixel to the right.
if x > 127 then x = -8 end
will check if the sprite moved too far to the right and off the screen.
And if that happens, then x = -8
will reset the sprite's X position to where it started.
Together, this code will simply start the sprite on the far left, make it move to the right, and then warp it back to the left side to infinitely walk across the screen.


sprite = 1
x = -8
y = 59
timing = 0.25
function _draw()
cls()
spr(sprite, x, y)
print(sprite)
end
function _update()
--animate
sprite += timing
if sprite >= 5 then sprite = 1 end
--move
x += 1
if x > 127 then x = -8 end
end
RUN!


Warning: If you are new to coding, this may look complicated. It uses tables to organize all of the different game objects. So if you have not used tables before, we suggest reading about tables in our Guide to help understand this.
What's up with tables?
--animate multiple sprites
--by nerdy teachers
function _init()
--create a table for player data
player = {
sprite = 1,
x = -8,
y = 59,
timing = 0.25,
}
--create a table for enemies data
enemies = {}
--set items sprites, positions, timing, first and last animation frames
enemy1 = { sprite=5 , x = -20, y = 5, timing = 0.1, speed = 1.25, first = 5, last = 8 }
enemy2 = { sprite=9 , x = -14, y = 30, timing = 0.2, speed = 0.4, first = 9, last = 12 }
enemy3 = { sprite=13 , x = -11, y = 90, timing = 0.4, speed = 0.75, first = 13, last = 16 }
--add each enemy to enemies table
add(enemies,enemy1)
add(enemies,enemy2)
add(enemies,enemy3)
--create a table for items data
items = {}
--set items sprites, positions, timing, first and last animation frames
item1 = { sprite=48 , x = 30, y = 110, timing = 0.3, first = 48, last = 55 }
item2 = { sprite=56 , x = 60, y = 110, timing = 0.25, first = 56, last = 59 }
item3 = { sprite=60 , x = 90, y = 110, timing = 0.15, first = 60, last = 63 }
--add each enemy to enemies table
add(items,item1)
add(items,item2)
add(items,item3)
end
function _draw()
cls()
--draw player
spr(player.sprite, player.x, player.y)
--draw enemies
for enemy in all(enemies) do
spr(enemy.sprite, enemy.x, enemy.y)
end
--draw items
for item in all(items) do
spr(item.sprite, item.x, item.y)
end
end
function _update()
--animate player
player.sprite += player.timing
if player.sprite >= 5 then player.sprite = 1 end
--move player
player.x+=1
if player.x > 127 then player.x=-8 end
--enemies
for enemy in all(enemies) do
--animate
enemy.sprite += enemy.timing
if enemy.sprite >= enemy.last+1 then
enemy.sprite = enemy.first
end
--move
enemy.x += enemy.speed
if enemy.x > 127 then enemy.x=-8 end
end
--items
for item in all(items) do
--animate
item.sprite += item.timing
if item.sprite >= item.last+1 then
item.sprite = item.first
end
--no moving code for items
end
end
Run

Here is what we drew in our sprite sheet. The same player as before, then 3 enemies, and 3 items.

Notice that they all use only 4 sprites to create their animation except for the coin which uses 8.
We separate the player
, enemies
, and items
into 3 different tables.
For the player, we simply wrote the player data directly into the table. But the enemies
and items table will hold smaller tables for each enemy's data and each item's data. So
we wrote out those tables for each enemy as enemy1
, enemy2
, enemy3
, and
each item as item1
, item2
, item3
.
You may notice some new variables stored with those objects. After timing
, we
also added speed
to the enemies to allow each enemy to move at different speeds.
Then we added first
to remember the starting sprite number and last
to
remember to last sprite number to be used in the checks that happen in the _update() function.
The _draw()
and _update()
functions use a special table loop.
for entry in all(table)
That will cycle through each entry in a table and run the same code over them. This keeps our code nice and short. The only hard part is imagining what the tables look like and understanding how to prepare the table data for loops like this.
Save this cartridge image and open in your PICO-8 to get the sprites and the code so you can start playing around with it.


font
