Part Three: The Joy of Plex
Things have been progressing well with my Commodore 64 platform game since part two, and I have now put together a trailer showing the first two areas of the game.
Before I begin retelling my joyous experiences of learning C64 sprite multiplexing, I’d like to show a couple of screenshots that show the origins of Bear, who actually started life in Unity 3D.
I had numerous attempts at making a platform game in Unity, with the goal then to be able to publish it to numerous platforms (probably starting with iOS). However, I found it difficult to get the pixel perfect platforming I was aiming for, and I struggled to make graphics assets that would suit the game I had in mind. In the end, I gave up on the idea, and Bear sat untouched for a good long while.
I’m really glad that I decided to get my C64 out of the loft and set it up. This is what sparked the idea of making Bear into a C64 sprite, and attempting to make my platform game again. I’m surprised that the restrictions of working with a C64 has helped to bring the game to life, and that I found it much easier to create graphics with a 16 colour limit and a low resolution. Something to Bear in mind if I ever attempt to make the game in Unity again!
Speaking of restrictions, one quite large restriction on the Commodore 64, is that it only has eight hardware sprites available to use, which looking on the bright side, is more than enough for some games. In fact, the first two games I made for the C64 didn’t even use sprites in the main game, and were just used to show things like the game logo and score, and everything else was built from screen characters. Some games require many more than the eight available sprites though, and so a technique called sprite multiplexing is needed to allow this.
This technique takes advantage of the register which tracks where the screen refresh is currently happening, and re-uses sprites that have already been displayed by moving them down the screen underneath the refresh so that they are drawn again, giving the impression that there are actually more than eight sprites.
This is quite a commonly used technique on the C64, one famous example is of the massive ‘fist’ boss in Turrican.
The fist is made up of rows of sprites that are reused again and again to make one very impressive giant enemy!
There are very helpful sprite multiplexing code examples (along with lots of other great resources) over at Codebase 64: http://www.codebase64.org
However, me being me, I wanted to have a go at writing a multiplexing routine myself. Some of the more complex routines actually sort the sprites for you, so that the upper eight sprites are displayed first, then the next eight, and the next eight, without the user having to worry about the order of them when they are being moved around the screen.
As this was my first attempt at such things, I decided to go for a slightly simpler approach.
I had already split my game screen into three horizontal zones. The lowest black area contains eight sprites that are located in the bottom border (the top and bottom borders have been ‘opened’ so they no longer display – see part two). These eight sprites make up the display panel for the game to show lives, objects collected and the games logo.
The upper light blue and middle dark blue zones each show three collectables (apples) and four enemies (the ‘sphere’ type sprites – which are just placeholder for now) which makes seven sprites for each of these areas. These sprites will not move from their zones. The remaining eighth sprite in each zone is for Bear, who will move between the two zones.
By keeping most of the sprites in their designated zones, this simplifies the code needed for multiplexing a fair bit. It will restrict the movement of the enemy sprites, especially the ones that may move up / down, but I can always use two sprites for these enemies (one from each zone), which will be synchronised so they pass between the zones without any glitches.
Using this method gives me a total of six collectables and eight enemies per room, and in total I am displaying 23 sprites on the screen at once, which is a pretty satisfying achievement!
Although simplified, this was still one of the hardest parts of the game to develop so far. It took much head scratching and diagram drawing to get my brain around it all, and I was very relieved when it was all working properly! It really is a very useful technique to use on the C64, and can yield some jaw dropping results, as shown by the earlier Turrican example, and this massive boss from Creatures 2:
The next part of the game I decided needed to be added was sprite to sprite collision detection. I already had the Bear sprite colliding with platforms, but now he needed to be able to collide with the collectables so he can collect them, and of course the enemies.
Some C64 games use ‘bounding boxes’ to detect whether they have collided (similar to the technique I used to detect if Bear was on a platform). This checks the co-ordinates of the other sprites to see whether any have entered a box-shape area around the main sprite. This is a good technique to use, but does not detect collisions in a pixel perfect way as most sprites are not perfectly square!
I decided to take advantage of the C64’s sprite to sprite collision register. This register has a ‘bit’ assigned to every sprite, which changes when the sprite has collided with another sprite. So by checking which bits have changed, you can see which sprites are currently involved in a collision.
This can get complicated if three or more sprites have collided (possibly in two or more collisions!) but I decided that if I make sure that no enemies come into contact with each other, and no enemies touch any of the collectables, then it should be easy to see if Bear has touched a collectable or an enemy, which is the only two collisions I am interested in for this game.
Of course, the fact that I am using more than eight sprites complicates things further, but a check for collisions at the end of each of my horizontal zones gives me the collision information I need. To test the collisions, I made the collectables turn off when touched by Bear, and the border flash when he was touching an enemy.
One more thing needed to be added to my game before I could start designing lots of rooms: Procedural room drawing.
In standard character mode, the C64 screen is made up of 40 x 25 characters (made up of 8 x 8 pixels). Each character that makes up the screen takes up 1 byte, and then another byte is needed for the colour of the character. So, for a full screen of characters you need 1,000 bytes (40 x 25) and another 1,000 bytes for the colour, which equals 2k.
If the rooms in a game are stored in this way, given that the C64 has 64k of memory, this means that only around 30 rooms could be included! And that is without the code and other graphics needed for the game. Of course, you could get around this with a multi-load game (which I am trying to avoid), but there are other more efficient ways to deal with the problem.
Screens could be compressed before being stored into memory, and then decompressed and copied to the screen only when required.
Tile based systems are also a popular way of dealing with the problem, where the rooms are made up of references to ‘tiles’ of characters. If the tiles were made up of 2 x 2 characters, this halves the amount of memory needed to store a room. If the rooms are then compressed as well, this reduces the amount of memory needed again.
The approach I decided to take, was to store the rooms as a series of platforms and walls. The code I use to draw rooms from this information is changing all the time, as I find I need differently constructed rooms for each area, but the principal stays the same.
To draw a room with one vertical wall and one horizontal platform, all you really need to draw those two objects is three numbers for each:
– X and Y co-ordinates of the start of the object
– Length of the object
This means that the room can be stored as six bytes!
Obviously, this is not a very complicated room, and the more platforms and walls a room has, the more memory needed to store it, but this is still an improvement.
To give more flexibility to my room drawing routine, I actually added an extra two bytes for each object so the colour and type of platform can be chosen too. This will allow for lots more variation in the way that the rooms look – very important when aiming for a large number of rooms in the game to keep players interested!
To give the rooms some more character, I added some background graphics. These will be re-used throughout the game, and will be compressed when stored to save on memory. I also added some code to detect when Bear has hit the the left or right edge of the screen, so I knew when to switch to the next room. The game really felt like it was taking shape at this point, as I was able to start exploring the rooms in Bear’s world!
Designing rooms can be a very fun process, as you get to let your brain run riot, but it does require a lot of creativity, so can become tiring when there are lots of rooms to create.
It’s also very tiring when you discover yourself as a perfectionist who can’t stop fiddling with room designs until 100% satisfied with them!!
I’ll leave you with some screenshots which show the development of the first room I designed for the game (which eventually got moved to later on in the game due to the difficulty). Bear in mind these screenshots were taken over several weeks, which just goes to show the amount of time before I was happy with it!