Learn how to make a space shooter for the Sega Mega Drive using SGDK! I highly recommend working through the Megapong Tutorial first, as that explains a lot of the basics of MD coding.

Megalaga 1 - Space

Posted February 17, 2020

Welcome to another new project tutorial series on Mega Drive development! This time we’ll be creating a space shooter from scratch using SGDK, the Sega Genesis Development Kit. This is what the end result will look like:

images/final_megalaga.gif

It’s a very basic take on the genre. You have to shoot down the enemies at the top of screen and once they’re all destroyed, you’ve won the game. The enemies move left and right and you can only shoot 3 bullets at a time, so you have to get the timing down if you want to beat the game. This tutorial should serve as a good example on how to code one of the most classic of genres on Sega’s 16bit machine.

As usual, I highly recommend that beginners work through Megapong first, as that tutorial explains all the basics of Mega Drive development in more detail than this tutorial will.

And as a final note, this game will use assets created by Jonathan for his Game Creator’s Pack, so shoutout to him!

Making Space

Create a new project (feel free to use my template) and get your environment set up if you haven’t done so already.

Then, download the image file we’ll need for our tiles using the link below:

Download tile image

Unzip it and take a look. As you can see it’s 24x8 pixels big, meaning it will result in a total of 3 tiles at 8x8 pixels each. We’ll use these tiles to assemble a cool space background. Create a new folder called tiles inside the res folder of your project, then put the image in that folder. Then create a new file inside the root of the res folder and call it resources.res. Open it up and add the following line to it:

IMAGE  background  "tiles/space.bmp" FAST

This will import the image and store it under the name background. Now we’ll load the tiles in the code. First, include the resources in the project by adding the following line at the top of main.c:

#include <resources.h>

Then put the following two lines at the beginning of your main() function:

VDP_loadTileSet(background.tileset,1,DMA);
VDP_setPalette(PAL1, background.palette->data);

This will load the tiles of our background image into memory, starting at index 1. Since the image contained three tiles, we can now access them via the indexes 1, 2 and 3. After loading the tileset, we grab its palette data and save it into PAL1. This one image file actually contains all the colors we’ll need for this game. Usually it’s common to use a different palette for sprites, but since we’re making a very simple game we can be efficient. It’s a good habit to get into when developing on older hardware!

Now to put our tiles on screen. We could assemble the tiles by hand, but let’s make it more interesting (and easy) by generating a random space background each time the game is started. We’ll achieve this with a for loop that will randomly pick one of the three tiles, then place it on the screen. The first tile will get preference, as it’s just empty space and we don’t want the background in our game to be cluttered with too many stars. It would end up looking more like white noise than the vast emptiness of space.

So let’s do this. First of all, define these variables in main() so we can use them for our loop:

int i = 0;
int thex = 0;
int they = 0;
int val = 1;

Then create the loop:

for( i=0; i < 1280; i++){

}

As you can see, we’re looping up to a value of 1280. Why that number? We want to cover the whole screen with tiles, and the Mega Drive has a resolution of 40 x 32 tiles. Multiply that, and you get 1280!

We’ll want to place each tile individually, so we’ll need to know the x- and y-coordinates of where we want to put them. But since we’re simply looping through all the tiles from first to last, we’ll have to use a little trick to get those coordinates. Put this at the beginning of the loop:

thex = i % 40;
they = i / 40;

This snippet is good to keep in mind, as it’s really quite useful. It allows you to work with one-dimensional arrays while still using two coordinates.

Now that we have the desired position of the current tile, we’ll need to figure out which of the three possible tiles will be placed. SGDK has a random() function that can help us here, but it gives us a random value out of the entire possible range of integers…which is a bit much for our purposes. Generating random numbers within a range from 1 to 10 is enough for us. Luckily, math can help us do that!

val = (random() %  (10-1+1))+1;

The formula here is random() % (max - min + 1) + min. It’s another very useful code snippet, so write it down somewhere so you won’t have to keep getting it from Stackoverflow like I do.

We said we wanted to give the empty space tile preference, so that the background won’t be too cluttered. So we’ll say that if val is higher than 3, we just set it to 1. This will guarantee that the empty tile will come up a lot more than the two tiles with stars in them, since those are only placed when val equals 2 or 3 exactly.

if(val > 3) val = 1;

Okay, now we know what tile we’ll use and where we’ll put it. All that’s left is to…well, put it on screen! And since we’re placing a single tile, we’ll use the function VDP_setTileMapXY for that:

VDP_setTileMapXY(BG_B,TILE_ATTR_FULL(PAL1,0,0,0,val), thex, they );

We’re putting our tile on the background plane (BG_B) using PAL1 at position thex:they. Compile the game and take a look:

images/space.png

Space. It seems to go on and on forever…

Reset your emulator a couple of times to see that a new background is generated each time. Nifty, huh? If you want to change the amount of stars, simply change the line if(val > 3) val = 1. But personally I’m happy with this balance.

Now as a final flourish, let’s scroll the background to make things more dynamic. Before the main game loop (while(1){}), place the following two lines:

int offset = 0;
VDP_setScrollingMode(HSCROLL_PLANE,VSCROLL_PLANE);

The offset will keep track of how far the background has moved. And we want to just scroll the entire background plane, which is why we’re setting the vertical scrolling mode to VSCROLL_PLANE.

Now put the following line at the beginning of while(1) to actually make the background scroll:

VDP_setVerticalScroll(BG_B,offset -= 2);
if(offset >= 256) offset = 0;

This will scroll the background down by two pixels each frame. Once the background has moved an entire plane length (which equals 256 pixels), we’ll reset offset to 0 to prevent an overflow.

Now compile the game and witness the scrolling in action!

images/scrolling.gif

Pretty cool. Let’s just do one final thing before we wrap things up.

When you’re working with the VDP of the Mega Drive (in other words, when we use functions in SGDK starting with VDP_) it’s a good idea to disable system interrupts. It’s not too important to worry about the precise reasons for it now, let’s just say that it’s better to be safe than sorry. Luckily it really isn’t a big deal, simply wrap all your code dealing with the VDP in the following two function calls:

SYS_disableInts();
//Code that loads the tile, draws the background...
SYS_enableInts();

Not the most glamorous thing to end this post with, but it’s important. That’s it for this time, next time we’ll use structs to create entities in an efficient manner. I’ll see you then, be excellent to each other!

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 code

All 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!

  • Megalaga 1 - Space
  • Megalaga 2 - Entities
  • Megalaga 3 - Enemies
  • Megalaga 4 - Enemy Movement and Input
  • Megalaga 5 - Bullets
  • Megalaga 6 - Collision and HUD
  • Megalaga 7 - Enemy Bullets
  • Megalaga 8 - Spam Protection
  • Megalaga 9 - Sound
  • Megalaga BONUS - Powerup
  • Get Words in Your Inbox!

    Be oldschool and sign up for my newsletter to get updates! Just enter your email address, prove you're not part of Skynet and you're good to go!



    Powered by CleverReach. I will not send you spam or sell/give your email address to someone else.  You can of course unsubscribe at any time. By clicking the subscribe button above, you confirm that you have read and agreed to our privacy policy.

    By using the Disqus service you confirm that you have read and agreed to the privacy policy.

    comments powered by Disqus

    Related Posts

    HaxeFlixel Tutorials!

    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.
    Read More

    Streets of Was

    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.
    Read More

    Streets of Rage 2 Design Docs

    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.

    Read More