This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Multidirectional scrolling


by on (#77849)
In this post, Banshaku wrote:
And instead of talking about mappers we should focus on making simpler game with less hardware

And "lose [your] interest right away", as you put it :P

Quote:
so we can have some code base to work on more ambitious projects. I guess that was people in the past did indirectly anyway.

And that's what I continue to do, despite strong suggestions from someone to make something that scrolls already.

by on (#77854)
tepples wrote:
And that's what I continue to do, despite strong suggestions from someone to make something that scrolls already.

That would be me, right? =)

by on (#77861)
I found scrolling to be needed for the project I want to do, unfortunately.

by on (#77862)
Scrolling is easier than most people think, specially if it's just in one axis. Horizontal scrolling is particularly easy, due to the fact that nametables are 256 pixels wide.

by on (#77864)
Yeah scrolling one direction at a time is easy but scrolling both at the same time (free-directional scrolling) is a nightmare, I got weird bugs every time I tried to do that because the update logic for one axis would interfere with the logic of the other axis.

by on (#77865)
tokumaru wrote:
Scrolling is easier than most people think

Efficiently organizing data for scrolling, on the other hand, isn't necessarily trivial. Nor is creating several km worth of map data to be scrolled over.

by on (#77882)
tepples wrote:
And "lose [your] interest right away", as you put it :P


Making a game with less complicated hardware doesn't mean that it's a single screen game. And with a mmc1 like from retrousb you could make something similar to Ninja Gaiden.

I don't know how you got back that post and what was the purpose in the first place to digg it up. It doesn't bring much to what I said about "let focus on games instead of making a new mapper".

by on (#77886)
Bregalad wrote:
Yeah scrolling one direction at a time is easy but scrolling both at the same time (free-directional scrolling) is a nightmare, I got weird bugs every time I tried to do that because the update logic for one axis would interfere with the logic of the other axis.

I'm sure you would eventually get it right if you hadn't given up. I too have found weird bugs while trying to implement free scrolling, but once I stopped and planned everything beforehand I only needed minor tweaks to get it working.

tepples wrote:
Efficiently organizing data for scrolling, on the other hand, isn't necessarily trivial. Nor is creating several km worth of map data to be scrolled over.

Even simple puzzle games can benefit from rooms slightly larger than a single screen... No being able to see everything that's going on might even add to the fun. Not all levels must be several kilometers long.

by on (#77901)
I've gotten free scrolling to work fine. Should I write a tutorial?

by on (#77904)
I think free scrolling isn't that hard. I think it's combining it with compression (the "efficiently organizing" that tepples talks about) that's difficult, at least I feel like it would be.

by on (#77914)
3gengames wrote:
I think free scrolling isn't that hard. I think it's combining it with compression (the "efficiently organizing" that tepples talks about) that's difficult, at least I feel like it would be.

So you probably haven't written an 8-way scroller yourself, have you? :) It IS hard, there are so many chances to be "off by one" that you really have to be very careful when designing how you're going to go about it. I'm of course talking about "real" limitless scrolling with variable scrolling speeds, not the SMB3 way (vertical scroll is limited to 2 screen heights, it only needs to update columns) or the Gauntlet way (4-screen mirroring, screen limited to 512x480).

That said, if you are systematic about it's not too bad. But it is hard in my book as far as NESDev goes.

by on (#77918)
I haven't, but I've been thinking about it. [And sadly, came to the conclusion I'd probably just do it the SMB3 way to save the headach.] but I think I should rephrase. Doing it with compression and not using a ton of RAM would be hard. And to add to it, I also was thinking of a way to also update a 60 byte table to also keep track of walkable spaces. That seemed easy, but yet it uses 60 bytes of RAM. I'm not sure if anyone else has better methods, but with low CPU costs. Does anyone use a RAM table for collision on the background so you don't have to read the PPU?

by on (#77926)
3gengames wrote:
Doing it with compression and not using a ton of RAM would be hard.

Map decompression and nametable updates should, in theory, be 2 different systems. Anyway, if you use fixed-size compression (i.e. not RLE, LZ and the like), decoding it in real time isn't so hard.

Quote:
I'm not sure if anyone else has better methods, but with low CPU costs. Does anyone use a RAM table for collision on the background so you don't have to read the PPU?

I doubt anyone reads the PPU for collision. If they do, they certainly shouldn't. VBlank time is already too short if you're only writing to VRAM, imagine if you also had to read it in order to make game decisions...

I'm not sure if RAM tables are the best option either, because they wouldn't work well with slopes and blocks more complex than solid/empty unless they used much more than 60 bytes of RAM.

For collision decisions I just read directly from the level map. Once I have a metatile's index I have access to all of its collision information.

Now I really really think it's time for a split!

by on (#77927)
What always bugged me is that the vertical scroll and horizontal scroll routines would work fine on their own, but they would randomly interfere eachother when working at the same time.

Doing 4-way scrolling like Final Fantasy or Dragon Warrior is easy for example, as the horizontal scrolling can assume the vertical scrolling is at an integer number of metatile and vice-versa.

When you want true free-directional scrolling, the problem is that if the scrolling of the "other direction" (that is, vertical axis for the horizontal scrolling routine and vice-versa) might not be an integer number of metatiles so you don't know how you are supposed to do your updates, because it depends on what the "other" routine is doing at the moment. (I hope my english wording of the problem makes sense).

I've tried this with both metatile based maps, and maps directly stored as spearate NES screens (raw name and attribute tables) and I encountered a similar problem on both attemps.

I'm pretty sure there is a fix available but it would probably mean use a more complex algorithm where there is a signle routine doing the scroll into all directions instead of two horizontal and vertical scrolling routines called one after eachother.

There is no reason to implement compression first, you need to make it work with uncompressed maps, then adding comperssion is as simple as replace all data load from map (which should be something like a lda [Map],Y) by a subroutine that will load data from the compressed map (for this reason it's important that the compession data is randomly acessible, pseudo-randomly acessible, or that the map is entierely decompressed in RAM).

I finally lost interest in this when I figured that all NES project I'll do in the near future would anyways scroll only one direction at a time.

by on (#77935)
Dwedit wrote:
I've gotten free scrolling to work fine. Should I write a tutorial?


Yes please.

by on (#77939)
Oh I forget to mention it but I'd be interested in the tutorial too.

I can also share with my failed attempts sources if anyone is interested.

by on (#77943)
In my honest opinion, the ONLY thing that complicates free scrolling is the fact that there are only 2 nametables. Once you decide how to handle that (there are 3 options: use 4-screen mirroring; hide the scrolling artifacts using various tricks; concentrate the artifacts in locations less likely to be noticed), it gets really simple.

I always hide the scrolling artifacts, either by masking the top 16 scanlines or the leftmost and rightmost 8 columns. Once that's decided, you know where the seams will go ("under" the masked area).

by on (#77944)
tokumaru wrote:
Quote:
I'm not sure if anyone else has better methods, but with low CPU costs. Does anyone use a RAM table for collision on the background so you don't have to read the PPU?

I doubt anyone reads the PPU for collision. If they do, they certainly shouldn't. VBlank time is already too short if you're only writing to VRAM, imagine if you also had to read it in order to make game decisions...

I'm not sure if RAM tables are the best option either, because they wouldn't work well with slopes and blocks more complex than solid/empty unless they used much more than 60 bytes of RAM.

For collision decisions I just read directly from the level map. Once I have a metatile's index I have access to all of its collision information.

Now I really really think it's time for a split!


Mario Bros does read the PPU for collision. I discovered this in early emulator development as I ran the game before adding the ability for $2007 reads to actually return information.

RAM tables were used in some commercial games. Ninja Gaiden is one of them.

by on (#77946)
Super Mario Bros. uses a 32x13-metatile (two screen) sliding window in RAM for its collision map. Anything with a destructible playfield (collected coins, broken blocks, etc.) will need to use some sort of collision map in RAM, and that's why SMB1 doesn't have backtracking: so that it can expire columns of the collision map.

Backtracking, destructibility, no PRG RAM: pick two. Or restrict the level geometry slightly and pick one and two halves.

by on (#77948)
On that thought, has anyone ever explored expanding the built in ram to fill the entire 8k of space it responds to? Not just explored it hardware wise but also tried implementing it in an emulator and seeing if it breaks any existing games that might rely on mirroring. It seems like that might be relatively easy to do and it would give you a nice boost in memory.

by on (#77949)
http://www.youtube.com/watch?v=v5fXMly_ ... ideo_title

i tried to do this a few years ago for megaman 3 (my rom hack)...and it was turning out pretty good as you can see, but i could never ever figure out how to deal with enemies ex-cluding megaman. :( notice at the end of the video how the spiky thing wraps around to both the top and bottom of the screens.

It was just too hard and i gave up and quit. :(

by on (#77950)
Hacking a game to include multi-directional scrolling is certainly harder than programming it from scratch, because you're messing with a finalized architecture.

by on (#77951)
tokumaru wrote:
In my honest opinion, the ONLY thing that complicates free scrolling is the fact that there are only 2 nametables. Once you decide how to handle that (there are 3 options: use 4-screen mirroring; hide the scrolling artifacts using various tricks; concentrate the artifacts in locations less likely to be noticed), it gets really simple.


I'm pretty sure this wasn't my problem. I made a system so I adress all metatile by a (row, column) system, and it gets converted to a VRAM adress with a loockup table. (Up to 32 columns and 15 rows are supported for vertical mirroring). I made a system that delays the row updates when scrolling vertically so it hides them in the overscan area, but you're right that this might the problem : The horizontal scrolling routine "ignores" this delays and assume the data here is already updated. If the user change his mind for example when scrolling down, and scrolls up again, the vertical scrolling routine will "cancel" the delayed update, but the horizontal scrolling routine will ignore that and still act as if the bottom row was updated. I'm not sure if this was my problem, but it was something in the like.

I use $2007 reads for attribute tables in my (other) game project, so that I can modify only the top or bottom half of the 32x32 block by RMW operations.
For my (non-working) scrolling attempt I used a completely different system where it mirrors attribute tables in RAM, and again the table would only be adressed by (row, column) pointer and would be converted by a loockup table.

by on (#77955)
If you can expand the 60 byte RAM table, you could add slopes. One bit for solidity and two for 4 possible slope types. But I don't think I'll be dealing with slopes soon so it's probably a idea I'd personally like to explore and mess with.

by on (#77965)
I just made an 8-way scrolling engine that uses vertical mirroring so it's limited to two screens wide with many screens vertically. Right now it can decode tile chunks that are written to the row buffer every 8-pixels, followed by copying the buffer to the nametable. The tile chunks only store flat surfaces and slopes where the objects will stand; it still needs a way to fill the space between the ground. It will also support limited brick smashing.

It also keeps a 128-byte copy of both attribute tables, which I'm not crazy about but it's the easiest way to overwrite only the palette that must be changed while keeping the other palettes in the same byte. Reading back the attributes in vram will eat up more vblank time that can't be wasted, since I've got some ambitious split screen ideas in the works.

With extra prg-ram, I don't see why free scrolling can't be done in vertical mirroring without artifacts (on ntsc) unless you need a status bar (So I can see why Mario 3 and Kirby stuck with horizontal mirroring and ate the artifacts).

by on (#77982)
tepples wrote:
Backtracking, destructibility, no PRG RAM: pick two.


I still think this is a really defeatist mantra. There are all sorts of ways to achieve all three.

"Backtracking" in the sense that you're using it must be clarified that you imply "backtracking throughout the entire level." It's quite easy to design levels to have large vertical dropoffs partway through, or other various methods of one-way doors.

You also have to clarify that by "destructibility" you mean "wholly persistent destructibility throughout the entire level." Would people accept blocks respawning 5 screens behind them? Why would that be a problem? In Zelda dungeons the enemies stay dead for only a few screens, then the old rooms repopulate. In a large number of games, enemies respawn off screen constantly. Why not then do the same for destructible blocks?

If your game is focused on blocks and their destructibility, it also shouldn't be a problem. You won't need the RAM for other objects and enemies and can devote all of it to saving a level's worth of destruction. Naturally you design the levels around the amount of destruction that could reasonably be saved.

Is it completely impossible to do any compressing/decompressing on the fly as the player moves around? This ought to be especially easy in "screen flipping" games like Battle Kid where a pause is expected at every room edge, but obviously this topic is for 8 way scrolling. I still think it should be possible, though.

Essentially, the statement should be "pick two unless you don't mind a slight headache, and who in NES development would?"

by on (#77983)
strat wrote:
With extra prg-ram, I don't see why free scrolling can't be done in vertical mirroring without artifacts (on ntsc)

I have been able to see glitches at the top and bottom of the screen using several TVs and NTSC consoles. I simply don't believe the common notion that the glitched scanlines are conveniently cropped in NTSC.

Also, PRG-RAM shouldn't have anything to do with the actual scrolling, like I said before. PRG-RAM simply makes fetching the tiles easier, but you can still fetch them in many other ways, even directly from ROM.

UncleSporky wrote:
Essentially, the statement should be "pick two unless you don't mind a slight headache, and who in NES development would?"

I agree with everything you said!

by on (#77988)
UncleSporky wrote:
defeatist

You appear to have misunderstood what I meant by "one and two halves". I meant one, half of a second, and half of a third. Restrict backtracking partially and restrict destructibility partially, and things can be made to fit. Please allow me to elaborate:

UncleSporky wrote:
It's quite easy to design levels to have large vertical dropoffs partway through

Hence "restrict the level geometry slightly and pick one and two halves." If you're going to have an obvious gravity barrier every four screens to purge the persistence of destroyed game objects, then a limit on backtracking is obviously one of the "two halves".

UncleSporky wrote:
You also have to clarify that by "destructibility" you mean "wholly persistent destructibility throughout the entire level."

Which brings me to restricting level geometry. Assume that the portion of a 2-way scrolling map through which destruction persists is 32 screens long, or 512 columns of 16-pixel-wide metatiles. If only one thing in each column is allowed to be persistently destroyed, the destruction buffer takes 64 bytes.

UncleSporky wrote:
Would people accept blocks respawning 5 screens behind them? Why would that be a problem?

In some games, players are supposed to backtrack and "farm" for a resource by killing enemies. In Mega Man, it's energy. In Zelda, it's cash. In a DW/FF style role-playing game, it's experience.

But in other games, farming is not expected. Is Mario supposed to hit a block, get the mushroom, go five screens away, come back, hit the same block, and get a fire flower? Or run back and collect the same coins over and over?

And then there's the other kind of farming, Harvest Moon/Animal Crossing style. If you have a huge plot of land, and you can plant things in each grid cell, the game needs to save what crop is planted in each cell and how long until it's mature.

UncleSporky wrote:
In a large number of games, enemies respawn off screen constantly.

And players got frustrated with it when they would defeat an enemy to clear the path, walk offscreen to get a running start to make the jump, and then the enemy would respawn, again blocking the path, and knock the player back into a bottomless pit. See the list of most annoying examples at "Knockback" on TV Tropes.

UncleSporky wrote:
Is it completely impossible to do any compressing/decompressing on the fly as the player moves around?

It's possible. Games like Sonic the Hedgehog, Blaster Master, and tokumaru's pet project use multiple layers of metatiles to accomplish this.

by on (#77992)
Enemies are just objects in most cases. Just keep track of all objects that have been killed in a 2 screen area of the screen you're on. And then also have separate objects that never ever get cleared, coins and blocks and such. That way you can have objects that respawn and objects that don't.

by on (#77993)
3gengames wrote:
Enemies are just objects in most cases. Just keep track of all objects that have been killed in a 2 screen area of the screen you're on. And then also have separate objects that never ever get cleared, coins and blocks and such.

Which breaks for cases such as 1-2 from SMB1. See previous discussion about persistent destruction.

by on (#77995)
Well background objects could be represented by a 2-bit "state" system of some sort. Although in a free-scrolling engine that'd get more huge with the memory needed. But oh well.