Last month I published a post about my first attempt at dabbling with GBDK2020—a homebrew game development kit for the original Gameboy. I stumbled across GBDK on one of my aimless evening reddit browsing sessions, and as I’m looking for ways to learn and practice C, it made a lot of sense to give it a go.
In that post, I made the simplest thing I could think of—creating the text part of my logo into a tile map and scrolled it down the screen, similar to the original Nintendo boot screen we all remember.
While this was fun to make, and was arguably a reasonable introduction to GBDK, it wasn’t all that impressive and ultimately, the next step moving on from that only real next step is to make a functioning game.
This brings us to the topic of this post, as I’ve made some progress towards creating my very first Gameboy game – a simple, duinobit-branded space invaders clone.
The game I’m making
At first, I wanted to make a schmup, but it soon became apparent why the Gameboy isn’t exactly know if it’s catalogue of battle hell classics—in short, the system isn’t exactly up to it, given the limitations on the number of sprites you can have on screen at any given time. So I had to go back to the drawing board and have a rethink.
Moving on from the schmup idea, I figured one of the simplest types of game to whip up would be a space invaders clone. It’s not very sophisticated in terms of gameplay, and doesn’t require any real skill or talent when it comes to creating game assets, which is great for me, as I’m really not much of a talented pixel artist.
The latter was the arguably the main reason I opted to create this type of game, as following up from my animated logo, I could get away with using another asset I already had—the LED icon that forms the other part of my logo. This would mean simple game assets, letting me throw some sprites together with minimal effort and get cracking with the code.
What I’ve made so far
Right now, I’ve taken my first stab at creating the enemies for my space invaders clone. They’re animated, move, and have some limited timing to speed them up as they edge closer to the bottom of the screen—although it’s still very much a first attempt, with a fair bit of tightening up needed before moving onto the next few bits and pieces that make a game a game.
On that, I think I’ll take a stab at collision detection next—so you can expect a post on that topic in the next few weeks. I also want to start incorporating the text part of my logo, ideally as a defense bases, but I suppose we’ll see how difficult that turns out to be.
The project in action
If the gif below, you can see what I have so far—my rows of enemies, animated, moving, and speeding up as they go from side to side.

