Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Diagonal Scrolling

A topic by Juxxec created Sep 27, 2022 Views: 285 Replies: 4
Viewing posts 1 to 3
(5 edits)

Greetings All,

I am so sorry that I am posting here. The devkitPro forum is dead. I tried posting there multiple times, only to find out my messages have to be approved by a moderator, which never happens …

So here is my situation. I am using devkitPro to develop an in-house engine for my game. I am going to release the game and engine as open source.

In my game, I want to be able to scroll the screen in all directions: horizontal, vertical, diagonal.

The game is using a screen size of 32x32 tiles. My maps, however, are way larger than that. Even the 64x64 tiles size that the GBA supports is not enough for my maps.

I followed an example from devkitPro’s examples that scrolls a text message horizontally.

The way the example works is, the screen is scrolled to the right and the scroll offset is stored in a variable. When the offset reaches 7 pixels, the offset is set to 0. Then the whole 32x32 screen gets filled with the tiles from the map, just 1 tile to the left.

Here is the code which I modified slightly to fit my needs:

https://pastebin.com/Wtd6p8gY

Scrolling the screen this way does work, but it is inefficient and there is quite a bit of screen tear. A video of this approach is shown below:

I discovered that the GBA wraps the screen around, when the scroll offset goes outside of the screen width. This way, tiles that are on the left side of the screen (that are outside of the screen) are drawn at the right side of the screen (in view).

THis is illustrated by the diagram below:

As you can see, the Red rectangle is the scroll position of the “GBA Window”, the black rectangle is VRAM (32x32 tiles) and the purple is the vertical strip of tiles that gets drawn on the right side (is wrapped around).

By doing scrolling this way, only a single vertical strip needs to be updated at a time to achieve the effect. This gives us a giant speed boost.

The code for this is here: https://pastebin.com/NQzLFvWV

Here is a video that illustrates this approach:

This approach, however, has a drawback. It cannot be used for diagonal scrolling. The vertical strip that gets wrapped around for horizontal scrolling overlaps with the horizontal strip that would be used vertical scrolling. This creates weird artifacts, which can be seen in the following video:

Can somebody give me a hand with this? :(

Host

Hiya,

 I don't understand how that code works, updateBGColumn uses a variable y but it's never defined or populated. Not sure if you posted the whole thing or I'm missing something.

 However,  I can show you my scrolling map code if it helps. It's a bit more complicated than yours, but allows for some configuration

https://github.com/pmprog/dronedelivery.proto/blob/main/engine/mapex.h
https://github.com/pmprog/dronedelivery.proto/blob/main/engine/mapex.c

Basically, on mapex_setviewport it will completely redraw the screen at a desired location, but it takes time, so using mapex_scrollviewport to move it runs quicker (unless the distance for the scroll is too far, in which case the viewport will be completely redrawn). The scroll then just maintains the tiles that are offscreen, populating them with what's next to come.

I'm sure there's probably better ways of doing large maps than I've done here, but it works well enough for me.

PS. If you do build the project and try it out, the fact the camera is jerky as you move is not to do with the scrolling code, rather just the camera controller, which I never got around to fixing.

(1 edit)

Thank you very much. In the end I did not use your code, but I will definetely keep it around. I like how you handle the jump scroll (where you scroll to a random position and you need to fill the entire screen then).

My original code was just a sample. I did not post it all, cause there is a lot of bloat. I tried to copy the important parts. The vertical scroll code was identical to the horizontal scroll, so I skipped it. I did include the functions I believe, I was just not calling them.

Jam Host (2 edits)

It sounds like you're on the right track, taking advantage of the GBA's wrapping BGs to avoid having to shift the whole tilemap. The bigmap example from tonc-code.zip (edit: updated repo at libtonc-examples) has a working implementation of large scrolling tilemaps which you may find useful. There's also an annotated version of the same code which is much more readable.

I think you may just have an oversight with your vertical scrolling (it needs to start from the X offset of the horizontal scroll, after horizontal scrolling has been done?), because I'm doing similar in my game and it works fine, can scroll diagonally with no problem. Here's my code in case that's helpful, but it's not C. This is a bit of a tangent but it's based on the approach described in the GBA Resource Management article, which uses reference counting to dynamically unload tile gfx that are not in use (may be overkill for smaller games?), but other than that the basic approach of looping over rows & columns to copy in new sections of map data is the same.

Anyways, hope some of this helps, please shout if you're still running into issues!

(1 edit)

Thank you very much. By using this example, I was able to fix my own code.