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

Setting up vertical parallax

Setting up vertical parallax
by on (#39711)
I'm currently designing a vertically scrolling level where the player infiltrates a mountain base. The player starts at the bottom of the mountain, then works his way to the summit.

Some of the sections will take place indoors, that is, inside the mountain. The base will contain elevators that allow personnel to get around easily, but due to restricted access, the player will be forced to step outside occasionally and climb the mountain exterior to proceed.

To indicate the passage of time, the palette will change each time the player steps back outside for the next rock climbing segment:

Image

But getting to the point: Notice the mountain range in the background? I'd like to scroll that bad boy at a slower speed than the platforms in the foreground. It'll be a challenge but I'm pretty sure it can be done.

In order to do so, I'll probably have to switch over to CHR-RAM instead of the CHR-ROM I'm currently using. Since I'm still new to NES programming, I'm not really sure how to do that. Do I just specify a different iNES header? Also, as far as modifying CHR-RAM goes, is it simply a matter of writing to the Pattern Tables?

EDIT: Updated the mountain range in the background so that it repeats every 16 pixels.

by on (#39712)
Sounds like quite a task. CHR-RAM games (battletoads and micromachines coming to mind) had a parralax effect where tiles that weren't in the foreground all shared a common tile (or was a 16x16 layout?) that was rewritten depending on the scroll of the foreground, but nothing on the scale of this. You want to move that entire 'layer' at it's own scroll?

I think setting CHR-RAM is just setting CHR-ROM quantity in the iNES header to zero. then you just write in $0000-$1FFF to set your tiles.

by on (#39716)
Yes, this would be quite the complicated task. Actually, Batman ROTJ comes to mind, because they had parallax with the clouds in level 1 doing things like this without manipulating the scroll. What you're doing would be a little more complicated.

What I'd suggest doing is making the mountain tops as tessellated as possible, so you want have to do so much writing to CHR RAM. I'd take the mountain top "blocks" and place them side by side to make the tops of the mountains. But when scrolling horizontally I'd shift the pixels in this block left or right so that what's on one end shifts to the other end. Then these blocks that are side by side will effectively appear to scroll.

Are you also scrolling vertically? This would make things more complicated, I admit. Your main concern would probably finding the time to do such updates during gameplay.

by on (#39719)
SecretServiceDude wrote:
But getting to the point: Notice the mountain range in the background? I'd like to scroll that bad boy at a slower speed than the platforms in the foreground. It'll be a challenge but I'm pretty sure it can be done.

Yes it can be done, but that's one of the toughest things to do on the NES. Specially considering that your mountains are randomly distributed across the horizon (i.e. there isn't a short repeating pattern).

Quote:
In order to do so, I'll probably have to switch over to CHR-RAM instead of the CHR-ROM I'm currently using.

At first you may think so, but if you consider the amount of tiles you have to change, you'll realize that there is just not enough time to do this with CHR-RAM.

Even if you used only 16 tiles for the mountains (which I doubt), we're talking about updating 256 bytes of pattern table data. With the fastest possible code, which is an unrolled chain of LDAs & STAs (which would need 1536 bytes of ROM), each byte would take 8 cycles to copy, so 2048 cycles for all 256 bytes. That's nearly all of VBlank (there isn't even enough time for a sprite DMA).

And that's considering you have the data buffered somewhere in RAM before VBlank starts, because if we were talking about reading-modifying-writing CHR-RAM it would take a lot more time!

Quote:
Do I just specify a different iNES header?

As smkd said, setting the number of CHR-ROM pages to 0 should work, but some emulators refuse to see that as a valid board (as Nintendo never made a variation of NROM that used CHR-RAM), so you'd better pick an existing board such as UNROM, that has 128KB of PRG-ROM, but then you have to start worrying about PRG-ROM banks.

Anyway, I firmly believe that the answer to you problem is not CHR-RAM. All games I can think of that used parallax effects like this used CHR-ROM, probably for the reasons I explained above.

I advise you to keep using CHR-ROM, and do one of the following:

1.Keep all 8 possible rotations of the mountain tiles somewhere in your pattern tables and use an optimized loop to rewrite the portions of the name tables that contain mountains. This is a big waste of CHR-ROM space, but you don't need CHR bankswitching.

2.Have 8 different CHR-ROM banks each with a rotation of the mountain tiles, and select the appropriate one for each frame. It will only be necessary to update the name tables when the mountains complete 8 pixels of movement.

If you had a small pattern that repeated across the screen (something between 16 and 32 pixels wide), you could get away with bankswitching only, no need to update the name tables. Many NES games did this.

Quote:
Also, as far as modifying CHR-RAM goes, is it simply a matter of writing to the Pattern Tables?

Yes, exactly like you write to the name tables. But like I said, it is impossible to update a large number of tiles at once, considering that you also have to update palettes, sprites and name tables.

I just remembered a game that uses CHR-RAM and has parallax effects: Bee52. Check it out, maybe you'll get some ideas from it. Now that I remembered about it, it seems like it only updates one plane of the CHR data, since the clouds use a single color. It just happens that your mountains also use only one color, so you could in fact reduce the time taken to update the tiles by half, and things start to seem possible. How many tiles do your mountain use?

EDIT: I just checked Bee52 and it uses 12 tiles for the clouds. The pattern is shifted to make them move, and whenever 8 pixels of movement are completed the name tables are updated. I guess you might achieve what you want with CHR-RAM if you reduce the visual complexity of the mountains.

by on (#39720)
@tokumaru: Thank you for your wonderfully thorough response. You brought up some very important considerations. I may have to make some concessions here and there, but hearing everyone talk about how hard the effect is to pull off, I'm now obligated to do it. :)

As for the randomness of the mountains, please disregard that. The image I posted is just a quick illustration of the concept. I'll definitely reduce the mountains to a repeating pattern of 32 pixels if not 16 pixels. Or if the mountains prove to be too troublesome, I may remove them entirely and just try to get a parallax skyline gradient.

This particular level only scrolls vertically, so that should simplify things considerably.

by on (#39722)
Well, if it only scrolled horizontally, I'd say replace the dithering pattern in the BG by simple horizontal lines, and made the mountains only use a 16x16 pattern, that can be scrolled independantly by CHRROM or CHRRAM.

If it scrolls vertically (even only vertically) it's a whole lot harder. Unless you can make all foreground blocks sprites and the mountains in BG or something like that.
It could probably be done by using 8 CHRROM banks, each almost the same but with the mountains scrolled to a different offset, and quickly overwrite the nametable when the scrolling changes away of 8-pixels bounariy.
CHRROM would really make this feasible, for CHRRAM you'd probably have way too much stuff to updata and it would be desesperate..

by on (#39723)
tokumaru wrote:
I just checked Bee52 and it uses 12 tiles for the clouds. The pattern is shifted to make them move, and whenever 8 pixels of movement are completed the name tables are updated. I guess you might achieve what you want with CHR-RAM if you reduce the visual complexity of the mountains.

Sweeeeeet. This is so going down.

by on (#39724)
While we're at it, look at Sword Master and Metal Storm for some CHR-ROM parallax examples. I believe both use small repeating patterns in order to not need name table updates.

It's really fun looking at Metal Storm's pattern tables while playing, because it seems that all parallax effects share the same CHR-ROM banks, so you can see them all animating at once, very interesting.

Oh, I just remembered of another thing to consider about parallax effects: You have to shift the graphics in the opposite direction that they appear to be moving, because you are in fact trying to cancel out some of the movement that pushed the foreground in that direction. This is not some big discovery or anything, but I still though I'd mention it, because it's interesting enough that to make something look like it's moving to the left you have to actually shift the graphics to the right.

by on (#39726)
tokumaru wrote:
I just checked Bee52 and it uses 12 tiles for the clouds. The pattern is shifted to make them move, and whenever 8 pixels of movement are completed the name tables are updated. I guess you might achieve what you want with CHR-RAM if you reduce the visual complexity of the mountains.

This is a really great idea. I went ahead and simplified the visual complexity of the mountains to have a fighting chance.

Image

Every time the background scrolls 1-7 pixels relative to the foreground, it would only be necessary to update a handful of tiles in CHR-RAM. Provided I update those tiles during scanlines that don't coincide with the skyline/mountains, I wouldn't even need to wait for VBlank, right?

Every 8 pixels, I would update a subset of the name table, just like tokumaru said. Looking at the image above, that particular configuration would require an update of 80 name table entries; however, with some clever arrangement of the platforms, I could reduce that number by ensuring that only relatively small stretches of the skyline/mountains are exposed at any given time. Additionally, I could redraw the skyline gradient so that it's only 1 tile tall instead of 2, which would eliminate an entire row's worth of name table updates.

by on (#39728)
You really wouldn't need to rewrite the nametables at all.

by on (#39729)
yeah all you have to do is shift the tile data in the direction of scroll (with wrapping edges ofcourse) because after 16 pixels of shifting with that screen you are back to where you started with no need to update nametables. at minimum, it'll just be 32 bytes additional uploading if you just stick to the two 8x8 unique tiles of the mountain.

Quote:
Provided I update those tiles during scanlines that don't coincide with the skyline/mountains, I wouldn't even need to wait for VBlank, right?


vram is off limits during display unless you disable both BG/sprite display during the frame.

by on (#39730)
tepples wrote:
You really wouldn't need to rewrite the nametables at all.

Thanks, that's an excellent point.


smkd wrote:
vram is off limits during display unless you disable both BG/sprite display during the frame.

Shucks. Oh well, provided I update only a small handful of tiles during VBlank, hopefully that won't be a problem.

by on (#39731)
Once you get into this kind of stuff, you need insanely optimized code for vblank.
For all the optimization Battletoads did, it still managed to hit the "waste a cycle" feature for the LDY (nnnn+X) instruction because the address+X crosses a 256 byte boundary. If you are using a LD? (nnnn+?) \ STA 2007 sequence, try to avoid crossing pages.

Or just take the easy way out and use CHR-ROM, and reserve some tiles on a bunch of pages to be there just for the small number of parallax-scrolled tiles. The rest of the graphics on a VROM page may be completely unrelated.

by on (#39733)
Dwedit wrote:
Or just take the easy way out and use CHR-ROM, and reserve some tiles on a bunch of pages to be there just for the small number of parallax-scrolled tiles. The rest of the graphics on a VROM page may be completely unrelated.

That would require a donor cart with MMC3 or another mapper that switches CHR pages smaller than 4 KiB. The 7400 and CPLD mappers on RetroZone boards can't handle it.

If you're not scrolling up and down, you can squeeze out more VRAM update time by turning off rendering eight lines early. Put sprite 0 at y=232, waiting for PPUSTATUS to register a sprite 0 hit, and then write $00 to PPUMASK. This creates a blank bar at the very bottom of the NTSC picture, which will generally fall within the overscan, and during the scanlines that this blank bar is present, you can write to PPUADDR/PPUDATA all you want. (But don't try to update the palette until the real vblank starts.)

by on (#39734)
To get this thing of effect, it's a good idea not to deal with CHRRAM, because it's just insane. You'd have to write loads of unrolled loops, VBlanks that are longer than natural VBlanks, etc...
With CHR-ROM it would be very simple to do (only a bit wasteful, but you get nothing for nothing), and you'd just have to do update ~4 lines of nametable each 8 pixels of scrolling, which is doable with a simple unrolled loop.

Quote:
That would require a donor cart with MMC3 or another mapper that switches CHR pages smaller than 4 KiB. The 7400 and CPLD mappers on RetroZone boards can't handle it.

Wrong, it would work very well with MMC1, just that you'll need to have 8 pages of 4kb containing graphics for the moutain (of 8 different pixel shifts) and blocks for that level. This could take about 64 tiles, leaving you 192 tiles for any other in-game use of the same CHR banks.
But it's true it would be more optimal to use MMC3 to get 1kb switching and reserve 8 1kb banks for the mountains. Also you would have no reason to reduce detail in the mountains that way, because it woudln't change anything (unless it takes a really great amount of tiles).
Also I guess MMC2/4 would be great for this kind of things (but donor carts are extremely rare).

Quote:
You really wouldn't need to rewrite the nametables at all.

Not if scrolling horizontally, but of course yes if you scroll vetically. I guess tepples assumed you scrolled horizontally, but I guess you wanted it vertically.

EDIT : Keep in mind that the number of rows that there is to update in the nametable is one more than the number of rows the graphics take. I just tought I'd mention that. Without tricks you can update 4 rows per VBlanks, so mountains/horizon graphics should take 3 rows of graphics. If you want to update more and take an extended VBlank this should be less trouble because you know in advance the fine scroll when this happens (it's always zero), saving you load of troubles. Having extended VBlank when and only when this happens could be a decent solution, as glitches would be hidded by NTSC monitors, and the VBlank is always extended on PAL so this isn't needed.

If you want to avoid having to update both pattern tables and nametables, you could simply have all graphics for all 8 possible positions in a single pattern table, so you'd "only" have to update 4 rows of nametable each time you're scrolling. This would work with both CHRROM (of all sizes) and CHRRAM, but if you also need updates when scrolling the playfield you're screwed.

by on (#39738)
Bregalad wrote:
Quote:
That would require a donor cart with MMC3 or another mapper that switches CHR pages smaller than 4 KiB. The 7400 and CPLD mappers on RetroZone boards can't handle it.

Wrong, it would work very well with MMC1, just that you'll need to have 8 pages of 4kb containing graphics for the moutain (of 8 different pixel shifts) and blocks for that level.

Sure, you could do parallax with 4 KiB switching, but then your 128 KiB CHR starts behaving more like a CNROM-era 16 KiB CHR.

Quote:
Quote:
You really wouldn't need to rewrite the nametables at all.

Not if scrolling horizontally, but of course yes if you scroll vetically. I guess tepples assumed you scrolled horizontally, but I guess you wanted it vertically.

There's a difference between dollying and panning. In dollying, the camera moves, and a parallax scroll is appropriate. In panning or tilting, the camera turns, and there is no parallax effect because there is no motion of the camera in space. I'd recommend following the model of Kirby 64, Street Fighter II, and NBA Jam, which use dollying horizontally and tilting vertically. To do this, perform all parallax effects horizontally, but don't perform any vertically.

But in any case, if you're scrolling vertically, it'll be more difficult to turn off rendering early because you might not always be able to tell where the opaque part of the background is.

by on (#39740)
tepples wrote:
Sure, you could do parallax with 4 KiB switching, but then your 128 KiB CHR starts behaving more like a CNROM-era 16 KiB CHR.

What do you mean by that ?
Even a simple SEROM with 32kb PRG and 32kb CHR could handle that : I seems that the screenshots above can be made with approximately 19 tiles, if you dare to repeat those 19 tiles over all 8 availalbe 4kb CHR banks (with mountains shifted vertically), and can do all the rest of graphics like normal exept using only 237 tiles instead of the usual 256, you're done almost like what SEROM would normally limit you too. You get nothing for nothing.
If you use 64kb CHR, this would impose for example that limit only to BG tiles and he's able to handle all sprites with the normal 256 limit.


Altough I agree it would be more convignent to have all CHR banks dedicated to one more more than one levels, than having one level using all CHR banks at the same times and the other levels sharing the rest of CHR banks, but this is perfectly possible and not even that limitating.

by on (#39741)
Personally I would do it with CHR-RAM, only use banked ROM if it was really needed. This is from the perspective of using all available resources (including vblank - if it's unused, it's wasted), and also on keeping the cost of a cart down.

by on (#39742)
You could actually get away with only writing to 2 tiles if you were doing CHR RAM. That looks like all that's changing. That's 32 bytes, which is 256 cycles unrolled. That's pretty doable.

by on (#39744)
Bregalad wrote:
tepples wrote:
Sure, you could do parallax with 4 KiB switching, but then your 128 KiB CHR starts behaving more like a CNROM-era 16 KiB CHR.

What do you mean by that ?
Even a simple SEROM with 32kb PRG and 32kb CHR could handle that

And have sprites taken from the same bank as the background, right?

Quote:
Altough I agree it would be more convignent to have all CHR banks dedicated to one more more than one levels, than having one level using all CHR banks at the same times and the other levels sharing the rest of CHR banks, but this is perfectly possible and not even that limitating.

Every effect needs to justify its existence to the byte-counters, and every byte needs to justify its existence to the bean-counters. If you can make a good argument that dedicating half your CHR ROM to one subtle effect is worth it, then go ahead. Otherwise, five 8-byte copies to CHR RAM start to look good.

by on (#39746)
Celius wrote:
You could actually get away with only writing to 2 tiles if you were doing CHR RAM. That looks like all that's changing. That's 32 bytes, which is 256 cycles unrolled. That's pretty doable.

Celius is right... Everyone else is making it too complicated...

Since you reduced the complexity of the mountains, there are very few tiles to update now. There are just 2 for the mountains (side by side), as Celius said, and 2 for the gradient (one on top of the other).

I don't know if plan on treating the gradient like the mountains, but even if you do, there are in fact only two colors in use for the background, so you can get away with updating a single plane of the tiles if you put those colors in the appropriate order in their palette. So with just 8 bytes per tile you only have to update 32 bytes of pattern table data, and like Celius said this is pretty doable, even considering all other PPU updates necessary (sprites, palettes, name tables, etc).

And like tepples said, since the edges of your small pattern connect, no name table updates are necessary. Just keep in mind that there are 16 rotations now (doesn't really make a big difference in the code).

Forget about longer blanking periods and things like that. What threw people off was the original detailed image of the mountains. That would require a lot of work, but the small repeating pattern you have now is easy.

by on (#39747)
Celius wrote:
You could actually get away with only writing to 2 tiles if you were doing CHR RAM. That looks like all that's changing. That's 32 bytes, which is 256 cycles unrolled. That's pretty doable.

Well, the minimum is 5 tiles (see above)
Quote:
And have sprites taken from the same bank as the background, right?

No, just that 19 tiles would be eaten to each sprite bank for that effect. Other than that everything should be like normal (this is only for the 32kb case, I don't know what the guy is planning to use for a mapper).
Quote:
Every effect needs to justify its existence to the byte-counters, and every byte needs to justify its existence to the bean-counters. If you can make a good argument that dedicating half your CHR ROM to one subtle effect is worth it, then go ahead. Otherwise, five 8-byte copies to CHR RAM start to look good.

Is 19 tiles per bank half of CHRROM ? It is only 7,4%, and you get nothing for nothing.
And it sounds hard to update 5 CHRRAM tiles and 4 nametable rows in a single VBlank, until you do insane tricks like Battletoads does, which are not to recommand to newbites.

EDIT : Oh tokumaru posed while I did. Well, maybe I'm making things too complicated, but I don't see how he could do vertical parallax scrolling without nametable updates. If you can then go ahead, again I don't care anyway I'm not doing that in my game and that will still make it decent (I hope).

by on (#39751)
Bregalad wrote:
Is 19 tiles per bank half of CHRROM ?

No, but if levels that include parallax are limited to just the tiles shown in this picture, they can't be very graphically complex. I was thinking ahead for when more tiles are added to the equation.

Quote:
And it sounds hard to update 5 CHRRAM tiles and 4 nametable rows in a single VBlank

I missed the part where the OP talked about specifics of the nametable update strategy.

by on (#39753)
Bregalad wrote:
Well, maybe I'm making things too complicated, but I don't see how he could do vertical parallax scrolling without nametable updates.

It's possible because the same small section of mountains is repeated across the whole background, there are no interruptions.

Name table updates would be necessary only if at some point he wanted only sky and no mountains, for example. Or if the repeating pattern was too long, because it would be impractical to have all possible rotations in CHR-ROM or it would mean too many CHR-RAM updates.

Name table updates reduce the memory cost because no matter how long your parallax pattern is, you only need 8 rotations. After 8 rotations, all tiles have to be shifted and we go back to the first rotation. But think about it: if instead of updating the name tables you kept rotating the patterns for 8 more steps, a 16-pixel wide area would be covered before name tables updates are needed. Now, imagine that if the repeating image is in fact just 16-pixels wide, like SSD's mountains, redrawing everything shifted 16 pixels is totally unnecessary, because it'd look the same. I suck at explaining stuff, but I hope you got it.

Just check the games I named, Sword Master and Metal Storm. Neither performs any name table updates related to the parallax effects, it's all CHR-ROM bankswitching.

by on (#39755)
Quote:
No, but if levels that include parallax are limited to just the tiles shown in this picture, they can't be very graphically complex. I was thinking ahead for when more tiles are added to the equation.

Yes this is absolutely right, but I was just saying it would be possible, not optimal.

Quote:
Just check the games I named, Sword Master and Metal Storm. Neither performs any name table updates related to the parallax effects, it's all CHR-ROM bankswitching.

Both of those games does horizontal parallax effects, not vertical, and it loops forever. The montains in the background doesn't look to loop forever in his screenshots, which changes a lot of things !

Quote:
Name table updates reduce the memory cost because no matter how long your parallax pattern is, you only need 8 rotations. After 8 rotations, all tiles have to be shifted and we go back to the first rotation. But think about it: if instead of updating the name tables you kept rotating the patterns for 8 more steps, a 16-pixel wide area would be covered before name tables updates are needed. Now, imagine that if the repeating image is in fact just 16-pixels wide, like SSD's mountains, redrawing everything shifted 16 pixels is totally unnecessary, because it'd look the same. I suck at explaining stuff, but I hope you got it.

If he applies what you say, he'll get a mountain rotating itself in the background and that scroll down just as the foreground does. In order to matain the mountain in place, it should be raised in the nametable as the same rate the scrolling raises up.

Or are you talking about having enough tiles in CHRRAM to cover the whole 30 rows of the nametable ? That would mean 60 tiles should be reserved for the effect (but only 4 of them updated at a time), but yeah no nametable update needed. I guess that's a good idea after all. It'd just be a shame computing the adress of the tiles that needs to be updated.

by on (#39758)
Also, since it's only 32 bytes, you might even be able to set aside an array for that in Zero Page. So it would actually be 224 cycles to do it.

Also, I think you mentioned to me once, Tokumaru, the idea of doing CHR RAM updates when there's free time. Say if you're not updating a row or a column of tiles, then you could update the CHR RAM data. Though this might not be such a good idea in situations where there are always updates for whatever reason.

Though if you are scrolling vertically, you'll want to modify the name table as well as the tiles. It just didn't look like that's what you were doing.

You know, you're not just limited to working with the BG and shifting tiles. Sprites operate on a coordinate system, and can go behind the background (except for color #0). Perhaps you might benefit from doing something with sprites. I'm not saying make a mountain out of sprites (that's a bad idea, especially since you only have 64 sprites and 8 on a scanline), but you might be able to do something with them. In my game, you'll enter a cavern-type area, and there'll be some icicle-type rock formations hanging down that will be made of sprites, and there'll be parallax for them.

Another thing I might do is for something like a large moon, make the circular part out of sprites while filling the center in with solid BG tiles. This would require only writes to the name table, but it'd probably require a lot of sprites to completely cover the solid BG tile edges. You'd want to do this with 8x16 sprites because it's big, but your biggest issue would be worrying about the 8 sprite per scanline limit. If you have the circle part of the moon flickering when the BG doesn't, it'll look pretty bad.

by on (#39760)
Thank you all for your informative responses. You've all given me some really good ideas to consider.


tokumaru wrote:
I don't know if plan on treating the gradient like the mountains, but even if you do, there are in fact only two colors in use for the background, so you can get away with updating a single plane of the tiles if you put those colors in the appropriate order in their palette.

Pure genius. I originally restricted the background and each 16x16 pixel region of the foreground to two colors each so they could play well together with the palette/attribute tables. Your observation is one I wish I had thought of. :)


Celius wrote:
You know, you're not just limited to working with the BG and shifting tiles. Sprites operate on a coordinate system, and can go behind the background (except for color #0). Perhaps you might benefit from doing something with sprites.

That's a really great idea, and in fact I plan to do exactly that, but not for the background due to the sprite/scanline limitations you mentioned. I intend to use some sprites to create an additional foreground layer (maybe high altitude cirrus clouds), which will actually scroll faster than the platforms as you ascend the mountain. What's cool about using sprites for the clouds is that I can also move them horizontally to indicate wind.

by on (#39762)
Oh yeah, I actually plan to use sprites for clouds too! This would be good as you could place them behind tree tops. to make it look really layered.

I really dislike some really stationary backgrounds where it looks really really flat; especially ones with skies. Using sprites for the moon and clouds really eliminates this garbage wall paper look. Though sometimes that adds character to a game, I generally just think it looks bad.

EDIT: About making the foreground, that is a really great idea. Having a foreground like you mentioned really makes it look 3Dish. In my opinion it has way more effect than making an extra background layer. Both in combination will really make your game look great (assuming you pull it off right).

by on (#39768)
Bregalad wrote:
Both of those games does horizontal parallax effects, not vertical, and it loops forever.

I believe I mentioned those requirements for it to work as I suggested. Well, maybe not the lack of vertical effects, but yeah, I was completely disregarding vertical parallax effects. This would make things extremely complicated.

Like tepples suggested, there are games with horizontal parallax effects only, while vertical scrolling works as usual, and that doesn't look bad at all. I guess we tend to forgive the lack of attention to vertical scrolling. Even in Sonic games you can find several levels where the background doesn't move up or down at all. I can't remember if there is any that scrolls at the same rate as the foreground though.

Quote:
The montains in the background doesn't look to loop forever in his screenshots, which changes a lot of things !

Of course they look like they loop! They are only interrupted by foreground objects, and there is no problem with that. You'd need name table updates only if there were background interruptions, but the background looks very contiguous to me.

Celius wrote:
Also, I think you mentioned to me once, Tokumaru, the idea of doing CHR RAM updates when there's free time.

Oh yeah, but this is probably not appropriate for parallax effects, as the movement would look pretty jerky when updates failed to be executed on time, because the foreground would still scroll, meaning that the mountains would be moved the same amount as the foreground, and you'd cancel out half of their movement only on the next frame... they would appear to flicker or shake back and forth, really bad...

This idea was originally for updating animations of objects... Since objects rarely have their graphics changed every frame (it's more like every 4 frames for 15FPS animations) a delay of 1 frame to load the new graphics shouldn't really be noticeable.

@SecretServiceDude: Sorry, I missed the part where you showed you'd need to change 5 tiles and just from looking at it I assumed 4 (although you could easily reduce it to 4 if you shifted the graphics down a bit, unless you have a very specific reason to use that particular vertical position). But still, with the single plane trick we're looking at 40 bytes, pretty doable. Like Celius suggested, that's so little you could even buffer the bytes in zero page, so that it'll be quicker to read them, although that's not a requirement if you have the VBlank time to spare.

If you are feeling like optimizing it really bad, you could take advantage of the fact that the gradient has a few lines that alternate, so you could keep the 2 patterns in 2 different registers and perform a few writes before needing to load new patterns, saving some time. And the bottom of the mountains tiles have a few lines that are always filled and need nu updates at all! Of course this is specific to the mountains, and if you plan to use the same code for different graphics you'd better stick with full tile updates. You could have optimal copying routines for each type of graphics, but that sounds a bit extreme if you're not really short of VBlank time.

by on (#39769)
tokumaru wrote:
@SecretServiceDude: Sorry, I missed the part where you showed you'd need to change 5 tiles and just from looking at it I assumed 4 (although you could easily reduce it to 4 if you shifted the graphics down a bit, unless you have a very specific reason to use that particular vertical position).

If the mountains were locked in place, I would definitely shift them down to fit nicely within tile boundaries. But the key point here is that the mountains are not stationary; I intend to scroll them 1 pixel for every 16 pixels of foreground movement. Since the mountains will scroll (albeit slowly), most of the time they probably won't fit nicely within tile boundaries, which is why I update that extra tile.

I hope that clears up any misunderstandings, just in case there were any.

by on (#39770)
Ah, so you will in fact use vertical parallax as well... Well, it seems like you'll need name table updates after all. Sorry, I missed that.

Have you figured a good way to redraw only the necessary rows of the name tables? The fact that there are pieces of foreground covering the mountains will probably make this a little harder, because you'll either have to skip them or redraw them. Redrawing is probably easier.

by on (#39775)
SecretServiceDude wrote:
I'm currently designing a vertically scrolling level where the player infiltrates a mountain base. The player starts at the bottom of the mountain, then works his way to the summit.

SecretServiceDude wrote:
This particular level only scrolls vertically, so that should simplify things considerably.

Bregalad wrote:
Not if scrolling horizontally, but of course yes if you scroll vetically. I guess tepples assumed you scrolled horizontally, but I guess you wanted it vertically.


Tokumaru, tepples : Instead of accusing me to complicate things, you should better read what the author asks instead of posting wrong things.
Especially since I mentionned a couple of times that you should be mitaken horizontal and vertical and you completely ignored that.

@Secret sevice dude : I'm really sorry but you'll have to read the whole thread ignoring all tepples and tokumaru's posts, because they were assuming you were scrolling horizontally all the way down there. This should be really confusing to you but I can't do much for you. I should have been confusing too myself I guess.

by on (#39777)
I was indeed thinking horizontally all the way... sorry. I guess that the word "parallax" simply feels related to horizontal movement. So even though I read all the posts, my brain simply turned "vertical" into "horizontal". Sorry about that.

But he doesn't have to ignore everything. He seems to have got good ideas from the discussion anyways, and that's what counts. By now he already knows how to update the tiles and knows that name table updates will be necessary.

by on (#39778)
Bregalad wrote:
@Secret sevice dude : I'm really sorry but you'll have to read the whole thread ignoring all tepples and tokumaru's posts, because they were assuming you were scrolling horizontally all the way down there. This should be really confusing to you but I can't do much for you. I should have been confusing too myself I guess.

With all due respect, I greatly appreciate the posts from tokumaru and tepples, and yours as well. All of the posts here have been enormously helpful, so I have no reason to ignore them.

It's true that I'm new to NES programming, but by no means am I a novice game programmer; I've been doing it professionally for several years. Even if there was a little bit of miscommunication in this thread (which is bound to happen once in a while), I possess enough experience as a programmer to disregard/modify a suggestion if it doesn't suit my needs. I'm not so easily confused, but if it does happen, I'll be the first one to ask for clarification.

After taking everyone's suggestions into consideration, I'm well on my way to getting this effect off the ground. You guys really help me to think in new and sometimes unorthodox directions, which is extremely cool.

by on (#39779)
Okay it's really great if you aren't confused by that. You should be able to do it on your own then.
It's great that you are a professional programmer, you'll be able to teach me how to do boss AI without leading to horrible spagetthi code :roll: (I have terrible trouble with that).
Something tells me that your game will really rock. You seem to be an awesome graphist too. The mountains still looked better originally (without being restricted to 16x16), if you can do that and keep them on 3 tile rows, and use the method I described on my eariler posts with CHRROM, you'd probably get great results. But do whathever you want because you're a pro !

by on (#39780)
Bregalad wrote:
Something tells me that your game will really rock.

I sure hope so. That's really awesome to hear. Thanks for the encouraging words!


Bregalad wrote:
You seem to be an awesome graphist too.

Again, thanks for the compliment. Actually, one of the major reasons I chose to create an NES game (besides nostalgia) is that the graphics are limited, so I stand a better chance of putting together some passable graphics. If I attempted to make an SNES game, my efforts would look painfully amateurish compared to commercial releases.


Bregalad wrote:
The mountains still looked better originally (without being restricted to 16x16)

I agree with you there. For now, I'm doing everything I possibly can to simplify the effect in order to increase my probability of success. If I can get vertical parallax to work in the simplest case, I'll gradually add sophistication to the effect until I reach the limits of the hardware (or my ability). So, hopefully I'll be able to support more varied mountains eventually, but I'll worry about that later.

by on (#39782)
Quote:
Again, thanks for the compliment. Actually, one of the major reasons I chose to create an NES game (besides nostalgia) is that the graphics are limited, so I stand a better chance of putting together some passable graphics. If I attempted to make an SNES game, my efforts would look painfully amateurish compared to commercial releases.

It's exactly the same for me ! In fact I want to master how to do NES graphics and hope to make decent SNES graphics later (because I have more nostalgia for the SNES than NES personally). I don't know how well that strategy will work.

by on (#39784)
Actually, both the NES and the SNES aren't as nostalgic for me. They are nostalgic, but not as much as other people here, I'm sure. The Gameboy is by far the most nostalgic system for me. Some day I'll learn to program for it. I just really like the NES, and I thought it'd be simpler to program for than other consoles with all of it's limits (I was sort of wrong). One day I plan to move onto the SNES as it's a lot more capable. I really am not so concerned about not being able to make graphics that aren't amateurish as much as I am about making code that I think is running perfectly but since there aren't many debugging tools, there's really some small glitch that will cause the program to completely crash in one spot. Since I've only been programming for about 3 years, and I've only done the 6502 and a tiny little bit of QBasic, I don't think I'm ready to move on to that quite yet.

Bregalad wrote:
Tokumaru, tepples : Instead of accusing me to complicate things, you should better read what the author asks instead of posting wrong things.
Especially since I mentionned a couple of times that you should be mitaken horizontal and vertical and you completely ignored that.

@Secret sevice dude : I'm really sorry but you'll have to read the whole thread ignoring all tepples and tokumaru's posts, because they were assuming you were scrolling horizontally all the way down there. This should be really confusing to you but I can't do much for you. I should have been confusing too myself I guess.


You don't need to speak with such a hostile tone. It was just a simple misunderstanding. I wasn't sure either about whether he meant he was going vertically or horizontally.