Pixelwise scrolling sideways - how many ways to do it?

edited January 2012 in Development
Not that I need to, but I've been wondering if there's a good way to do this that I haven't considered.

Scrolling pixelwise vertically is "easy enough" - there's all the magic trickery you can do with tweaking the stackpointer and pushing and popping it.

But how about horizontally? I can see two ways of doing it that way (assuming it's tilebased) - shift all the blocks on the fly or have some preshifted copies in memory. Just like with sprites, really.

But have I perhaps missed a trick to doing it horizontally, or are the two above methods the only ones that work?
Post edited by Sokurah on
Website: Tardis Remakes / Mostly remakes of Arcade and ZX Spectrum games.
My games for the Spectrum: Dingo, The Speccies, The Speccies 2, Vallation, SQIJ.
Twitter: Sokurah

Comments

  • edited January 2012
    Preshifted copies work well if the background fills only part of the screen space. It could be very fast, up to 50 fps.

    Shifting the raster does not work well if you want to scroll with step that is not equal to 1, 4 or 8 pixels, or with arbitrary step.

    I don't know other ways to scroll horizontally.
  • edited January 2012
    You could use a wrap-around buffer and just fill in the edges. Then rotate bits in-situ and periodically copy to the main screen, but that's not fast.

    R-Type is probably the cleverest design of all, rotating bits in-situ on the screen and drawing the sprites around it so that the scenery is never over-written.

    But on a technical level, there are some intensely technical optimisations that Joffa was best at.

    There's the approach of TurboThe Tortoise, where adjacent blocks are ORed together before being written. That re-renders the whole screen from blocks at any position, but it can be a little slow and may need to go first to a temporary screen, then copied to the main one quickly to avoid flicker.

    For ultimate speed optimisation, you pre-shift what will pass through fixed chunks of the screen rather than the tiles themselves. So you store (1) a rolling empty background; (2) transition from empty to block (3) one block to another block and (4) block back to empty background. You load these into four registers and then prepare a PUSH loop with the various PUSH statements (up to 16 of them to cover the width of the screen) in the right order, and repeat that in a loop 16 times (for each row of the tile). It's a very fast way of rendering the scenery, but it only allows you one type of block per row (or two if you allow for a NOP or EXX between PUSHes).

    Joffa also liked to leave black attributes either side of the scrolling area, so that the rendering could start a byte earlier to do an 8-pixel scroll. In Cobra (the fastest scroll routine he wrote), there's actually a very wide border so whole sprites can be drawn off the edge of the play area.
    Joefish
    - IONIAN-GAMES.com -
  • edited January 2012
    As posted in the CPCWiki Forum by the author.....

    The Spectrum version of R-Type does not scroll the entire screen, that would be just too slow, and why bother scrolling big tracts of empty nothing?

    Think of one horizontal line with nothing in it but space, a quick left to right character scan against a collision map tells you that there's nothing there to scroll - so it doesn't.

    Now imagine that line with some background scenery in it, say somewhere in the middle, with empty spaces to the left and right of it. Scanning from left to right reads something like this...xx characters of empty space...yy characters of background...zz characters of empty space. You only need to scroll the yy characters and not the xx and zz spaces (since obviously pixel scrolling a space gives you....a space)

    Of course, as you're scanning left to right and find a block of characters to scroll (and scrolled them) you need to keep scanning until you reach the end of the line just in case there's another block. Which is often the case on the more organic looking levels where there are very few contiguous horizontal background characters.

    This is what the Spectrum version does. It goes down the screen character line by character line and only scrolls data it finds that's background. And it only ever scrolls it a single character-high at a time, since that's all there is in a character line.

    The number of such scrolls varies as it's going along, Level 1 has no background right at the start....so no data is scrolled. When some simple floor graphics appear it may be doing 3 or 4 scrolls per frame, and later when you start getting irregular ceiling and floors the number increases quite a bit. It may sound silly that at times only one single character of data is being scrolled because there's an empty space to the left and right of it but the miniscule amount of time it takes to do that makes it worthwhile.
  • edited January 2012
    Shiru wrote: »
    I don't know other ways to scroll horizontally.
    joefish wrote: »
    But on a technical level, there are some intensely technical optimisations that Joffa was best at.

    There's the approach of TurboThe Tortoise, where adjacent blocks are ORed together before being written. That re-renders the whole screen from blocks at any position, but it can be a little slow and may need to go first to a temporary screen, then copied to the main one quickly to avoid flicker.

    Yeah, TurboThe Tortoise is imho up there among the very best scrolling games on the Spectrum. It does look like it goes 4 pixels at the time, though, but you wouldn't think so from looking at it.
    ...that, or I'm wrong about the scrolling in nibbles, of course. wrongified2.gif

    But okay, I was just checking to see if there was something I'd overlooked, but it seems like things are just like I suspected.

    Thanks guys. :)
    Website: Tardis Remakes / Mostly remakes of Arcade and ZX Spectrum games.
    My games for the Spectrum: Dingo, The Speccies, The Speccies 2, Vallation, SQIJ.
    Twitter: Sokurah
  • edited January 2012
    Penetrator is another game that uses four pixel scrolling; it's a decent trade off between smoothness and speed when your frame rate is relatively modest.

    To do it without pre-shifting, you can make use of the BCD rotation instructions RLD and RRD which, if a teeny bit slower than RL (hl) and RR (hl) can get a full screen scroll going at a decent enough rate. I'd imagine that if you threw in the same sort of optimizations that R-Type uses you could get something that positively flies along.
  • edited January 2012
    RLD and RRD are two instructions I haven't actually used yet. They are interesting, but they take their time over what they do. Certainly quicker than doing four separate shifts, but then since it's only two shifts per whole character of movement then pre-shifting begins to look attractive as an option. I'd also wonder about doing a finer scroll but optimised to a higher frame rate.

    But really, it comes down to whether you can always optimise the scroll around a majority of blank areas, or if you want a detailed tile map across the whole play area.
    Joefish
    - IONIAN-GAMES.com -
  • edited January 2012
    joefish wrote: »
    There's the approach of TurboThe Tortoise, where adjacent blocks are ORed together before being written. That re-renders the whole screen from blocks at any position, but it can be a little slow and may need to go first to a temporary screen, then copied to the main one quickly to avoid flicker.

    how do you know that?

    honestly I'd love to know, Dave used to explain paralax and preshifting blocks etc but never went too technical in his details

    I knew I should have copied his library of routines before he went off to be a project manager at Codies!!
  • edited January 2012
    I'm sure he's been on here and said about it, didn't he?
    Or I might have read too much into a description of it.

    Oh b*ll*cks, no. I've just found the thread and it was you talking about scrolling the parallax blocks in the opposite direction - not how the rest of the screen is done.
    http://www.worldofspectrum.org/forums/showthread.php?t=24289&highlight=turbo+tortoise+scrolling&page=3

    OK, I don't know then. Be interested to find out if someone knows. From the speed it runs at it must be pre-shifted, and the parallax effect implies that it's being re-drawn from tiles each time rather than a rolling buffer, but how it splices individual pre-shifted tiles together I'm clearly only guessing. I haven't written one like this so I'm not sure what's an efficient approach.
    Joefish
    - IONIAN-GAMES.com -
  • edited January 2012
    Looking at it again, it's a 4-pixel scroll so if it is pre-shifted, that's only two versions of each block absolutely necessary; four if feeling extravagant. From timing a walk-past of a bit of scenery, it looks like it takes 4 frames between refreshes, which seems plenty long enough to render to a hidden screen then copy to the main one. It's also limited in the screen area - 26x16 characters. But then so are a lot of Speccy games, including Cobra. While it runs smoothly enough, I wouldn't expect to find any mind-bendingly efficient optimisations in there.
    Joefish
    - IONIAN-GAMES.com -
  • edited January 2012
    Hysteria has a nice scroller and uses a back-buffer for the middle third of the screen which contained the scenery. If I remember correctly, It uses PUSHes to draw the blocks for the ground and unrolled LDIs to transfer the back buffer to the screen behind the raster and the sprites are redrawn on top of the fresh display. The back buffer is bit-shifted and new 1-byte wide vertical strips put in as needed. It works really well and gives the effect of a 3-layer parallax play area.

    It's a fun game too!
  • edited January 2012
    Ah, I'm glad someone's been poking around in that code, as I'm rubbish at figuring out what's going on from looking at other people's code. I usually just resort to trying to figure out how I would do it, coding it, and seeing if it runs anywhere near as well. And I do love Hysteria. I did once experiment with writing a similarly styled game for the ST, but I got distracted by trying to optimise lots of rather nifty parallax scrolling.

    In fiddling with code I find it can sometimes be quite a close race between re-drawing a scene from pre-shifted tiles; or scrolling, then copying, a back buffer. If you have a few tiles and can use POP/PUSH, the former takes the lead. But add more tiles and the latter wins out, even if only from the amount of memory saved.

    I guess that's the same difference between Cobra and Hysteria.

    There are several other scrolling techniques I'd like the time to experiment with. The big over-arching issue is working out how to present a game such that whole character-space scrolling comes across as smooth and presentable. Then, you needn't worry so much about colour clash. For that, you need big sprites and fast movement. But at 50Hz the entire width of the screen would scroll in under a second; 1? seconds at 25fps. But as you slow down the refresh rate, the size of the step and the jerkiness would become more apparent.
    Joefish
    - IONIAN-GAMES.com -
  • edited January 2012
    joefish wrote: »
    Looking at it again, it's a 4-pixel scroll so if it is pre-shifted, that's only two versions of each block absolutely necessary; four if feeling extravagant. From timing a walk-past of a bit of scenery, it looks like it takes 4 frames between refreshes, which seems plenty long enough to render to a hidden screen then copy to the main one. It's also limited in the screen area - 26x16 characters. But then so are a lot of Speccy games, including Cobra. While it runs smoothly enough, I wouldn't expect to find any mind-bendingly efficient optimisations in there.

    on Turbo, from what I remember there was only one set of tiles loaded in memory per level (think it was 2 levels per load), so unless the game created a preshifted set when it had loaded - it didn't preshift

    tbh I didn't really take much note of the programming side which was a missed opportunity :sad:
  • edited January 2012
    joefish wrote: »
    In fiddling with code I find it can sometimes be quite a close race between re-drawing a scene from pre-shifted tiles; or scrolling, then copying, a back buffer. If you have a few tiles and can use POP/PUSH, the former takes the lead. But add more tiles and the latter wins out, even if only from the amount of memory saved.

    I guess that's the same difference between Cobra and Hysteria.

    The clever use of colour in Hysteria masks the restriction of only the middle 7 lines of the screen being used by the main scroller. The 4 lines below are done using PUSH since they're just a repeating pattern. I wouldn't be surprised to find some code from Green Beret in Hysteria's background rendering routine. It just goes to show that by combining different scroller techniques, you can play to their strengths and end up with something that's still balanced enough to allow some decent gameplay.
    joefish wrote: »
    There are several other scrolling techniques I'd like the time to experiment with. The big over-arching issue is working out how to present a game such that whole character-space scrolling comes across as smooth and presentable. Then, you needn't worry so much about colour clash. For that, you need big sprites and fast movement. But at 50Hz the entire width of the screen would scroll in under a second; 1? seconds at 25fps. But as you slow down the refresh rate, the size of the step and the jerkiness would become more apparent.

    A nice trick that Joffa used for both Cobra and Hysteria was to scroll the ground every single frame but the background only scrolls every other frame.

    This meant that by drawing the background after the raster in one frame and drawing the sprites ahead of it in the next, the CPU usage could be used across two frames for the scrolling background and sprites but the 50Hz scrolling of the ground helps give an illusion of everything moving smoothly. Just to mention, in Hysteria, the first layer of background parallax is also drawn using PUSH but only scrolled every other frame along with the backdrop. Because it's a 4-frame tile it scrolls by two pixels instead of one so it moves at half the speed of the ground but twice the distance of the backdrop.

    Might be something to think about if your game design allows it - Scroll a peripheral portion of the play area at 50Hz but the 'interactive' area at 25Hz? It would allow the CPU some extra time to generate some interesting colour effects which might help mask the slower update speed.
  • edited January 2012
    kphair wrote: »
    I wouldn't be surprised to find some code from Green Beret in Hysteria's background rendering routine.
    Green Beret scrolls middle part of screen by classic RL(HL), i believe it was about 2048B to scroll. upper part is cleared by PUSH, dont remember how scroll was performed on the most bottom line of terrain.
    sprites are put directly on screen after it was cleared (upper part) and background was copied from buffer (bottom part).
  • edited January 2012
    I don't know if you've seen it, but I can do the Cobra scroll over the full screen at 50Hz, though that's obviously without sprites or any real game going on. I haven't tried to tackle a more detailed background like Hysteria, but I have tried the split scrolling thing combined with a little multicolour. I've got a feeling that drawing those masked sprites in Cobra is a far more intensive job than the actual scrolling, to be fair. But the bit of 50Hz is a lovely trick for fooling the eye into thinking things are a lot smoother than they are.

    However, I'm only really interested in it if I can do a larger screen area, and combine multicolour, otherwise I'd just end up with a restrictive game window like we've seen so many times before. Or worse. A 16-character wide horizontal scrolling game isn't going to impress anyone.

    Combining multicolour with scrolling is exceedingly complicated; I've made several tries at it, some more successful than others. I'm working on a game based on one of these at the moment, though I have a few others on the back-burner for later.

    On the ST, with memory to spare, I'd have four copies of the background in memory, each pre-shifted by 4 pixels, then use a self-modifying wrap-around copy routine to copy it to the screen. By just swapping screens and pointers I could then 4-pixel scroll the main screen. I could do the same on the Speccy for a 2-pixel scroll, or 2 buffers for a 4-pixel scroll. But sadly, without being able to interleave bitplanes like you can on the ST, you wouldn't be doing any overlaid parallax.
    Joefish
    - IONIAN-GAMES.com -
  • edited January 2012
    BTW. it is surprising how well works scrolling in Astro Marine Corps. i mean it is char based and uses two planes and still works quite nice
  • edited January 2012
    Fikee wrote: »
    BTW. it is surprising how well works scrolling in Astro Marine Corps. i mean it is char based and uses two planes and still works quite nice
    To be honest, I find its frame rate a bit slow and jerky. I'm pretty sure it's less than 10fps. Also the background is going about half the speed of the foreground. A quarter would give a better sense of distance. Maybe it's being a bit too ambitious.
    Joefish
    - IONIAN-GAMES.com -
  • edited January 2012
    In discussions of horizontal scrolling I'm always surprised that Zynaps doesn't pop up more often. It was one of the first full colour smooth scrolling horizontal shoot-em up I'd ever seen with large full coloured sprites.

    Granted that the parallax scroll effect is limited to the stars in the background, but the overall effect is excellent.

    I take it then that it doesn't employ any technical wizardry to get enthused about?
  • edited January 2012
    I think that one of the best colourfull scroll is in Extreme and Dan Dare III. I think that it?s the same, indeed
  • edited January 2012
    I think Zynaps has better scrolling than Turbo The Tortoise.
  • edited January 2012
    climacus wrote: »
    I think that one of the best colourfull scroll is in Extreme and Dan Dare III. I think that it?s the same, indeed
    That's just whole character movement. There's no mystery to that as it's just copying bytes into different places. You can redraw the entire screen from a buffer in 2 frames or from UDGs in about 3 frames. If you scroll the screen by characters at that speed one whole screen goes past in under 2 seconds which is pretty fast, but doesn't give you much time to react. You can spend your time optimising it, of course, but the faster it goes the harder it is to play with; the slower it goes, the more jerky it looks.
    maiki wrote: »
    I think Zynaps has better scrolling than Turbo The Tortoise.
    Zynaps is very smooth, but only has a few small sprites on-screen, which is why R-Type gets all the attention. Zynaps is pretty quick with it's scroll though and the sprites are pixel-positioned. They also go behind the scenery so you'll probably find the scenery scrolling uses a similar technique to R-Type to shift it in-place in the screen memory.

    Zynaps and Turbo are completely different games though. Huge areas of the screen in Zynaps are just empty black space; there are no parallax background textures in the gaps and also no need for the masked sprites over it that Turbo is drawing.

    In Cobra I wouldn't be surprised if drawing the maximum number of sprites takes longer than the scroll routine.
    Joefish
    - IONIAN-GAMES.com -
  • edited January 2012
    Arjun wrote: »
    In discussions of horizontal scrolling I'm always surprised that Zynaps doesn't pop up more often. It was one of the first full colour smooth scrolling horizontal shoot-em up I'd ever seen with large full coloured sprites.

    Granted that the parallax scroll effect is limited to the stars in the background, but the overall effect is excellent.

    I take it then that it doesn't employ any technical wizardry to get enthused about?

    don't forget Joffa's Green Beret as well, that was a colour scroller oooh and Hysteria (his web link still works, that was weird)
  • edited January 2012
    Gutz had a variety of Joffa's scroller, and I also made a separate style one for the rib cage corridors.
  • edited January 2012
    joefish wrote: »
    I don't know if you've seen it, but I can do the Cobra scroll over the full screen at 50Hz, though that's obviously without sprites or any real game going on.

    Well that's half the battle really, isn't it? I've been working on an engine myself on and off and have managed to get close to a full-screen update in one frame but it's very limiting in where you position your code for drawing sprites and managing the updates of all the objects.
    joefish wrote: »
    Combining multicolour with scrolling is exceedingly complicated; I've made several tries at it, some more successful than others. I'm working on a game based on one of these at the moment, though I have a few others on the back-burner for later.

    Don't we all, LOL! This real-life business is a bit of a bugger though. I've decided to put my own project on the back burner for now and work on something simpler that has been on my mind for a long time. I seem to have amassed a large collection of half-written demos over the last 25 years - It would be nice to finish something!
  • edited January 2012
    Before I forget and even though it's not purely a horizontal scroller, I think it's worth bringing up Ghosts 'n' Goblins. Keith Burkhill did a great job with that, especially considering he got most of the gameplay in there as well.
  • edited January 2012
    kphair wrote: »
    Well that's half the battle really, isn't it? I've been working on an engine myself on and off and have managed to get close to a full-screen update in one frame but it's very limiting in where you position your code for drawing sprites and managing the updates of all the objects.
    Oh, definitely. As I've said, given that the scroll in Cobra is windowed to only just over half the total screen area, I wouldn't be surprised if it spends longer drawing all the sprites than doing the scroll. But so it can be a bit lazy and not clip the sprites at the screen edges, there are thick black edges down either side of the play area to hide any overlap, reducing the scrolling area.

    All those games (Green Beret, Hysteria, Cobra) were similar game designs; quick moving with lots of sprites and shots and detailed backgrounds. If they were something like a Mario game, you could arrange it so the sprites are only ever drawn over empty space so don't need masking - that's a hell of a lot quicker (see the Gloop Troops games).

    Hysteria is probably my favourite of all those, but it is a bit cheeky in its design. There's that 50fps scroll at the bottom, and the 25fps one behind the player. The speed you're moving along at is tied to that middle strip (judging by the sprites and worms). But the items you have to collect move with the back screen, which is scrolling at half the speed and is supposed to be some distance behind you.

    What I'm looking at is optimising scrolling to try and do larger areas of the screen. Also to use simpler landscapes with PAPER coloured areas, then get away with not pixel masking the sprites. Also to design games that present a challenge from the layout, thus requiring fewer sprites. And maybe write multiple sprite functions that can clip to screen edges so the play area is the full screen width. And obviously to fit this in and around any multicolour I can get away with. But then I want lots of parallax, and all in 50fps too...

    There are a few things I really want to do on a 128K, but I've just started a large project that I hope I can fit in to 48K. It would be a shame if it didn't as I would be taking a different approach if it was a 128K project.
    Joefish
    - IONIAN-GAMES.com -
Sign In or Register to comment.