Larold’s Jubilant Junkyard” has become “Larold’s Retro Gameyard“. I’ve been working on this re-branding and migration for a while. All old tutorials should redirect you to this new site. If you see any errors, please let me know! See here for more information: What happened to Larold’s Jubilant Junkyard?

Drawing Backgrounds on The Game Boy Advance

When making your Game Boy Advance games, backgrounds will make up most of the world. You’ll use it for them environment, for buildings, and more. In this tutorial, you’ll learn how to use Butano Game Engine’s regular backgrounds.

Backgrounds in the Butano Game Engine, like Sprites, must be added to your project as bitmap images. You can view the basics of the Butano project structure here: Butano Project Structure for Making GBA games. The width and height of your background must both be multiple’s of 256px. With limit being above 4096×4096.

With your bitmap created, and added to the “graphics” folder, you should create a matching .json file. There are multiple types of assets in the Butano Game Engine, as you can see here: Butano Docs – Importing Assets. For this tutorial, we’ll be using a regular background. Here’s a basic background i found online, and edited slightly in Aseprite. It’s 256x156px in size.

I’ll name it clouds.bmp, and create a matching clouds.json.

Important Note: All graphics (sprites and backgrounds) must have all lowercase names. Also if you see an error, like “oceanbackground.bmp error: Invalid bits per pixel: 24” make sure you are exporting with an indexed palette.

{
  "type":"regular_bg"
}

Including your regular background in your code

After you run your project’s ‘make’ command, you’ll have a new bn_regular_bg_items_clouds.h file (in your project’s “build” folder). Include that, and the “bn::regular_bg_ptr” class into your main.cpp file:

#include <bn_regular_bg_ptr.h>
#include "bn_regular_bg_items_clouds.h"

Creating a background Pointer

Important Reminder: This should be done AFTER your call to “bn::core::init()

bn::regular_bg_ptr clouds = bn::regular_bg_items::clouds.create_bg();

Once you recompile and run your ROM file, you should have a basic background:

Background translation

Like with sprites, we can move the background around on the x or y axis. It’s graphics will loop around as your scroll. However, with regular backgrounds, we cannot scale or rotate them.

bn::regular_bg_ptr clouds = bn::regular_bg_items::clouds.create_bg();

while(true)
{
    bn::core::update();

    clouds.set_x(clouds.x()+bn::fixed(.2));
}

once compiled, you would see your background moving to the right, like so:

Multiple Backgrounds

The Game Boy Advance supports a total of 4 different backgrounds. Each can be individually controlled. Transparency is also supported on each background, allowing for very cool layer effects. Let’s add two more backgrounds on top! The other half of the previous ocean background, and a ground background,. Below i have ground.bmp and water.bmp.

Note: The purple is the first color in the palette, and will be transparent.

I’ll need to create a matching “ground.json” and “water.json” file. Both of which, are the same:

{
    "type":"regular_bg"
}

We’ll include them create pointers, and move them to the right also (but at different speeds).

#include "bn_core.h"
#include <bn_keypad.h>
#include <bn_regular_bg_ptr.h>
#include <bn_camera_ptr.h>
#include <bn_sprite_ptr.h>
#include "bn_sprite_items_testplayer.h"
#include "bn_regular_bg_items_water.h"
#include "bn_regular_bg_items_clouds.h"
#include "bn_regular_bg_items_ground.h"

int main()
{
    bn::core::init();
    
    bn::regular_bg_ptr water = bn::regular_bg_items::water.create_bg();
    bn::regular_bg_ptr ground = bn::regular_bg_items::ground.create_bg();
    bn::regular_bg_ptr clouds = bn::regular_bg_items::clouds.create_bg();


    while(true)
    {
        bn::core::update();

        clouds.set_x(clouds.x()+bn::fixed(.2));
        water.set_x(water.x()+bn::fixed(1));
        ground.set_x(ground.x()+bn::fixed(4));
    }
}

The result is a layered parallax scroll effect:

By default, they are drawn in the order you create the pointers. You can change which order they are rendered using the “bn::regular_bg_ptr::set_z_order(int)” function.

Removing Backgrounds

Like with sprites, backgrounds will automatically remove themselves when they go out of scope. Alternatively, you can use “bn::optional“s or hold the pointers in a bn::vector.

#include <bn_core.h>
#include <bn_keypad.h>
#include <bn_vector.h>
#include <bn_regular_bg_ptr.h>
#include <bn_camera_ptr.h>
#include <bn_sprite_ptr.h>
#include "bn_sprite_items_testplayer.h"
#include "bn_regular_bg_items_water.h"
#include "bn_regular_bg_items_clouds.h"
#include "bn_regular_bg_items_ground.h"

// Vector from #include <bn_vector.h>
bn::vector<bn::regular_bg_ptr,3> vectorOfRegularBackgrounds;

// Optional is part of #include <bn_core.h>
bn::optional<bn::regular_bg_ptr> optionalGround;


int main()
{
    // We NEVER create anything before this!
    bn::core::init();

    {
        // The clouds background will only last inside of the this scope (defined by the curly brackets)
        bn::regular_bg_ptr clouds = bn::regular_bg_items::clouds.create_bg();

        // The water background will last until it's removed from the tree
        vectorOfRegularBackgrounds.push_back(bn::regular_bg_items::water.create_bg());

        // The ground background is optional, with it's value set it will last until we change that value or reset the optional
        optionalGround = bn::regular_bg_items::ground.create_bg();

        // Wait for a to be pressed
        while(!bn::keypad::a_pressed())bn::core::update();
    }

    // When this part of the code is reached, the clouds background has gone out of scope and will be removed
    while(true)
    {
        bn::core::update();

        
        // Wait for 'A' to be pressed
        if(bn::keypad::a_pressed()){

            // This will remove the water background, whose pointer was in this vector
            vectorOfRegularBackgrounds.clear();
        }   

        
        // Wait for 'B' to be pressed
        if(bn::keypad::b_pressed()){


            // This will remove the ground background, which was optional
            // Make sure to always test for an actual value
            if(optionalGround.has_value())optionalGround.reset();
        }   

    }
}

Conclusion

That’s the basics of drawing backgrounds. for the sake of clarity the graphics were all separate bitmaps. But you could have them all defined a single bitmap, and use the “height” property to let Butano know how to split them.

Be sure to check out the tutorial on drawing sprites to add objects to your world.

Leave a Reply

Your email address will not be published. Required fields are marked *

THANKS FOR READING!

If you have any suggestions, and/or are confused about anything: feel free to leave a comment, send me a email, or a message on social media. Constructive criticism will help the gameyard, and others like yourself. If you learned something from this tutorial, and are looking for more content, check other these other tutorials. 

Drawing Backgrounds on The Game Boy Advance

Thanks for reading my tutorial, here are the files for that tutorial. 

Download Instructions

You’ll need the Butano Game Engine installed to run this. In addition, you’ll need the ability to run Makefiles. After you unzip the code, Make sure you update the LIBBUTANO . It should point to the “butano” folder INSIDE of your butano download folder. For me it was “c:/butano/butano”. After that, you can create your .gba file by running make.

If you want to make/request changes for the code, you can send me an email or put in a PR request on GitHub. Here’s a GitHub link for the code below.

Sign-Up for the "Gameyard Newsletter" for MOre Game Development News

If you like Retro Game Development, subscribe to the Gameyard Newsletter. Stay up-to-date with all the latest Game Boy news. It’s free, and you can unsubscribe any time!

Be sure to check your email inbox for a confirmation email.