Arduboy Course - Part III: Animated Sprites

date
Jun 9, 2024
type
KnowledgeBase
year
slug
arduboy-basics-3
status
Published
tags
Arduino
C++
Microcontroller
summary
Let’s make some sprites and learn how to put them on the Arduboy!
Previous Chapter: Part II: MOVEMENT

Create a Sprite animation in Aseprite

Let’s make some animated sprites and learn how to put them on the Arduboy!
I’ll use Aseprite, but Piskel is another tool that would get the job done! (And it’s free!)
Let’s make some animated sprites and learn how to put them on the Arduboy! I’ll use Aseprite, but Piskel is another tool that would get the job done! (And it’s free!)
  • Open Aseprite, click New File... in the top left and enter the dimensions you want your Sprite to have.
    • Enter a Width of 8px and a Height of 8px. (For use on an Arduboy the dimensions must be multiples of 8!)
    • Choose Indexed as your color mode
    • Choose Black as your Background.
    •  
notion imagenotion image
notion imagenotion image
  • Now you see an empty document. Select all colours in the palette on the left side except for black and white and delete them (you can drag-select). The Arduboy’s display can only handle black and white, so no use keeping any other colours around…
  • Select white and use the pencil tool (B) to draw your first frame. (Press X to swap between black and white)
 
notion imagenotion image
  • Then open the timeline by pressing the 🎞️ button on the bottom right
  • Select Frame > Duplicate Cel(s) (ALT + D) to create a second frame and change it to start a little animation. You can press Enter to toggle playback.
  • Add a few more frames until you have a little animation.
notion imagenotion image
notion imagenotion image

Export from Aseprite

  • Select File > Export > Export Sprite Sheet (CTRL + E)
    • Under Layout, choose Sheet Type: Vertical Strip - this is the required format for Arduboy
    • Under Output, select PNG and choose a name and location for your file.
    • Click Export
    •  
notion imagenotion image
notion imagenotion image

Convert PNG to Byte Array

  • Drag your exported file onto the drop zone
  • Copy the output.
notion imagenotion image

Displaying sprites on the Arduboy

  • Paste the byte array into your project!
    • Per default the output starts with the size of the entire image. ‼️ Change the second number to the height of just one frame! ‼️ (In the coin example I have 48 as the height, but it’s actually 6 frames on top of each other, so I have to change the height to 8)
      Per default the output starts with the size of the entire image. ‼️ Change the second number to the height of just one frame! ‼️ (In the coin example I have 48 as the height, but it’s actually 6 frames on top of each other, so I have to change the height to 8)
  • Now we can draw the image with the Sprites class!
Here is the full code for an example where you see the animated CoinPowerup:
notion imagenotion image
Alright, It plays the animation! 
But the code is NOT very flexible and NOT easily re-usable, so let’s fix that next!
Alright, It plays the animation! But the code is NOT very flexible and NOT easily re-usable, so let’s fix that next!

AnimationPlayer Class

Let’s make a class that makes playing Animations simple for us!
We’ll put that class into a new file.
Let’s make a class that makes playing Animations simple for us! We’ll put that class into a new file.
  • In the Arduino IDE click onto the 3 dots () at the top right of the source code, then choose New Tab
  • This will create a new file, name it animationPlayer.h
    • 🎓
      In C++ you usually split your code into: → header files (.h) that contain variable and function definitions → source files (.cpp) that contain the actual implementations But we’re not going to do that. For simplicity’s sake, we’re just going to put everything into the header file and be done with it. 👍
notion imagenotion image
👉 This is the plan:
  1. Set up the new file
  1. We’ll create the struct Animation that holds all the information about one single animation - the byte array, the number of frames it has, and an array that determines how long each frame should be shown for (in milliseconds).
  1. Then we’ll create a class AnimationPlayer that can hold multiple Animation structs. Then we can easily switch between which of its Animations should be playing!

1. Basic File Setup: Include-Guard

We start out by adding a so-called “Include-guard”. This is to make sure that the same code won’t get included multiple times, even if we do #include ‘animationPlayer.h’ in multiple places.

2. Animation Struct

Now we create the Animation struct (In C++ a struct is basically the same as a class: a custom data type that can hold multiple variables and methods.)

3. AnimationPlayer Class

We want the AnimationPlayer class to do the following for us:
  • Hold data for multiple individual animations - this will allow us to have all the animations for a character or prop in one AnimationPlayer instance!
  • Draw the current frame of the current animation onto the screen
  • Automatically advance frames according to the frameTimes Array of each Animation
  • Automatically loop at the end
Here it is:
And here is how to use it:
✅ Works ✅ Much easier to use ✅ More flexible ✅ Easily reusable
notion imagenotion image

Animated Character

Following that same procedure, I made an animated character in Aseprite (I’m calling him “Burt”) and split the animation into several separate files:
  • Spawn
  • Idle
  • Walk Left
  • Walk Right
  • Jump-Off
  • Jump in Progress
  • Land
  • Crash
Here he is in all his byte-array-ish glory:
notion imagenotion image
And here’s how we’d set up all his animations in a single AnimationPlayer:
Now we have all the animations for a character in one object and we can switch between which animation plays!
But how do we know when to switch to which Animation? Good question! We’ll get to that, but first we need to add a few more pieces…

A new class for moving things: Entity

Wouldn’t it be great if we could bring all the momentum-calculation stuff also into a re-usable form? Then we could have multiple things that react to gravity and and that we can apply momentum to…
Wouldn’t it be great if we could bring all the momentum-calculation stuff also into a re-usable form? Then we could have multiple things that react to gravity and and that we can apply momentum to…
Let’s modify our Player struct from earlier and turn it into a class called Entity. Our player character will then be an instance of this class, and if we want to add non-player-characters (NPCs) later, they can also be instances of that same class!
👉 What we need:
  • Our class needs to have variables for everything we want to keep track off - position, momentum, size, etc.
  • Our class needs a few methods that we can call to make it do stuff.
    • Let’s make one called init to initialize it (set all the starting values)
    • One method to process new data.
Make a new 📄 file called entity.h and add this the code below
notion imagenotion image
Include it in the main file like this:
Now we can create a variable of type Entity and use its constructor to set it up like this:
Or we can call the init method at any time to assign values (think respawn)
In actual use, you’d then call process every frame, send along button states, and it would calculate all the momentum values and the x/y position from that inside our player Entity instance:
page icon
And with this we now have everything required to build any kind of animated Entity!
 

🎓 BONUS: How to make a dithering brush in Aseprite

  • Press B to switch to the Brush (Pencil) tool
  • Draw a pixel
  • Press M (Mask) and select the pixel plus 3 empty pixels
  • Press CTRL + B to turn your selection into a new brush
  • Switch to the Brush/Pencil tool again (B) - Now you can draw a dithering pattern.
notion imagenotion image
notion imagenotion image
 
 
 
 

Leave a comment