Part Two: Pixel perfect platforming
Since the last instalment, I made the decision to go completely back to basics and do some research before progressing any further with my platform game.
Why? It has been a dream of mine to make a C64 platform game for a long, long time, and I want to make the best job of it that I possibly can. And it’s always good to learn something new, right?
Since I am (possibly quite badly) self taught in machine language and it has been many years since I used it last, there are a fair few gaps in my knowledge of how machine language and the C64 work, so I figured it would be a good idea to try to fill in some of these gaps to make progressing with coding as easy as possible.
I already owned The Commodore 64 Programmers Reference Guide, which is very handy to refer to and learn the basics of machine language, but I needed something a little more advanced. I sought out some recommendations from the Lemon64 forums, and one book that cropped up again and again was Jim Butterfield’s ‘Machine Language for the Commodore 64‘.
I recommend the revised and expanded edition, which you can download along with lots of other great books from here: http://www.bombjack.org/commodore/books.htm
Jim’s book is widely regarded as being the best way to get started and to advance with machine language.
Another great suggestion given to me was to study some source code from other C64 games.
This was a very valuable step to take as it has taught me many programming tricks, ways to structure code and some great ways to conserve memory. It can be a little daunting diving in to somebody else’s code, but with the right approach and some patience can be incredibly rewarding when you discover something new.
Armed with all of this new information, I actually decided to start my game again from scratch, which although has cost me time and was somewhat painful, it will now ensure that my project is structured correctly and that all of my code is up to date with the new knowledge I have gained.
Another piece of ‘research’ I decided was needed was to play some platform games for inspiration. One of these was the first game I remember playing on my Dad’s ZX Spectrum 48k, which had only three buttons to control the main character, the simplicity of which I adore: Left, Right, Jump. Simple. Too many games these days have you clumsily looking down at your hands trying to remember what does what. None of that here.
One of the things that stands out most about Manic Miner (whether you like it or not!) is the pixel perfect jumps that have to be made to get from platform to platform and to avoid the numerous incredibly imaginative enemies. I would like some of what Matthew Smith was taking when he designed these games.
You collect all of the objects on the screen and make your way to the exit, where you are faced with a new screen and more objects.
The sequel, Jet Set Willy, had a more ‘open-world’ approach, and lets you explore a huge mansion (three times bigger than Manic Miners map) to collect objects at your leisure and in an order of your choosing. I was unsure at this point whether my game would be open world or screen by screen, but there would be plenty of time to decide this later.
Jet Set Willy and Manic Miner are both classic ZX Spectrum games which are fondly remembered by many people, so I decided that this is the kind of platform game I would like to create, although with a C64 twist to the graphics.
I have nothing against Spectrum graphics at all, they bring back lots of fond memories for me, and I love the very distinct bright colours. However, the style of graphics I wanted to aim for was something more along the lines of my favourite C64 titles, Creatures and Creatures 2.
These are both platform games made by Apex Computer Productions (John and Steve Rowlands), which I always remember for the Torture Screens, where you have to find a way of stopping the various devices from causing a grizzly end to your friends.
The graphics (and sound also) are seen as being some of the best the C64 has to offer, so I was setting the bar very high by aiming for this style, but I think the cartoony Creatures graphics along with the collecting and platforming of Jet Set Willy / Manic Miner would make a great combo.
The C64 has a bitmap graphics mode, and two different character modes (plus each of these is available in hi-res or multi-colour modes). For now, I decided to choose standard hi-res character mode, which is the mode that the C64 first boots up into. This would allow me to use characters (blocks of 8×8 pixels) to make up platforms on the screen and would serve nicely as a way to test getting my sprite lined up and colliding with them.
My first step into collision detection on the C64 was to calculate the row and column of the character directly underneath my sprites foot and place a solid block character there. This calculation is the sprites x or y position divided by 8 (the number of pixels in a character) minus the offset value of a sprite. The offset value is taken into account as a sprites ‘zero’ position (0,0) is actually within the border and not on the visible screen.
Once I had my block appearing in the right place (telling me that my calculations were correct), I debugged the remainder of the row and column calculations to the screen, to tell me how many pixels were remaining until the sprite hit the next character on the screen.
In the picture above, the digits in the top left tell me that my sprite is one pixel right and two pixels above the solid white block. Therefore, as there are 8 pixels in a character, if these numbers are not in the range of 0 to 7, I know that the sprite has crossed the border into another character and I need to increase or decrease the row or column number to find a different block.
The reason for finding this row and column under the sprites foot, is that I can then test which character is on the screen in this position, as well as the characters around my sprite for collision detection purposes.
With 256 characters available to output to the screen (0 to 255), I set a half-way point of character 128 to be a solid block that my sprite should not move through. So, by testing the characters around my sprite and checking if they are lower than 128, I know whether my sprite should keep moving or stop.
I placed some blocks around the edge of the screen and moved the sprite around with the joystick to check that it stopped in the right places. I was pretty chuffed to see that this was working, it wasn’t an easy task for a rusty machine language programmer to get this far!
The next step was to add some gravity (very important for a platform game), which involves checking if the sprite is directly on top of a solid character, and if not, to move the sprite down every frame until it was.
Of course, once the sprite had hit the bottom of the screen, it was stuck there and only able to move left and right. And so the real fun of creating this game really started, when I got to design a screen with some platforms on it.
This really allowed me to check that the sprite was dropping off the edges of the platforms at exactly the right moment, when the last pixel of the foot had left the edge – pixel perfect!
This was only fun for so long though, as the sprite was still getting stuck at the bottom of the screen with no way to get back up. Time for a jump routine.
The jump routine involves making sure that the sprite is stood on a solid platform and that the fire button has been pressed, before moving the sprite upwards every frame for a set distance, at which time the gravity routine kicks in and brings the sprite back down.
I decided that a 4 character height jump would be good for my sprite (just about the height of the sprite plus 1 character more). This is less than Miner Willy’s gravity defying jumps, but should make some fairly large gaps passable.
Something that now became apparent to me was that the sprite was moving up and down in a completely linear fashion, which looked quite jarring. After looking at some videos of platform games, I decided that I needed a jump ‘curve’. This involves slowing down the sprites movement the closer it gets to the apex of the jump, and once falling, accelerating again. It looks a lot better and more realistic than a linear jump pattern, and although took some figuring out was well worth the effort.
After much testing of my sprites new jumping and falling functions, it became clear to me that I now needed some different platform types. I already had solid platforms that the sprite couldn’t pass through, and background characters that the sprite would pass over, but what was needed now was a platform type that the sprite could stand on top of but also jump and walk through.
Jet Set Willy and Manic Miner also both had conveyors, collapsable and ‘death’ platform types (spikes and poisonous bushes etc), so I set this as my next goal.
I added some more character number comparisons into my collision detection routine:
000 - 063 Normal font (letters / numbers / punctuation, sprite will pass over) 064 - 127 Backgrounds (sprite will pass over) 128 - 143 Collapsing platforms (deteriorate and eventually disappear when stood on) 144 - 153 Conveyors (move the character left or right when stood on) 154 - 191 Semi solid platforms (can be stood on, but can jump and walk through) 192 - 239 Solid platforms (cannot pass through) 240 - 255 Death (spikes etc)
These new platform types really started to give the game some depth and a definite sense of fun and adventure.
My sprite was lacking some character though, as I had yet to add some animation to him.
CBM prg Studio has a great sprite editor with a built in animation function, which is really useful for testing and tweaking animation before adding it to the game.
I added four frames of walking and a jump frame for each direction, which really brought the sprite to life. Walking and jumping around the screen was now twice as much fun, and I spend a good amount of time testing at this point!
Something I now decided was essential was a C64 trick I had used previously in the Snake clone game I made. There is a register within the C64 that if changed at a specific time in the screen refresh cycle, it makes the top and bottom borders disappear, meaning that you now have lots more room for your sprites to move around in. For a platform game, this is very handy as you can now place platforms very high up on the screen and the sprites will still show (as opposed to disappearing into the border) when stood on them.
I now split my screen into three different areas by changing the border and background at points in the screen refresh, which gave the screen a much more ‘open’ feel. I now had an upper and lower play area, and an area at the very bottom where my status panel would show.
The reason for this was because I was about to attempt a technique that I was really not looking forward to due to its complexity – sprite multiplexing!