17th September 2020
The previous code challenges I did on theC64 were quite a success and had me in a sort of comfort zone with a machine code monitor and Turbo Assembler, although I did come across some pitfalls - but I managed to get out of those quite easy enough.
A demo/intro was made in 2018 on theC64 Mini (See: C64 mini weekend dev challenge #1). A couple of games were made this year, using Turbo Assembler and a few PD utilities (Storm Chase, and The Forever Extending Hungry Snake) . I have decided to do just one last theC64 full size challenge for this year. This time, this challenge will be taking me outside of my comfort zone.
Killer Saucers is going to be an 8-level, 3 lives high score attack retro-style single screen shoot 'em up tailor made as what you would imagine a reader's game for a magazine cover tape would have looked like back in those days. Of course this game is not going to be an actual Power Pack tape. Just a standalone game which you will be able to download for free from my web site. The reason for why all of the levels are going to be single screen is due to the limitations of the assembler that was featured on the Power Pack tape. ;)
"Planet Earth is under attack by incoming flying saucers. Your mission is to guide your grounded vehicle and fire missiles at them. Beware though. the saucers can also fire missiles back towards you. You will have 1 minute to shoot as many Killer Saucers and 8 levels before they can kill you. For each level complete. The game will eventually get harder to play. After 2 levels, newer flying saucers will appear on screen. Although 8 levels. This is a high score attack challenge"
Back to the challenge:
The purpose of this challenge is also my part of celebrating the 30th anniversary of Commodore Format magazine. The magazine started in September 1990, and ended in September 1995. The memories about this magazine lives on. The main attraction for CF were the Power Pack cover tapes. Each month, at least 1 or more full games, and a few playable demos were added to the cover tapes. Occasionally, some exclusive non-commercial/commercial or Public Domain utilities were featured on the cover tape. So, for this final theC64 challenge. I have decided to work on a new C64 game using only the utilities that featured on the cover tapes - also pick out two or 3 useful utilities for other tasks such as compression, memory code movement and music.
The following programs I have chosen for theC64 challenge are as follows:
- FROST (Format's Really Original Sprite Thingy) - Power Pack 32 & 56 (Sprites)
- Font Editor V3 - Power Pack 38 (Character Set)
- 6510+ Assembler - Power Pack 45 (Programming and compiling)
- Code Suck Monitor (Preparation / moving / saving of sprites)
- A chosen music editor (Excluding Soundtracker 64 from Power Pack 57 - It is tough to handle) . My choice is likely to be DMC or Voicetracker/Music Mixer.
- A couple of compression tools (Most likely to be XTC V1.0 and Fast Cruel Cruncher again).
1. Frozen by FROST
I loaded up FROST on to my theC64 full size computer. This was from the original tape. I still had to wait for the clock to count down during loading. Brings back memories eh?. It started with a nice intro presentation with some Future Composer Music. Pressing Space goes directly to the editor.
I made a start with drawing the sprites with the editor. I drew a single frame for the player, for Killer Saucerz. Drawn up next was the player's bullet. I drew it like a missile with a flame at the bottom. The animation consists of 4 frames for that one. Thirdly I drew an explosion, which consists of 6 frames. Then came 4 different enemies using 4 frames. Finally was the enemy bullets. Although at the moment I class 4 aliens to be enough for such a small hi-score challenge game. There may be a chance of more alien saucer frames. This of course depends on memory free after compiling a complete game.The last 4 frames set are the saucers missiles (Basically a reversed version of the player's bullet).
I completed all of the sprites I needed so far. I went to the save menu to save to disk. Oops, I forgot to save the files to disk and utility was trying to save to tape. theC64 has no tape save function, so I pressed RUN/STOP and then tried saving the sprites to disk again (After changing the device). Also, as a just in-case scenario I selected MAKE DATA to generate a BASIC listing for all of the sprites that I made.
The DATA MAKER went in to BASIC and generated a big list of DATA lines. I saved all of those lines to disk. Then I loaded and listed the directory. It turned out that the version of FROST I used only saved a 1 block file to disk, and the BASIC listing successfully saved completely. Looks as if FROST had a bug. I think the version I used might have been from CF32.
2. Do the SPRITE thing
Because I reached a problem with saving the complete set of sprites. I needed to find an alternative solution to this problem. Scenario: I have hundreds of DATA lines in BASIC, I need to make it into a machine code generated DATA. How do I get to put the data to $2000, and how do I save it from the start to the end without an Action Replay Cartridge? A problem always has a solution. I had Code Suck Monitor installed on one of my disks. So I loaded that up. New the listing. Loaded up the sprite data lines and then created a BASIC listing to convert the data list into machine code data at $2000 - until the C64 ran out of DATA.
A simple solution was:
1 FOR X=8192 TO 12288:READ Y:POKE X,Y:NEXT X
Of course the ?OUT OF DATA error did spit out, but I only wanted the sprite data to convert to machine code until it reached the end of data.
I enter the Code Suck Monitor, examined the data using the M prompt until empty memory was found. The I saved the sprite data from $2000-$2500 (start of clean memory after running the BASIC listing)
3. Now Which Font?
Since I was very happy with my sprites. I decided to work on the character set for the game. I chose FONT EDITOR V3 for designing and creating the game graphics font. This is because the size of the font is pretty short, especially for 1x1 fonts. I only needed something basic for designing and creating the game's prototype background.
A few characters were drawn to form a road and also some buildings, as well as the text and numbers. Once I was happy, I saved the font ready for the next session.
4. Where's the Editor?
Because this is to be a theC64 challenge, and theC64 does have no Action Replay support for the reset/freezing. I didn't want to cheat by using other text/screen editors for the main graphics for this project. Instead, I am relying on coding. I loaded up the 6510+ assembler and I had to program my very own screen+colour capture routine. It first clears the screen and then runs on a BASIC input using JSR $A560. After the tap of the RETURN/ENTER key, the program stores the complete screen and colour data to $4000-$47e8. Where $4000-$43e8 is for colour data and $4400-$47e8 is for the screen data. The game and title screen hasn't been designed yet. There just wasn't enough time tonight. I decided to call it a day.
19th September 2020
1. The Designer's Pencil
The second day of this project. Last time on Thursday, I created my own little editor, and assembled it. I loaded up 6510+. Loaded up the character set and then I loaded up the SCRED.SRC assembly source. The file then was assembled and SYS49152 started the program. I was ready for the painstaking screen design. I have decided not to design the title screen at the moment since I will be leaving it until last. I moved the cursor around the screen, and prodded a few keys to design the game screen and colour data. Things were working out quite nicely with the screen game design. I drew the hi-res char city and street and score panel. Then I pushed Return to store the screen and colour of the game pic. I enter the machine code monitor in 6510+ and saved the game colour and screen RAM data to my virtual workdisk.
2. I like to Move It
I am not quite ready to code yet. I need to move some things around, like sprites. Add a test music, and a few other bits. I reset theC64 full size, into CBM Basic. Then I loaded up the CodeSuckMonitor. The problem is that 6510+ Assembler's M/C monitor didn't allow me to load my data to a specific load address. I loaded in the sprite memory to $2000-$3000, game screen data to $3000-$3800 and the game character set to $3800. Then I grabbed one of my old music pieces, Plasmatic from the DMC collection and added that to $1000. I then used the Code S Monitor to save all of the game data. Reason for this is because I will need use all of the game data for the main coding.
3. Know the Code
6510+ had to be loaded again. I loaded up the assembler, and started programming the main game code. The first thing I had to do was prepare the game screen. Then after that I setup the IRQ interrupts for the game, including a synchronized timer. During each coding session I had to play around a little with the routines. Since each command was being written on a basic numbered line (Like how it used to be back in the 1980's). I saved the source and assembled it. Once assembly was successful I loaded in the game data and then typed in SYS 16384 to run the program. The game screen displayed successfully, and it also played my old piece of music Plasmatic in the background.
4. Ready Player One
Since I was doing the code a bit at a time. The next stage was to setup and test the game sprites and their animation. I created a series of pointers to give each enemy its own animation. The player ship only has a single frame, but the saucers and other sprites all use 4 or more frames. I programmed a routine that would display all 8 sprites. I placed the player at the bottom of the screen. I saved the source code and loaded in the game data and tested the animation. It was working quite smoothly. I was pretty happy with the animation.
Now was the time to get the player setup for the project. The player was positioned at the bottom of the game screen but it could not move. That is because there was no particular code added to the player ship. So I worked on adding the code. The player should only move left or right. However it should also stop on the left and right parts of the screen. I added code that did exactly that, via a push of a joystick in port 2 (Since most games used that joystick port anyhow). I saved the code, assembled it, loaded the game data and then run it. The player moved quite smoothly.
5. Ready, Aim Fire
The player was moving pretty much well, but it could not fire at the moment. I loaded back in the code and then created a couple of routines. The first one was to check whether or not the player had already fired a bullet. The second one was whether or not the bullet was out of the screen. If the bullet was
out of the screen. The player was able to fire the bullet again. Also a routine was programmed to moved the bullet upwards. Then after the bullet leaves the screen it is positioned inside the border at the very left. If the bullet is at the very left of the screen, the player can fire the next bullet. Otherwise it has to wait for the next one. I saved the source, assembled it, loaded the game data and had a working bullet.
6. UFO sighting
After the player bullet was one more session before I called it a day. The Saucers need to be moving on screen. I programmed a subroutine that allowed to move one saucer. I got the saucer to move around the screen. I watched it move. I wasn't too happy with the saucer bouncing around the screen. I have another great idea for it, which I will be continuing with on day 3 of the project. I'll mention about it in the next day update. I saved all of the data and code that was made for the project so far, and made a backup of the project from USB to PC. It would be a shame to lose the project if a USB gets corrupt and a file becomes unrecoverable.
DAY 3 - I like to Move it Move It
23rd September 2020
TV was unsurprisingly rubbish and filled with soap operas as usual. So what better thing to do if you hate soaps than do a bit more coding on theC64. I made this session a slightly shorter session. This time it involved programming the enemy movements from scratch. I deleted the old movement routine for just one saucer and created a loop which reads speed X and speed Y of the enemies. This was because I had a better idea planned for this game. I wanted to use a similar mode as my loader game Mootilation originally did. The saucers can move across the screen, but if they spot the player's position, they can swoop down and try to capture the player. There is still not enough action yet, as the player cannot blast the aliens yet. Also the aliens cannot target the player yet either. More code on this on Saturday. ... stay tuned!
DAY 4 - Fire at will
26th September 2020
Yet another short session today. I've been a little bit clumsy, but the second session should hopefully take place sometime tomorrow morning. Today I loaded up theC64 full size and 6510+ assembler and loaded and assembled what I did last time. I noticed a small fault in the game data. The enemy bullet animation was just plain garbage. It seems that I didn't manage to recover the enemy bombs during generating of the data in day 1. I decided to load up the Faces Sprite Editor V1.3 to fix this issue (As the version of FROST I used had a bug in the save sprites function. After fixing the sprite data and saving. I reset theC64 and then use Code Suck Monitor to load in the game data, update the sprite data and save the game data again
The re-save of the game data was done. I loaded up the 6510+ assembler and loaded up the game source code. I assembled it, loaded up the game data and then SYS16384. The program did run, but there was still a glitch in the enemy bullet sprite animation. This time it was because the sprite animation table was one byte ahead. I corrected the issue, saved the code again and reassembled the source and loaded the game data and ran the program. It looked much better now. On to the next phase.
So I had the enemy saucers animate correctly, the player shooting but the enemies could not shoot. I decided to work on a subroutine that could do exactly that. Before I could do that though, I needed to check that the enemy bullet could only fire if it was out of the screen. Also I needed to pick which enemy could fire out the bullet. In order to do this I created some pointers that allowed the bullet to move down screen and once it reaches the bottom, it should go offset. A second pointer was used as the random selector. A subroutine was created in order to select the enemy that should fire the bullet. Then the enemy bullet was then positioned
on to the enemy object. Of course the bullet had to be checked to be offset first. I saved the code assembled it, loaded up the game data and then ran the program. Nice, enemies are dropping bombs.
The next stage had to be postponed because although I was doing the routine, I accidentally typed in NEW forgetting to save the source code, loaded up the game data and then run the program. The routine was a random enemy Y position for every time it reaches a certain outside position on the game screen. I will be working on this trick tomorrow. ... Stay tuned!
27th September 2020
Yesterday I successfully had enemies firing. Today I worked on the collision read routine, and setting up the level tables. Each level tables was based on the enemy type, speed and number of shots to kill it. I also added a test collision routine for the player vs enemy. I saved all of the code like normal, and assembled the program. The assembled code was going to overwrite the source code. Looks as if memory is low here. I assembled the source and overwritten the listing. Typed in NEW I loaded in the game data and then typed in SYS16384. The assembler froze. The program didn't run. it was a complete FAIL.
So is it the end of the challenge resulting to a fail? No, because all I had to do was move the code to a different part in memory where it could not overwrite the listing and corrupt the project. I moved the assembled game code to $6000. It has not reached $7000 so that's quite good. I still have enough memory to finish the main game code. The title screen will be coded separately.
4th October 2020
First off, I was running a bit low in memory, but I noticed I created too many data tables for levels, etc. I don't really need those at the moment. So I deleted them to make more space for some more code. 6510+ assembler is memory restricted. I continued with the sprite/sprite collision routines this time. Last week the sprite/sprite collision routines only flashed the border if the player was hit by an enemy bullet, or if the player bullet hit an enemy. The collision felt very raw.
I added some more routines that could animate the explosion frame on to the player, and also bullet objects. This should only take effect if the object hits an enemy or bullet. The enemy bullet is indestructible by the player's bullet. So in a more common sense kind of way, the bullet sprite should explode before it leaves the screen after shooting an enemy. The player should also explode, before losing a life. I also added routines that zero-positioned enemy vertical position as soon as they have been shot by the players bullet.
I saved the source code, assembled and loaded the game data and then type in SYS $6000 to test the new source code. It seems to be working quite nicely, but I have noticed a bug in the code. The enemies were shooting their bullets, like they should have done. However when zero positioned. You could see bullets firing from the enemies that were killed. This is not how the game is supposed to work. I loaded back the code and then edited the listing so that if the enemy vertical position is 0, no bullet can be fired. I saved the source, assembled and executed the game code and then loaded in the game data. I then run the code, and it was working much better.
So now I have a fully working game engine, with full sprite animation, working collision detection and enemy bullet firing. Great.... but the project is not quite finished yet. The next stage (which will be in the next update to this blog/diary) will be something hectic and crazy. I aim to give the passing enemies some kind of crazy behaviour, when they spot the player in their sight.
6th October 2020
As mentioned on Sunday. This evening I wanted to code a feature which allows the saucers to kamikaze towards the player when detected. Before I did that, I fixed the player's re-spawn after death animation. The last frame of the player explosion was stuck. So I needed to sort that issue out. Next I worked on the kamikaze saucers routine. This was where flying saucers charge for the player, if the saucers are in range of the player ship. The routine worked for all of the enemy flying saucers, however there was still an issue. The enemy saucers charge towards the player constantly. The routine needed a timer. I created a timer, and I had the enemies charging towards the player on position - only if the timer has elapsed and reset. This made the kamikaze saucer routine much fairer, but there are still bugs in the routine. I tried to prevent the saucers from charging towards the player when offset. Hopefully on day 7 of this little project I should be able to sort this out.
11th October 2020
Just a load of random stuff
Today's session on this project has been pretty much a very long session. The first part was basically fixing the kamikaze aliens routine. The routine required being timed before an enemy could try and detect the place and then charge for it.
After fixing the kamikaze routine. I did a fix-up of the enemy firing routine. First of all, the enemy firing was too rapid. Not only that. There was a case where aliens could fire when at zero position. So I decided to add some code which allowed the enemy to only shoot after a wait duration timer has reached a certain point, also check whether or not the alien was on screen or not. Then the enemy should fire a bullet.
Once that was fixed it was time to spawn random enemy types, colour and speed. The random position for each sprite was also read. I had to create some more pointers and expand the table of bytes. This was so that every time an enemy leaves the screen, or is shot, or kills the player. A new enemy comes out of the screen with a new colour, frame and starting position. Once I was happy with the result it was time to update the enemy to bullet collision.
The enemy to bullet collision originally cycled the border colour to indiicate an enemy has been shot down. That was not really how the game should operate. The enemy short should add a number of points to the score. So I generated a few pointers. This is because scoring points should vary on the enemy type. There are 4 different enemy types. The scoring system should work like this:
Enemy type 1 = 100 points
Enemy type 2 = 200 points
Enemy type 3 = 300 points
Enemy type 4 = 500 points
The low byte of the enemy's animation got stored into a new pointer called scorezone and then when calling the score routine, the scorezone code checked for the enemy type low byte value and then jumps to one of the scoring subroutines that added up the correct scoring amount.
I saved the updated source code, assembled the source code, I loaded in the game data and then started the game code. The game is starting to look quite promising, despite the ugly game background graphics, and a few minor bugs. Those will be fixed in the next session. Then hopefully once those bugs have been fixed. It is time for setting up the concept, game level tables, etc. This is shaping up quite nicely.
Due to the limitations of the 6510+ assembler this game is going to feel like one of these book/magazine type in games - but not in BASIC (Fnar!) :P . I will of course, try my best to make a quality release out of this game, after the code is finished.
All game data and final source will be provided, along with the 6510+ assembler I used (Which you can explore if you want).