In this tutorial series you will learn how to make a simple single-player Pong-like game for the Sega Mega Drive using SGDK! If you just want to see the full source code, you can get it from Github.
Megapong 3 - Importing Resources
Welcome back! Last time we set up our development environment to make things easier for us. This time things will get a bit more exciting, as we’ll import a graphic and use it to draw the background for our game! We have a lot ahead of us, so let’s rock. You can either use the project from part 2 or create a new one. This one will become our game, so remember where you put it…
Compiling Resource Files
Resource files are any type of media file that you’d like to use in your game. Images for sprites and backgrounds, audio files for effects and music… all the good stuff. However, before the Mega Drive can deal with our files, we’ll have to compile them into a format it can understand. Luckily SGDK will once again do all the heavy lifting for us!
First of all we need something to actually compile. Download the archive for this part of the tutorial here. Inside you’ll find an image file called
bgtile.png. We’ll need that in a second, so put it somewhere within reach. For reference, this is what it looks like (scaled up 4x so you can see it better:)
Please note that you cannot right-click and save this image, you have to download the .zip file above and use the file within!
Now open up your project folder. Inside you will find a subfolder called
res. This is where we’ll put all our resources the project needs. Let’s be a bit more organized though! Open up the
res folder and create a new subfolder within it. Name it
tiles. Now put
bgtile.png inside of it! It always pays to be organized, so it’s a good habit to get into.
Alright, now we have our file inside the project folder. However, we still need to tell SGDK what to actually do with it. So take another look inside your
res folder. We’ll now create a file that basically acts as a list of all our resources. SGDK will use that list to convert and import everything we want to use in our game. It’s basically just a text file with a fancy extension, so create it from within VSCode or simply create a new text file in Windows Explorer. Then name that file
resources.res. Make sure it’s directly inside the
Now open that file up and copy the following line into it:
IMAGE bgtile "tiles/bgtile.png" 0
Now save the file. So…what does this mean? Let’s look at it step by step.
IMAGE: This tells SGDK that we want to create a resource of type IMAGE. There are other types (like SPRITE, BITMAP…) but for our purposes, IMAGE is the best choice.
bgtile: This is the name we will use to refer to our resource inside the code. It doesn’t have to match the file name, but I’d recommend it since things could get confusing otherwise.
tiles/bgtile.png: This is the location of the resource we want to import (relative to the project folder).
0: This tells the resource compiler what compression to use. Since our game will hardly tax the Mega Drive hardware we’ll set it to 0 for now, which means no compression.
Since the tile is our only resource for now, you can close
resources.res. But before we try it out there is one final thing you need to do. In your
main.c file, add the line
#include <resources.h> at the very top, after
#include <genesis.h>. When SGDK processes our resources it will create a header file (
resources.h) with our stuff in it. Unless we import it, our game won’t know that it’s there, which would lead to errors. So make sure that line is there!
Now compile your game and if everything went well, you should now see the
resources.h file in the
res folder. So far so good!
Putting The Tile On Screen
Now that we have our tile image in the proper format, we’ll put it on screen. There are two steps in order to achieve this: First we’ll load the tile, then we display it. Which is kind of obvious, I guess. Let’s just do it first, then I’ll explain some of the theory behind it.
Put the following line of code at the beginning of your
main function in
VDP_loadTileSet does what it says: It loads a tileset. Remember that we imported our file as an IMAGE? A resource of type IMAGE contains three properties:
map. Since we need a tileset, that’s the property we’re referencing. The name
bgtile is the one we set in
resource.res. If you used a different one, you’ll have to use it here as well! Ignore the
DMA for now.
Okay, with the tile loaded, let’s throw it on the screen. This line of code makes that happen, so put it after the previous one:
(Note: If you’re using SGDK 1.41, replace
Now compile your game and if everything went well, you should have a tile on the screen! …even though the color seems off?
We’ll take care of that soon, but first some explanations!
The Mega Drive uses planes to display graphics. When we’re working with tiles, you have two background planes to work with: Plane A and Plane B. In simplified terms you can think of them as layers that determine at what depth your tiles are drawn. For example, Plane A is drawn above Plane B, so you would use that one for foreground tiles, like the ground your character walks on, for example. Plane B is drawn behind Plane A, so that’s where you’d draw a sky or something along those lines. (The priority system deciding the draw order is actually a bit more complicated than that and can easily be overridden, but for this tutorial you can stick to the layer analogy.) Whenever you place a tile on the screen you have to tell SGDK what background plane to draw it on. To refer to the two background planes you use the defines
BG_B (before version 1.50 these were called
One MD tile is always 8x8 pixels big. Because this size is fixed, tile coordinates in SGDK are not given in pixels, but tiles. Meaning: If we put a tile at position
(1,1) the tile will be placed at pixel-position (8,8). If we add a tile at (2,1), this new tile we appear right next to the first one, at pixel-position (16,8). It’s very simple and useful, but it’s important to keep it in mind, as other things within SGDK actually use pixels as a measure.
Finally, let’s quickly talk about VRAM. This is where the Mega Drive stores all the graphics needed for the game. For now you can basically imagine it as a stack of tiles. Whenever you load tiles using
VDP_loadTileSet, SGDK puts that tile onto the VRAM stack. In order to access the tile we want, we have to remember where it was put. This is done using a simple integer: The first tile to be loaded is tile
1, the second tile is
2 and so on.
With all this theory, let’s see if you can figure out how we just got our tile on the screen! Here is the signature of
VDP_setTileMapXY. Take a look at the parameters and try to figure out what we did:
void VDP_setTileMapXY(VDPPlan plan, u16 tile, u16 x, u16 y);
When you know the theory behind it it’s quite simple, but here’s a step-by-step explanation for reference!
VDPPlan: This is the background plane we want to draw our tile on. We picked
BG_B, but we could’ve also used
tile: This tells the function what tile to use, or in other words: This tells the function where in VRAM our desired tile is located. Since we’ve only loaded one tile, it’s at position
x: This is the x-coordinate (in tiles!) where we want to put our tile. We chose
2, which would be 16 in pixels.
y: This is the 25th letter of the alphabet, and also the y-coordinate of where we want to put our tile.
Phew! That was a lot to take in, but we got to put a tile on the screen so it was worth it. One final note though: Remember the
1 I told you to ignore in
VDP_loadTileSet(bgtile.tileset,1,DMA);? Well, this
1 actually told SGDK where to put the tile in VRAM. We could have loaded it onto position
9 or whatever, but then we’d also need to change the
tile parameter in
VDP_setTileMapXY. Also we’d have created a gap in the VRAM which you usually don’t want, as it’s confusing. It’s usually best to pile on the tiles one after the other.
As for the
DMA, we’ll take a look at that in another tutorial.
And that finally wraps it up for this part! We’re slowly getting somewhere. In the next installment we’ll play around with tiles some more and will also fix the color. Thanks for reading and until next time!
If you have any questions, comments or criticism, post them in the comments below or reach out to me on Twitter @ohsat_games! Special thanks to Stephane Dallongeville for creating SGDK and everyone in the SGDK Discord for their help and keeping the dream alive!
Download the source codeAll patrons on Patreon get the complete source code for this tutorial, as well as other perks such as early access! Become a Patron!
Just Want to Buy Me a Coffee?
Check out the rest of this tutorial series!
If you’ve popped over to the tutorial section recently you might have noticed that I’ve added my very first HaxeFlixel tutorial! It shows how to implement a simple, pixel-perfect 2D water shader which I used for Go! Go! PogoGirl. But a few of you might be wondering what a HaxeFlixel is. Well, it’s a 2D game framework that is as powerful as it is underrated! It runs on the (also underrated) Haxe language, is extremely well documented, open source, and has built-in functions for almost anything you’d need.
As I’m sure many of you will remember, the original Streets of Rage for the Mega Drive had multiple endings. The real canonical ending has you beat the crap out of Mr. X, thereby ending his reign of terror forever (yeah, right). However, if you confronted Mr. X with a buddy in tow, a new possible path unlocked. A quick refresher is in order. When you confront Mr. X he will ask you to join his organization.
A few years ago, Yuzo Koshiro posted a pile of old game design documents for Bare Knuckle 2 aka Streets of Rage 2 on the Ancient blog to commemorate the release of Streets of Rage 2 3D on the Nintendo 3DS. These documents gave a deep insight into the game’s inner workings, technical aspects, designs and even some cut content. They were an awesome resource for one of the most awesome games ever created.