A Proper Vertical Parallax Effect on the Commodore 64?
Ever since I released the first playable demos of my prototype game, Colony, back in the mid 1990s, I have mused on how I could have enhanced the visual qualities of the game.
Specifically, I wondered if the parallaxed landscape could be given a vertical component, as a means of emphasising the sense of space and motion.
Obviously, such features are common in games for more modern platforms, but have never been seen in legacy machines such as the Commodore 64; Ocean's 1986 release, Parallax doesn't count because the entirety of its eponymous parallaxing doesn't extend beyond a simple pattern shift effect - as can be seen in the clip below.
Unremarkable though that parallax effect was by today's visual standards, it was nonetheless enough to build an entire game model around and even name the game after!
Another example from the C64's heyday would be Thunderblade, which demonstrated an extremely crude and somewhat ugly kind of vertical (and slight horizontal) parallax effect:
A much more recent example would be MAH, an unusual game featuring vertical parallax elements
using what appears to be a simple (correct me if I am wrong about that!) vertical pattern shift effect:
It's a slick effect but what I am after is something quite different.
With close to three decades of the demo scene expanding the Commodore 64's capability envelope, maybe it's time to raise the bar on parallax effects too by working a vertical parallax scroll into Colony's landscape so that it dips and rises as the plane climbs or dives.
In other words, let's make Colony's parallax scroller a little more... "16-bit".
HARDWARE OR SOFTWARE?
Upon deciding I had to try to reduce the console-C64 gap through this innovation, the first methodology I thought of was the obvious "go-to"
hardware scroll feature of the VIC-II's notoriously tricky $D011 register.
After all, why bother concocting the charset graphics and associated handling routines for a bloaty software solution when the same effect could be achieved by tickling a register?
That said, I had to be wary of knocking the open top and bottom borders out of kilter, as they rely on $D011 tweaks from within the main game interrupt to stay open.
That initial concern was immediately allayed when I began to "cut code"; $D011 could be modified by the interrupt handlers managing the landscape layers between the top and bottom of the screen without losing the open borders effect.
But... the outcome was mostly hideous: landscape layers shunted out of place and system crashes for no immediately obvious reason; like I said, $D011 doesn't take kindly to being prodded.
However, through lengthy experimentation, I was able to use $D011 alone to vertically scroll the foreground's full-colour scrolling layer (that's the part that has the base and all the little men running around), but it required a sacrifice in the form of the panel below it being reduced by 8 pixels in height (later 16 pixels) to accommodate a buffer space for the vertical scrolling.
There was a snag, however.
The interrupt layering was such that there was only enough space for around 3-4 pixels of vertical scroll in that layer; any more and the machine would crash or the interrupt would stall.
That was never going to suffice; after all, we need the upper layers in the landscape to vertically parallax scroll as well if the effect is to be worthwhile, and that's not going to work if the foreground can only scroll a few pixels vertically.
The only solution for that was to alter the raster trigger values for each handler and to change the size of the foreground layer, making it eat into the distant trees layer above it.
That would mean I could now have a 6 pixel scroll vertical scroll on the foreground before it stalled the interrupt, which was more than enough to convey the vertical motion needed in that layer.
However, the foreground also required an additional interrupt handler, i.e., another raster interrupt layer to create the buffer zone mentioned above, bringing the total in the game engine to a staggering nine.
Or let me put it this way. The game's raster interrupt now does the following via its nine handlers:
- Multiplexes and updates the sprites across 3 screen regions;
- Animates the software sprites aka the little men running around the landscape;
- Sequences the toggleplexing and motions of Sprite #$02 (the afterburner and laser / bomb sprite);
- Polls the joystick for firing the selected weapon;
- Performs the collision detection for the plane's laser hitting enemy sprites;
- Opens the top and bottom borders;
- Dynamically chequerboards the colours (the best way to smoothly mix hues of diverse luminosity on the C64) on the radar display;
- Splits the screen into different zones for background colour, the two multicolours, character bank (using one of either two user-defined graphics sets available) and hi-res;
- Handles the bi-directional multispeed horizontal parallax scrolling and map-feeds, AND...
- Handles a large part of the new vertical parallax scrolling component.
However, after much "panel beating" - my term for any coding process that relies on many iterative trial-and-error sessions - I finally had to concede that the overall desired effect was not going to happen via hardware scrolling alone; some other techniques would also be required because, very early on, it was obvious $D011's vertical hardware scroll was not going to play ball on the other landscape layers.
For the more distant trees at low level (i.e. landscape layer 3) and for the reddish-coloured trees in the foothills (i.e. landscape layer 2), I thought that would entail multiple copies of the char data, offset vertically by one pixel in each iteration, using a fast routine - this time performed outside the game engine interrupt - to switch between the various definitions.
That worked okay (eventually) when I tried it for the low level trees, but I was out of char space for the wooded foothills.
Thankfully, the solution was staring me in the face: switch to another charset for that layer.
AN EXTRA CHARSET? ARE YOU MAD?
Now hear me out.
Before you berate me for the lunacy of finding an extra 2K of RAM just for a non-critical game effect, let me explain that I am planning on doing so much more with that extra charset.
It has to hold additional definitions for the foreground landscape to accommodate a major game feature, namely, the battle-damaged trees and other foreground objects that succumb to the rigours of the conflict raging above and around them.
Recall how I described this in the Colony Game Concept post?
Well, this is the how to compliment the what of that game feature.
YET ANOTHER TECHNIQUE ADDED
So much for the bottom 3 landscape layers; what of the not-so-small matter of vertically scrolling the distant mountains (landscape layer 1)?
For that, I was able to use another cool C64 trick, so beloved of the demo scene (and used in the "get ready" screen of Mayhem in Monsterland).
Gentlemen, I refer, of course, to FLD.
That's Flexible Line Distance, a simple technique that keeps the VIC-II from drawing what it's "supposed" to on-screen until the next raster line (or however many raster lines down the screen you want to delay the rendering process).
In Colony, this is executed within the very first raster interrupt handler, way up above the visible part of the screen, and it affects landscape layers 1 (the mountains) and 2 (the wooded foothills).
So in actuality, the wooded foothills use two methods for their vertical scrolling: FLD + character bank switching.
SUMMARY OF THE METHODOLOGIES
So, to recap, we now have 4 different techniques at play here:
- $D011 hardware scroll on the foreground layer (aka layer 4);
- User-defined graphics definition rotation on the distant low level trees layer (aka layer 3);
- Charset definition change via bank switching on the forested foothills layer (aka layer 2);
- FLD scroll on the distant mountains (aka layer 1) AND on layer 2.
A LITTLE PROBLEM: THOSE NON-STANDARD COLOURS
Remember in the Luma-Driven Graphics article how I said that when using ALM (the Alternating Line Method) to attain non-standard colours, the resultant new colour will exhibit
a bias in favour of the first constituent standard colour in the alternating lines?
Well, by vertically scrolling any screen region occupied by ALM, you inadvertently trigger an eye-jarring effect caused by this bias.
That meant, for example, the murky green of the grass behind the foreground trees was alternating between a much more pinkish green and said murky green with each vertical pixel the foreground scrolled.
Of course, the solution was to switch char banks with every vertical pixel scrolled, to maintain the integrity of the non-standard colours, which is what I ended up doing.
Laborious, fiddly, frustrating but utterly necessary to the final effect because, as I have said before, we're going for finesse here, something to make the game more "16-bit", so the inconvenience of the matter doesn't come into the equation.
WAS THE EFFECT WORTH IT?
Only time and the verdict of the finished game's players and reviewers can say, but personally, I love it and feel that another step in closing the "console gap" has been taken.
One small vertical scroll for this game, but a giant leap for the Commodore 64 gaming scene! (I hope).
In the meantime, check out the clip below and let me know what you think - be sure to set the YouTube Settings to maximum quality!
If you liked this article and want to know when the next one is posted, kindly consider joining my 100% spam-free, nag-free Newsletter.
Anything you receive from me will be cool and interesting - especially if you're a C64 gamer or coder!
In the meantime, feel free to use the handy buttons on this page to share it on social media, if that's your thing!
The seamless combination of advanced techniques you've implemented here is making my jaw drop now in 2019.
I can't imagine how my 1989 self would have reacted to this display of technical and artistic mastery.
(Actually I probably would have insisted it wasn't possible on a stock c64 and then been gobsmacked into stunned silence when proven wrong, only to then do a ridiculous about-face and naively wonder why more c64 games don't boast such features.)
Simmo, I can only say thank you for such praise - I'm not worthy!
It seems that not everyone shares your enthusiasm and appreciation for what I have done thus far, going by some "catty" feedback / subtle snipes elsewhere; perhaps it's rattling a few people who have their own agenda or maybe my presentation style in these articles is alienating some people.
I have spoken about finesse and going to ridiculous lengths in pursuit thereof, which is possibly being interpreted in such as way as to portray me as a braggart, which is the last thing I would wish to be.
Certainly, from my perspective, I have been hoping that other game developers would see merit in the idea of pushing the boundaries for the sake of creative excellence and, even more so, for the betterment of the player experience.
The key thing I don't lose sight of is that no matter what outstanding achievement anyone makes in this world, there will always be someone who will resent you for it; that notwithstanding, the important point is that most people will like it and that's enough to outweigh any petty reactions.
So, onward with the game's development!
Leave a Comment
Comments are moderated to prevent spam and emails are only required to filter basic spambots; such emails are neither harvested by me nor displayed on this website.