Arduboy Course - Part I: Basics

date
May 26, 2024
type
KnowledgeBase
year
slug
arduboy-basics
status
Published
tags
Arduino
C++
Microcontroller
summary
The basics of the Arduboy library. Draw shapes, draw text, get input, play sound!
🎓
Sections marked with 🎓 are advanced knowledge. You can ignore these for now and unfold them once you’re ready to dig deeper!
Arduboy Basics (PDF) ← Here’s an even simpler single page introduction for you to 🖨️ print
Arduboy Basics (PDF) ← Here’s an even simpler single page introduction for you to 🖨️ print

Arduboy Course (so far)

  • 📘 Arduboy Part 1: Basics (this page!) ⬅️ YOU ARE HERE

Arduboy Basics

This page is a basic introduction to the Arduboy and the “Arduboy2” library we will use to make games for the Arduboy.
This page is a basic introduction to the Arduboy and the “Arduboy2” library we will use to make games for the Arduboy.
We’ll go through:
  • What even is an “Arduboy”?
  • How to set it all up
  • How to draw to the screen
  • How to work with button input 🎮
  • How to turn on the LED 🔆
  • How to make sound 🔉

What’s an Arduboy?

ℹ️
An Arduboy is a portable gaming console with a 128X64 pixel, 1-bit OLED display (black and white only), running on an ATmega32u4 chip (as you find on the Arduino Leonardo, Arduino Micro or Sparkfun Pro Micro)
It’s easy to build one yourself or you can order a credit-card-sized version on https://arduboy.com
notion imagenotion image

Prerequisites ⬇️

  • Install the Arduboy2 library from within the Arduino IDE or PlatformIO
⚠️
If you have a homemade Arduboy that uses slightly different components, you MUST NOT have this library installed (uninstall it if you have it installed). Instead use the Arduboy-homemade-package (follow the instructions on their github page - it adds compatibility for a wide range of displays and microcontrollers)
 
notion imagenotion image

Arduboy Library basics

💡
If you haven’t, check out the article about the basics of Arduino C++
Here’s a very simple example that tracks if the user presses the A or B button and prints “A” and/or “B” onto the screen while these buttons are held down:
notion imagenotion image
Heres’ an explanation of what it does:
  1. We include the Arduboy2 library with #include <Arduboy2.h>
  1. Create an instance of the Arduboy2 class. (Arduboy2 arduboy;, where arduboy is our variable name for the object. ← This is what we’ll be talking to.)
  1. We call arduboy.begin() in setup() to get it to do whatever it needs to do internally to be ready. (Initialize the hardware, show the Arduboy boot logo, etc.)
  1. At the top of loop we do if(!(arduboy.nextFrame())) return; to make it wait until it’s time to render the next frame (per default the framerate is limited to 60fps). This line essentially means: if we’re not (!) ready for the next frame (arduboy.nextFrame()), then return (exit the loop() function before anything below this line can be executed) - so the program will only run this first line again and again and again until the time is ready to render a new frame!
  1. Then we do whatever we want to do - in this case we’re clearing the screen, then polling the buttons, then checking for button presses and printing stuff onto the screen (actually goes into the screen buffer at this point)
  1. Finally, we tell it to render everything from the screen buffer onto the actual screen so our users can see it!

🎓 Extended example

Here is the same example, but extended to use all the buttons. In addition, it also turns on the LED while a button is pressed.
notion imagenotion image

Drawing to the screen 🖥️

Every frame we want to do the following:
  1. Clear the screen: arduboy.clear()
  1. Draw to the framebuffer with all the Text, Shapes and Sprite functions explained below
  1. Plot the contents of the framebuffer onto the actual screen: arduboy.display()

🎓 Framebuffer Explanation

Why can’t we draw directly onto the screen? Because all instructions are executed right away. So if you clear the screen (or parts of it), then you’ll see a blank screen before the bits and pieces you draw onto it appear one after the other. The result is flickering.
The age-old solution to this issue is to draw everything into a buffer (the ”framebuffer”) and then plot the entire buffer onto the screen at once. Fixed! Now one complete image is followed by another complete image.
Fortunately the Arduboy2 library handles all of this for us! All we have to do is arduboy.clear() in the beginning and arduboy.display() in the end!

