GBDK Color Tutorial
Contents
Introduction
This tutorial seeks to extend your knowledge of basic spriting on the Game Boy by adding colors to sprites, backgrounds, and the window layer, and to act as a human-readable reference with real-world examples. If you've compiled your first .gb but want to spruce it up a bit, this tutorial is for you.
Prerequisites
This tutorial leans heavily on the GBDK_Sprite_Tutorial and the GBDK_Layers_Tutorial. They're not required, but this tutorial will assume you have an understanding of the topics they cover, including the tools used.
Step one: Create the tiles
We're stealing the smiley sprites from here.
Step two: Basic code
Fire up your text editor of choice and throw in the basics, pasting in the smile array:
#include <gb/gb.h> #include <gb/cgb.h> //Created with GBTD, exported to .c with options from: 0, to: 1, label: smile unsigned char smile[] = { 0x0F,0x0F,0x30,0x30,0x40,0x40,0x40,0x40, 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, 0x84,0x84,0x84,0x84,0x80,0x80,0x80,0x80, 0x44,0x44,0x43,0x43,0x30,0x30,0x0F,0x0F, 0xF0,0xF0,0x0C,0x0C,0x02,0x02,0x02,0x02, 0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, 0x21,0x21,0x21,0x21,0x01,0x01,0x01,0x01, 0x22,0x22,0xC2,0xC2,0x0C,0x0C,0xF0,0xF0, 0x0F,0x0F,0x30,0x30,0x40,0x40,0x40,0x40, 0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84, 0x84,0x84,0x84,0x84,0x80,0x80,0x80,0x80, 0x44,0x44,0x43,0x43,0x30,0x30,0x0F,0x0F, 0xF0,0xF0,0x0C,0x0C,0x02,0x02,0x02,0x02, 0x01,0x01,0x01,0x01,0x01,0x01,0xF9,0xF9, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x22,0x22,0xC2,0xC2,0x0C,0x0C,0xF0,0xF0 }; void main(){ SPRITES_8x16; set_sprite_data(0, 8, smile); set_sprite_tile(0, 0); move_sprite(0, 75, 75); set_sprite_tile(1, 2); move_sprite(1, 75 + 8, 75); SHOW_SPRITES; }
Step three: Compile change
There's a flag in the code that needs to be set at the compile stage: -Wl-yp0x143=0x80
Add that in as an argument when running lcc
:
/path/to/lcc -Wl-yp0x143=0x80 -o set_sprite_palette.gb set_sprite_palette.c
Without that bit, the ROM will compile as a regular non-paletted Game Boy game and show up as green on green.
Running that ROM should look like this:
Pretty bland, as it's still using default colors.
Step four: Palette data
Let's dig into the relevant functions: set_sprite_palette
and set_sprite_sprite_tile
.
If you crack open /path/to/gbdk/include/gb/cgb.h
you'll see a bunch of predefined colors, like these:
#define RGB_RED RGB(31, 0, 0) #define RGB_BLUE RGB( 0, 0, 31) #define RGB_PURPLE RGB(21, 0, 21) #define RGB_LIGHTFLESH RGB(30, 20, 15)
You can use these or make your own with the RGB(red, green, blue) format, with 0 being none of a color and 31 being one hundred percent of that color. You can also enter each number in as a raw number (see step five). Let's define an array of colors:
UWORD spritePalette[] = { 0, RGB_RED, RGB_ORANGE, RGB_YELLOW, 0, RGB_GREEN, RGB_BLUE, RGB_PURPLE 0, RGB_BLACK, RGB_GRAY, RGB_WHITE };
Let's break this down. Each line is a four-color palette. The first entry is the transparent color, so leave it as 0. The next three are the draw colors in order. In GBTD's default settings, these replace the light, dark, and darkest colors, in that order.
Throw that above main
.
Now let's convert that into a palette with GBDK:
set_sprite_palette(0, 3, spritePalette);
This puts three color schemes into the software's palette set, starting at zero. It pulls from the spritePalette
array we defined above, four colors at a time.
If we were to define any more from a different source, we'd want to start at entry 3 (the fourth entry after 0, 1, 2 and 3).
Now that we've loaded our palette, let's start painting with it.
set_sprite_prop(0, 0);
This takes sprite number 0 (currently set at the left 8x16 pixels of the face) and assigns the color scheme in slot 0 (0, red, orange, and yellow) to it. Put this after the sprite has been set but before SHOW_SPRITES;
. Don't forget to change the other half too:
set_sprite_prop(1, 0)
Compile and run that to see the changes. I won't post a screenshot as it's just the last picture but red.
Step Five: Let's do something cool
I made a quick three-column gradient in GBTD, set it to display, and in the while loop, set the three columns to progress at different rates. Changing the sprite palette will, of course, change the colors of everything using that palette. Consider something like Super Mario's star mode color changes without duplicating tiles, or applying shadows to already-rendered sprites.
#include <gb/gb.h> #include <gb/cgb.h> unsigned char gradient[] = { 0xE3,0x1F,0xE3,0x1F,0xE3,0x1F,0xE3,0x1F, 0xE3,0x1F,0xE3,0x1F,0xE3,0x1F,0xE3,0x1F }; UWORD spritePalette[] = { 0, 0, 0, 0 }; void main(){ set_sprite_data(0, 1, gradient); set_sprite_palette(0, 1, spritePalette); set_sprite_tile(0, 0); move_sprite(0, 75, 75); set_sprite_prop(0, 0); SHOW_SPRITES; while(1){ spritePalette[1] += 1; if(spritePalette[1] > 32767) spritePalette[1] = 0; spritePalette[2] += 10; if(spritePalette[2] > 32767) spritePalette[2] = 0; spritePalette[3] += 100; if(spritePalette[3] > 32767) spritePalette[3] = 0; set_sprite_palette(0, 1, spritePalette); delay(50); } }
Step Six: Other layers
Note to self: Do this
Takeaway
Hopefully now you can compile to a Gameboy Color ROM and apply colors to various tiles.
Exercises
- Overlap two sprites for twice the colors
- Animate backgrounds by changing the color palette of background tiles