While it isn’t 100% there, it’s a good 80% of what’s needed to get the enemies for this game working, the remainder being collision detection, which will no doubt be the main focus of my next GBDK-related post.
The code
In the previous post, I gave a brief overview of a few Gameboy development concepts—we won’t repeat any of that here, instead I’ll just briefly summarise what the code does and how it works in a couple of bullets, before sharing it below.
- A struct called “gameEnemies” to define the enemy properties
- A function called “moveEnemies” which uses the “gameEnemies” struct
- And these are then animated in the games main while loop using a delay
Sounds simple—because it is.
Although, that said, I did take longer than I thought it would to get my head around this. It also doesn’t help that there isn’t much in the way of useful emulator debugging, at least that I’ve found so far.
If anyone has any solutions, please let me know in the comments, as this would be incredibly useful as this simple game gets more complex moving forward.
I’ve included the code I’ve made for this project so far, for anyone whose interested.
gameSprites.c
unsigned char gameSprites[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x3C,0x00,0x42,0x00,0x91,0x00,0xA1,
0x00,0x81,0x00,0x81,0x00,0x81,0x00,0xFF,
0x00,0x24,0x00,0x24,0x00,0x24,0x00,0x24,
0x00,0x24,0x00,0x24,0x00,0x24,0x00,0x24,
0x00,0x18,0x00,0x18,0x00,0x24,0x00,0x24,
0x00,0x42,0x00,0x42,0x00,0x81,0x00,0x81
};
main.c
#include <gb/gb.h>
#include <stdint.h>
#include "gameSprites.c"
int enemiesSpeed = 1;
int enemiesDirection = 1;
struct GameEnemies {
UBYTE spriteids[4];
UINT8 x;
UINT8 y;
UINT8 count;
UINT8 legs;
};
UBYTE spritesize = 8;
struct GameEnemies enemies;
void moveEnemies(struct GameEnemies* enemies, UINT8 x, UINT8 y, UINT8 count, UINT8 legs) {
int enemyY = 0;
int enemyX = 0;
for(int i = 0; i < count*2; i+=2) {
if(i == 12 || i == 24) {
enemyY+=18;
enemyX = 0;
if(enemies->legs == 2) {
enemies->legs = 3;
}
else if(enemies->legs == 3) {
enemies->legs = 2;
}
}
set_sprite_tile(i, 1);
move_sprite(i, x+(enemyX*20), y+enemyY);
set_sprite_tile(i+1, enemies->legs);
move_sprite(i+1, x+(enemyX*20), y+8+enemyY);
enemyX++;
if(enemies->legs == 2) {
enemies->legs = 3;
}
else if(enemies->legs == 3) {
enemies->legs = 2;
}
}
}
void setupEnemies() {
enemies.x = 32;
enemies.y = 32;
enemies.count = 18;
enemies.legs = 2;
moveEnemies(&enemies, enemies.x, enemies.y, enemies.count, enemies.legs);
}
void main(void)
{
SPRITES_8x8;
set_sprite_data(0, 4, gameSprites);
setupEnemies();
SHOW_BKG;
SHOW_SPRITES;
while(1){
moveEnemies(&enemies, enemies.x, enemies.y, enemies.count, enemies.legs);
if(enemiesDirection== 1) {
enemies.x+=enemiesSpeed;
if(enemies.x >= 54) {
enemiesDirection = 2;
enemiesSpeed++;
enemies.y+=8;
}
}
else if(enemiesDirection == 2) {
enemies.x-=enemiesSpeed;
if(enemies.x <= 12) {
enemiesDirection = 1;
enemiesSpeed++;
enemies.y+=8;
}
}
if(enemies.legs == 2) {
enemies.legs = 3;
}
else if(enemies.legs == 3) {
enemies.legs = 2;
}
delay(500);
}
}
A couple of notes about the code
It works—but it definitely needs some work. As I’ve said, I’m using this to help me learn C, which besides a little bit of C++ tinkering on Arduino, I’m completely new to, so it’s going to be a little clunky and unclean for the time being I’m afraid. The concept of structs is especially alien to me, although I feel like I’m edging towards a better understand of what they’re for and how to use them—slowly but surely, as they say.
Something I would note for any other novices looking to try their hand at this, is that I spent a lot of time trying to get everything working for variable enemy and row counts, but frankly, with the limited hardware it’s not worth the effort—you’re better off hardcoding numeric values, which is what I mostly ended up doing in the end.
I won’t go into too much details of how and what with the code—it’s there, you can have a look and get the idea. If anyone has any specific questions or queries on it, drop these in the comments and I’ll respond. I’m also welcome to any constructive criticism that will help me get a better grasp on all this as I continue with making the game.
Things I think I’ll change
While overall, I’m happy with the progress—there are definitely a few things I’ll likely change moving forward, as I think these will have a pretty big impact on how the game turns out.
I’ve included a few of these in the bullets below:
- Enemies being 8×16 is a pretty poor use of the limits on the sprite layer. I think I’ll try and remake these as single 8×8 sprites, giving me more enemies and making it a lot closer to being a space invaders clone than it is currently.
- Once I’ve reduced each enemy to a single tile, this will enable me to have more of them. While I think having 40 of these, like the version of space invaders on the original Gameboy had, might be a bit tricky, given the total 40 sprite limit on the sprite layer with GBDK2020, we might be able to get away with 35—or 5 rows of 7—without having to rework them to use the background layer.
- I’d also like to have the movement of each row timed differently, again making it closer to space invaders—I need to think how best to do this, but I think it would definitely be a worthwhile change to give it more of an authentic feel as we get closer to a finished product.
Summit it up and next steps
While I think I’ve made reasonable progress, it’s obviously some ways away from being a fully-fledged game. Scoring, collision detection, the defense bunkers, and of course, a player—there’s a lot left to do before this becomes a playable game.
One thing I might look at sooner rather than later is investing in some actual Gameboy hardware and a flash cart, as I’d hate to spend all this time on a game just to discover that it won’t run on original hardware without a massive overhaul.
Unfortunately, and as someone who has moved around a fair bit over the years, I’m not lucky enough to have one knocking about in a box somewhere, so I’ll have to pick one up from eBay—which from what I’ve seen, cost about as much as a kidney these days. It’s fair to say I was more than a little surprised by this.
Well, that’s all for now folks. If you made it this far, thanks for reading! And as always, any comments or questions are always welcomed, so drop those below and I’ll do my best to respond.