I guess making an 8-bit game is something I would have liked to do for a long time. Fort Django was started in 2014, and after a long pause I found the energy to make it into a release.
Djangooooooooohh....! |
You guide the character with a joystick in port 2. You can run, climb, crouch, jump and shoot. Shoot down the baddies, collect money bags and find the exit. The descending bonus timer means the faster you can collect the next bag the more $ you can get.
The game is very short and not at all hard. The only challenge comes from trying to be faster, for example it's possible to break the $10000 barrier on completion.
Get that bag, shoot that baddie |
Making of
I created the game with cc65 C compiler, using inline-assembler for speed critical parts such as the sprite routines. The C64 has eight sprites, eight 8-bit addresses for the horizontal coordinate (0-255) and one address that holds the highest bits for all the X coordinates, so the sprites can also reach the right hand part of the screen. (256-320)
For a beginner it can be a bit tricky to decode these 9-bit sprite coordinates, especially in pure assembler. I have eight separate 16-bit memory locations for storing the X coordinates. These are then broken down into the hardware sprite coordinate values. This approach is a compromise between ease of use and speed.
The figure below shows how the 16-bit X coordinates are stored in $C000/$C001, $C008/$C009, $C010/$C018 byte pairs (the grey stuff in the middle). The less significant byte of these 16-bit values can be copied directly to the $D000, $D002, $D004... but the high bit is taken from the lowest bit of the most significant byte of the 16-bit values and combined into a value that is stored in $D010.
This is done once in a frame, so the high-bit issue can be forgotten in other parts of the code. The handiness of this is only really apparent in C, where you can then move the sprite x coordinate around with:
*(unsigned*)0xc000=*(unsigned*)0xc000+1;
Comparisons between coordinates become easier, too. This checks if sprite 7 is right of the sprite 0:
if(*(unsigned*)0xc038>*(unsigned*)0xc000){do_stuff();}
Basically all the "collision detection" is built from this type of statements instead of the hardware sprite collision address, and as such is not pixel perfect. In these box-collision cases it's better to be lenient toward the player and a bit biased against the enemies.
The "16-bit" coordinate ought not to exceed 511, because only one bit is taken from the more significant byte.
The sprite Y coordinates are 8-bit values anyway and can be handled directly with the $D001, $D003, $D005... hardware addresses.
lda $C038
sta $D00E
lda $C030
sta $D00C
lda $C028
sta $D00A
lda $C020
sta $D008
lda $C018
sta $D006
lda $C010
sta $D004
lda $C008
sta $D002
lda $C000
sta $D000
lda $C039
clc
rol a
ora $C031
rol a
ora $C029
rol a
ora $C021
rol a
ora $C019
rol a
ora $C011
rol a
ora $C009
rol a
ora $C001
sta $D010
This is a starting point for a fairly generic solution, but of course it can be adapted for any particular needs. For example, the top sprite coordinates of the dudes in the game are copied and transformed from the bottom part coordinates, which changes the above routine a bit. Also, if less sprites are used why bother going through all the eight?
About the graphics
The graphics are made with PETSCII editor. Not only the background tiles, but the game map and even the sprites have been edited there. It goes to show that the PETSCII editor multiframe-editing is surprisingly powerful way for controlling this type of game "assets".
The game map tiles. |
The tile movement rules. @=space, A=block, B=platform, C=ladder |
The game map. |
Editing a multicolor sprite in PETSCII editor. The sprite export is not a standard feature! |
What next?
I dropped many game elements I toyed with at some point. For instance, the chests could have contained items, and the doors could have potentially led to other areas in the fort.
The gold bags were a fairly late addition when I felt that only shooting bad guys would be far too minimal. From adding the bags it was a small leap to increase the jumping elements in the game. The bags also inspired the time-based "bonus dollars" mechanic. Still there might have been a bit more to do.
Code-wise, a music routine would have been nice but in the beginning I was a bit scared to sync the animation with a music interrupt. The sound effects are also sparse due to my inexperience with SID.
Yet, all additions would have also expanded the complexity of the game and the testing time exponentially. I'm glad I could finish it as it is. With this experience I already have some ideas about how to approach this type of project better.
Links
You'll need a Commodore 64 or an emulator to play the game.
Fort Django v1.1 at CSDb
Read the blog post about the v1.1
1.0 (older version):
Direct download
Alternative link
Page at CSDb
A cracked version in a T64 format