Page(/tutorials) Megarunner 3 - Scrolling

Megarunner 3 - Scrolling

Posted November 18, 2019

Hey! Request a tutorial!

Join my Patreon until September 30th,
suggest a tutorial topic, and I'll do it!

(If I can, but we'll figure something out)

Welcome back! Last time we drew a background with a floor and even some street lights. This time we’ll get things moving by scrolling the background to create the illusion of endless running!


As usual, we have to do a bit of preparation work. First off we’ll define a new constant at the top of the file that will store the speed at which our background will scroll.

const int scrollspeed = 2;

Next up we’ll set our desired scrolling mode. In main(), add this line after VDP_setPlanSize(32,32);:


What does this actually do? First of all, note that we’re giving the function two values: The first one sets the desired mode for horizontal scrolling (HSCROLL) the second one for vertical scrolling (VSCROLL). But what is a mode? SGDK (and the Mega Drive hardware) supports multiple ways of scrolling. The values that we have chosen (with _PLANE) tell SGDK that we want to scroll the entire plane at once. You could also scroll tiles or lines, which are slightly more advanced modes that allow you to create parallax effects and such. But we simply want to scroll the entire plane for now.

One more thing before we get to the actual scrolling. We will need a variable that stores the scrolling offset, which I’ll explain in a second. Define this variable right before your main game loop starts:

int offset = 0;
    //game loop stuff

Keep Scrollin' Scrollin' Scrollin' Scrollin'

Alright, let’s get scrolling! As you might expect, SGDK offers us a function that will handle the scrolling. Put this one right at the beginning of your game loop:

VDP_setHorizontalScroll(BG_B, offset -= scrollspeed);

The first argument tells the function which plane we want to scroll. Since we put our tiles on background plane BG_B, that’s of course the one we want. The second argument passes in the offset that we want. This basically tells SGDK how far we want our plane to be moved: In our case, we want to move it by scrollspeed. But why are we keeping track of offset?

It might seem obvious to some and confusing to others, depending on what game engines you’ve worked with in the past. In some cases you tell the engine “I want the background to constantly scroll at speed X” and then it just happens. In SGDK this works differently! We are not passing in the desired speed at which we want the plane to scroll, but the actual distance we want it to move each frame. This means that we have to keep track of how far the plane has already scrolled, so that we can adapt that value for the next frame.

In the first frame, we have offset == 0. Our call to VDP_setHorizontalScroll subtracts scrollspeed from that, which results in offset == -2. This offset is then applied to the plane, meaning that it will be moved two pixels to the left. In the next frame, offset is reduced again to offset == -4, meaning the plane is now rendered another 2 pixels to the left (and 4 pixels left from where it originally was). So basically we have to tell SGDK every frame where our plane is currently located.

And one last thing: On the Mega Drive, planes loop automatically. Simply put, this means that any pixels that leave the left edge of the plane are automatically rendered on the right edge. This means that our background will never really move outside of the screen.

I hope that wasn’t too confusing.


“But wait!” I hear you cry. “Wouldn’t that mean that offset will keep decreasing forever”? Yes it does! And this is bad, because that would eventually cause an underflow and mess everything up. True, the game would have to go on for quite a while before we’ve reached the limit of what an int can take, but it’s better to be safe than sorry. So right after VDP_setHorizontalScroll(BG_B, offset -= scrollspeed); add the following line:

if(offset <= -256) offset = 0;

This resets offset so that it doesn’t become too small. Wonder why I picked 256? Well…try to figure it out yourself for a minute! Remember that plane size…?

Okay, I’ll tell you the answer. We set our plane size to be 32 tiles wide. One tile is 8px x 8px, meaning that our plane is 32 * 8 = 256 pixels wide. So if the plane has moved 256 pixels to the left (that is, when offset == -256), it will have moved one entire plane-length – and since it loops, it will basically be right back to where it started. So by resetting offset when it hits 256 we get smooth scrolling without any skips! (And just for fun, feel free to try out other values and see what happens).

That was a lot of theory, but if you compile the game now you should see that we have a scrolling background! Just look at it go. Feel free to make racing car noises! Neeeeoooown…


And here’s a question!

As you might remember we’ve only placed one streetlight in our scene…but now, sometimes there are two on screen at the same time! Do you know why? Think about it and post your answer in the comments below!

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!

Become an excellent patron on Patreon and grab the complete source code for this tutorial, as well as other bodacious perks such as early access!

You will also be added to the Wall of Excellent People!

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
  • By using the Disqus service you confirm that you have read and agreed to the privacy policy.

    comments powered by Disqus