Learn how to make an endless runner 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.

Megarunner 1 - The Framework

Posted November 4, 2019

Welcome to a new tutorial series on Mega Drive development! Here we’ll be creating a Mega Drive game from scratch using SGDK, the Sega Genesis Development Kit. And this is what we’ll be working on:


I call it Megarunner. It’s an endless runner-type game where you jump over obstacles to gain points. The game ends when you hit one of the obstacles. It’s a simple concept and thus a good way to learn about some new concepts of Mega Drive programming like scrolling and animation!

It is highly recommended that you check out the tutorial for Megapong first, as that tutorial leads you through setting up a development environment and teaches you the basics of Mega Drive programming. Concepts and ideas already explained in Megapong won’t be repeated in as much detail here, so it’s a good idea to learn the basics first.

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

And with all that out of the way, let’s get coding!

Setting up a project

First we’ll create a project and set up the general framework along with some functions that we’ll use throughout. This tutorial already expects you to have SGDK installed and a development environment up and running, so if you haven’t, work through the Megapong tutorial first! I feel like I’m saying that a lot.

Create a new project, either by cloning/downloading my template or by using your own that you might have created (with a .vscode folder already in it). Call it “megarunner”. Or whatever you want, really. Then open the project in your IDE (ideally VSCode).

Now let’s add stuff to main.c! First, at the very top, include the string header:

#include <string.h>

We’ll need it for some string manipulations later. Now below that we’re gonna add some variables. I’d recommend labelling this code block using a comment, so that you won’t end up with a pile of random variables at the end of the project.

/*General stuff*/
const char msg_start[22] = "Press START to Begin!";
const char msg_reset[22] = "Press START to Reset!";
bool game_on = FALSE;

The two message constants will store the strings we’ll display before and after the game. game_on will track whether the game is currently running or not. Note that C doesn’t actually have a bool type, but SGDK defines one for us to make things easier (with TRUE == 1 and FALSE == 0 respectively).

Next, let’s define two small helper functions. The first will display a line of text in the center of the screen, while the second will delete that line. We’ll use them to display (and delete) the strings we’ve just defined.

void showText(char s[]){
	VDP_drawText(s, 20 - strlen(s)/2 ,10);

void clearText(){

A quick reminder here that the text functions in SGDK use tiles as their unit of measurement, not pixels. So VDP_clearText(0,10,32) will delete a total of 32 characters (= tiles) in the 10th tile row from the very left of the screen.

Now we have an easy way to display and delete text without having to fiddle with the positioning every time. Next, we’ll define startGame() and endGame(), two functions that will handle the beginning and end of our game.

void startGame(){
	if(game_on == FALSE){
		game_on = TRUE;

void endGame(){
	if(game_on == TRUE){
		game_on = FALSE;

As you can see, these functions toggle the game_on variable, while endGame() also displays our game over message using the function we just created. Told you it would be useful!

Alright, one more thing before we get to the main part of our game: We’ll have to create a callback function that will process our joypad input. We’ll only be using one joypad and two buttons, START and C. So add the following function:

void myJoyHandler( u16 joy, u16 changed, u16 state)
	if (joy == JOY_1)
		/*Start game if START is pressed*/
		if (state & BUTTON_START)
			if(game_on == FALSE){
		if (state & BUTTON_C)

As you can see we’re already adding a bit of functionality: If the player presses start, startGame() is called, which makes sense if you think about it. We’ll find out what the C-button does later on.

Alright, now we’ll close things off with the main event in the form of main(). This of course is the function that will be called on start and contains all our actual game code. For now we’ll just define the basic stuff, so it’s not much to look at.

int main()
	JOY_setEventHandler( &myJoyHandler );


		if(game_on == TRUE){


	return 0;

This is all pretty much boilerplate stuff. We initialize the joypad and tell SGDK to use myJoyHandler as our callback function. Then we display our msg_start message using that handy showText function again. Finally we begin the main game loop with while(1). We’ll have a section with things that should only happen when game_on is TRUE, but SYS_doVBlankProcess(); always needs to be called every frame.

Phew, that was quite a lot of code, but it’ll give us a good foundation to make our game. If you compile now you should see our string Press START to Begin! on screen and if you press Start on your controller it should go away. So far so good!

Stay tuned for the next installment where we’ll put some tiles on screen using a nifty new function. Thanks for reading and stay excellent!

If you've got problems or questions, join the official SGDK Discord! It's full of people a lot smarter and skilled than me. Of course you're also welcome to just hang out and have fun!

Download the Project Files!

All patrons on Patreon get the complete source code for this tutorial, as well as other perks such as early access! And Patreon support also ensures that I can keep working on tutorials like this one. Become a Patron!
Just Want to Buy Me a Coffee?

Check out the rest of this tutorial series!

  • Megarunner 1 - The Framework
  • Megarunner 2 - Tiles
  • Megarunner 3 - Scrolling
  • Megarunner 4 - Player and Obstacles
  • Megarunner 5 - Jumping Math
  • Megarunner 6 - Collision and Score
  • Megarunner BONUS - Tile Scrolling
  • 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