Text 🔤

Define a color, set the cursor to where you want to put your text, then print it!

Shapes 🟣

This is how we can draw pixels, lines, circles, rectangles, and triangles:
Pretty much the same functions also exist in versions for filled shapes:
ℹ️
For most of these functions the color attribute is actually optional and will default to WHITE if omitted.

Sprites 🖼️

We can draw images to the screen as well! But we don’t store our images as files, instead we include them in the source code.
  • Make an image (Aseprite is my favourite sprite editor, but you could just as well use a free web-tool like Piskel!)
  • You can include multiple sprites/frames in a single image, but be sure to stack them vertically!
notion imagenotion image
The result will look like this:
⚠️
The width can be any value. The height must be a multiple of 8 pixels. It makes sense to create a sprite sheet and include multiple frames in the same image.
⁉️
PROGMEM is a special keyword used to store data in the microcontroller’s program memory (flash memory) instead of RAM. We don’t want to change our Sprites on the fly, so why waste RAM?
Then we can draw an image onto the screen like this:
😕
wtf does :: do? TL;DR: Just accept that that’s what you have to do in this case 😉 But if you want to know more: :: is the Scope Resolution Operator and is used to access static members of a class, meaning we use it to access a method of a class that can be accessed without having an instance object of that class. More info in the Arduino C++ section under Classes!
There’s more ways to draw sprites!
Part III will be all about making and displaying Sprites!
Part III will be all about making and displaying Sprites!

Input 🕹️

First we need to call pollButtons - this is needed to track the state of buttons over time.
Then we can check if buttons are pressed or not pressed, etc.

LED 🔆

Use the setRGBled method to change the color of the LED. The 3 arguments take values for Red, Green and Blue from 0 to 255.

Sound 🔊

The BeepPin1 class allows you to play back tones via the Buzzer of the Arduboy.
For this to function properly you need to:
  • Call begin() on the beep instance
  • Call timer() on the beep instance (without this beeps won’t stop automatically!)
  • Call tone(timer count, duration in frames) to make it beep

🎓 Beep 2 tones at the same time

There’s also a BeepPin2 class, so we can play 2 tones at the same time!

🎓 Play Melodies

🎶
To play entire melodies we can use the ArduboyTones library!
Installation:
  • Sketch > Include Library > Manage Libraries…
  • Search for “arduboytones”
  • Click the Install button to Install the ArduboyTones library
  • Add #include <ArduboyTones.h> at the top of your sketch
Playing individual tones is very similar to the BeepPin class, but easier! We don’t need to convert to Hz and we can enter the durations in milliseconds instead of frames.
Playing a Melody
We can define an entire little melody as an array of pairs of frequency and duration.
The example below plays 220Hz (A3) for 1 sec (1000ms), then 0 Hz (pause) for 250ms, then 440Hz (A4) for 500ms, then 880Hz (A5) for 2 sec. Then it ends the sequence with the special TONES_END value
⁉️
PROGMEM is a special keyword used to store data in the microcontroller’s program memory (flash memory) instead of RAM.
Here’s a full example that plays this same melody whenever you press the A button:
 

Building a .hex file

Arduino games are often shared as binary .hex files. This is how you create one!
Arduino games are often shared as binary .hex files. This is how you create one!
Arduino IDE:
  • Sketch > Export Compiled Binary
  • Go to the build folder that was created in your project folder
  • Find the .hex file in there
VSCode + PlatformIO:
  • Add this line to platformio.ini: build_type = release
  • Make a build ✔️
  • Go to the .pio/build/ folder that was created inside your project folder
  • Find the .hex file in there
👍 Now you can try it in the Ardens Microboy Simulator or share it online!
 
➡️ Continue in Part II

Other Resources

  • 🌐 Huge list of games - find one you like and learn from the source code!
 

Leave a comment