E-Mail PeteBack to Home Page


Time Pilot '95

During 1995 in my spare time, I embarked on a game design project on my Amiga computer using a language called Blitz Basic from Acid Software. The game was a clone of one of my favourite 'old school' arcade games, 'Time Pilot'. At the time of writing the game, I tried to locate one of these classic machines but there were none to be found - such is progress. Undeterred, I proceeded to program the game anyway - from memory!

During the development, I purchased a PC and got myself hooked up to the 'net and at that point the project came to an abrupt end. The floppies containing the unfinished source code were destined to become attic box filler, however I still have the machine and one day I may finish the game - for old times sake.

Diary of a Game

While I was developing Time Pilot, I kept a diary of the progress. This is the first time I have kept a diary of the development of a program, I guess I thought it would be interesting to read it a few years later - like now. Here is the diary in it's unfinished entirety, I must stress that the writing style is intentionally very informal - it is customary for games programmers to write in this style - probably.


Sun 29th Jan (New Beginnings)

After almost 6 months of bugger all, finally started work on the new mega Time Pilot game engine. The old logic used dual playfields for the parallax bitmap cloud scrolling and therefore had to use the CPU intensive "buffer blit" command for the objects. The new routines eliminate scrolling and dual playfields, and instead use one single non-scrolling blank bitmap which I hope will increase speed. Also, after some late-night experimenting in the lab, I found that it was quicker to Blit without queues and use CLS, then it was to use Qblit. As there are no "drawn" backdrops, this looks like an ideal speed technique. I will replace the scrolling cloud backdrop with blitted cloud objects which is a bit of an overhead but it should be worth it. Final tests proved that this technique is far better than the old routines from my previous effort. This engine can shift thirty two objects in around a third of a frame! I just hope it still fits in a frame with the extra game logic.

Mon 30th Jan (Scheduling Frames)

Today saw the introduction of the frame time scheduler which shares frames between four different logic routines. As with the first version, timeslot one was assigned to joystick control thus providing the ideal 4-frame rotation speed. The joystick code was ported direct from version one - cheers to my team at work for thrashing though the rotation algorithm, especially Dave (Blackpool) Hewison who perfected the final result. I assigned timeslot two to the object intelligence/animation routine ( ). This routine itself cycles though the objects and only processes one each time it is called. It has the job of deciding whether to change an objects direction, or animation image. There would never be enough frame time on an A500 to process all objects in this manner hence the cycling technique.

Thu 2nd Feb (Main Blitting Routines)

After a two day drinking break, most of today was spent building on the main control routine. I have extended the bitmap at the top and left sides such that the objects scroll off the sides instead of suddenly disappearing. This problem is also solved on the bottom and right hand sides simply by using the "ClipBlit" command (careful how you say it). Decided to port the level one sprites and shapes file over to the new game to see how it looks with graphics, and it's not half bad. The object handler which animates each graphic now gets called 25 times a second using timeslots one and three, as does the joystick handler (I decided that every fourth frame was slightly too sluggish after all). All I need now is the bullet, collision and title screen routines to be back at the point I was at with the last release !

Fri 3rd Feb (Bad House Music)

No work on the game today, but did have to design a new IBM mainframe stock despatch module for the company. Spent the evening relaxing to extremely loud House and Garage music at the Prince of Wales (aka Sloanes of Chigwell).

Sat 4th Feb (Titles and Graphics)

Okay, today I take a break from coding the game and concentrate on the title screen and game graphics. Firstly the game graphics, these are drawn into set size boxes using Dpaint, and then turned into a shapes file using a small Blitz program. The Level 1 graphics from version 1 are okay and I can make use of them after a bit of tuning with the shape boxes. I have also added the graphics for the three sizes of cloud and the enemy bomb for level 1. Secondly, the title screen which was in 32 colours on the first version has had to be stripped down to just 8. Surprisingly, after loads of blood, sweat and graphics rejigging, this still doesn't look too bad. Also today saw the introduction of collision detection which as I remembered it before, is a right bastard. The central ship is a sprite and the adversaries are blitter objects (bobs) so the first attempt was using "SetCollHi" which detects for bitmap colour collision. The first thing about collision is that it must be done each frame, for each object - I think, so in it goes.

Problem 1 - when one object collides, unless it is removed from the screen immediately, all subsequent plots will also register the same collision - major bummer. Technique two - using "ShapeSpriteHit" which allows me to specify which objects to detect for. This seems to work, except for two major flaws which will render the game crap. Firstly the detection is rectangular, so a near miss is usually registered as a hit and secondly, the bleedin' rectangles are huge - much bigger than the object sizes themselves. I haven't got the patience to fart around at this point so here goes technique three - "RecsHit" (This must be said very carefully). This allows two arbitrary rectangles to be detected. I have amended the rectangular detection area such that it lies just within the actual object image and not outside it. This gives better detection and also favours slightly in the players advantage. In the end I think the rectangular detection size will have to be part of the objects newtype variable so that I can vary it.

Sun 5th Feb (Sprites and Text Control)

Still on graphics, I now simply want to colour the main sprite to my liking (previously it was using the default Blitz colours). This relatively simple task has taken around two hours. The problems were because I am using a three bitplane bitmap which allows eight colours. I therefore assumed to have 8 colours on the slice command but, oh no I need 32 colours to allow for the sprites which use palette numbers 17 onwards. Fine, change the slice to use 32 colours, no problem except the bitmap offset has shifted right about 200 pixels - gaaaah! The left border now appears in the centre of the screen, immediately to the right of the right border! Alas, I couldn't be arsed to work out why so I just amended the offset on the "Show" command to bring it back in line. So much for sprites being independent from the rest of the display! In the evening, added the text control routines to the title screen. This reads data, converts each character to an object number and "BBlits" the object on screen (I am using BBlit to restore the image after each page). Also included the joystick selection for players and the fire button start routines. I have also added constant colour fading in/out for the two blue colours and a clock routine which wipes between displays using a very rapid second hand movement. The clock by the way, simply draws lines from the centre to the various points on the perimeter. The colour used is dynamically modified from the current palette (via RGB) to match the background of the next screen. Enough for today I think.

Mon 6th Feb (Titles Screen Options)

Title screen only today - worked out what to blit on the screen in terms of text content. I decided to have very rapidly changing text which prompts the player to hit fire to expand on the subject in question (Instructions, Scoring, Credits, etc.). Hopefully this will look better when I add some music. I also scheduled a "Todays High Score" and an "All Time Great" table into the title sequences, although the entries are purely fixed at the moment (The idea is that the all time best will load in from disk). Finally for today, added the credits text which include some of the places and people which have helped make the development of the game slightly easier, indirectly, if not directly. 'Nuff said.

Tue 7th Feb (Fine Boozers)

No work today due to other commitments (i.e. Chigwells fine boozer - The Kings Head)

Wed 8th Feb (The First Demo Version)

Steve (a fellow IBM mainframe and Blitz guru) is pushing me for a review copy of the game already. The sooner I can get input from other people, the better, so I cobbled a decent version together for him. This "cobble 2-a" version included a more complete intro. screen with scoring details and instructions on how to play. At this time I am not happy with the title screen appearance and control mechanism, but it will do for the moment. A problem has suddenly occurred to me with the title screen. When the clock routine sweeps around the screen, it is in fact obliterating the image underneath. This means that it will have to be reloaded when the game is finished, and loading is one thing I must keep to an absolute minimum. To get around this I added another bitmap to store a copy of the title screen when it is initially loaded. The copy can then be used to restore the overwritten image using the "CopyBitmap" command. Ping! - another idea - there is no point in Bblitting letters to the title screen anymore. The image can now be restored using the CopyBitmap command thus saving the 30K memory used for the blit buffer.

Now that's what I call music - or lack of it. Things are a bit quiet on the sound front at the moment and I think the title screen is in need of a Med module. While bored one evening (I think the pub must have been shut or something), I sampled and resequenced a version of "Nightcrawlers - Push the feeling on". While this sound real cool, it eats up a massive 350K of chip memory. As we all have loads of RAM I thought "350K pah" and stuck it the demo version anyway at which point another bleedin' problem arises. No matter where I stick the "PlayMed" command in the loop, because the CopyBitmap takes close to a frame to execute, the module slows down when it happens. After a bit of trial and error, I found that the music could be given priority by coding the PlayMed as an interrupt using the "SetInt 5" command.

Thu 9th Feb (Bowling Day)

Give review copy to Steve. No progress tonight due to Ten Pin Bowling.

Fri 10th Feb (Scores, Loops and Prints)

Steve reckons the game looks pretty good so far which is encouraging but he has had to amend the code. Apparently there is a problem with the Clipblit command running on his A1200 with Blitz 1.9. The background colour, which is supposed to be transparent is overwriting objects underneath. As I don't have this problem with Blitz 1.7, asked Steve to supply Blitz 1.9 so I could try it on my A500 plus. Unfortunately I don't own a printer at home so I have to scrounge other peoples. It is always a good idea to get printed copies of source - coz its much easier to read and understand.

Today I am using the IBM mainframe continuous forms laser printer (a beast the size of a wardrobe) to print the source for Steve's Rash Panic and Acid's very own Defender. The print process is not without its problems, so here's how to transfer Amiga files to an IBM system 370 VM/SP mainframe. First mount multidos (or crossdos) so that the Amiga can write PC disks, then save the file in text (or ascii) format to the PC disk (this expands the Blitz tokens to full words). Next (and here's the hard part) file transfer the text file from PC disk (using an IBM 3270 terminal emulator connected to a mainframe CMS virtual machine) onto the CMS A disk using the ASCII CRLF options. This transfers the ASCII file into an EBCDIC CMS file segmented into 80 character records. Next write a REXX program to read the file and split the lines at each carriage return (Hex 25) character. Now read the split file and remove superfluous Blitz tokens (Hex 27 and 94). Also, because there is no EBCDIC equivalent of square brackets we have to do a fix by converting Hex B1 into "(" and Hex BB into ")" to mimic the brackets. You can now print the file - and that's all there is to it !.

The newtype variable for the objects seems to be growing at a healthy pace at the moment, the latest addition being a flag to inhibit object plotting. Previously I did this by setting the coordinates to 0 0, which is off the screen but moving right and thus scrolling right makes them visible again, a slight oversight I think. Scores had always been visible above the main screen using a separate 8 pixel high slice, but were static. Today I coded in the score update routine which, for ease of use, is drawn using the "Print" command. Print is very CPU intensive, so this routine only gets called every second frame when the joystick gets read (The joystick frames have more spare CPU kick than the object handler frames). The score colour will alternate (using a counter) between yellow and background blue to create a flashing effect for the active score. The final addition for today is a main control routine which will loop between the game and the title screen forever - or at least until Escape is pressed. So hitting escape once will return to the title screen, and again will exit the game completely (Escape is the most commonly expected exit key).

Sat 11th Feb (Static Bullets)

Not much today. I had planned from the start that I would use sprites for the players ship and the ships bullets. Today I added the bullets onto the screen (static bullets that is). It's pencil and paper time again as I begin to work out the bullet start positions for each frame of ship rotation and code them into the bullet newtype variable.

Sun 12th Feb (Blitz 1.9 Horrors)

Got Blitz 1.9 from Steve today, fired it up, loaded Time Pilot, compiled it, waited for the data to load and... horror of horrors what a load of bollocks. Graphics were being splattered all over the place, and the game was really struggling, missing frames all over the place thanks to the new intuition-style debugger. Promptly reverted back to Blitz 1.7 for the duration of the development - at least I know where I am with it. Also saw Star Trek Generations in THX at the Empire Leicester Square

Mon 13th Feb (Bullets and Collisions)

Time to get the bullets working properly. I am worried at his point because both the plotting and collision detection for three bullets will have to go in the main loop every frame. Bearing in mind that there are 16 objects and four sprites (1 ship plus 3 bullets), that makes a total of 64 detections and 20 plots for each and every 1/50th of a second. Seems like a lot to ask, and indeed the game misses the frame time, but when you switch off the debugger the thing still runs in half a bleedin' frame. All works pretty damn well for a first attempt, and with the score incrementing for each hit you can actually play the game. To wind down today, I started fiddling with copper colour bars on the title screen. The copper commands allow the palette to be modified at various point in the display and thus create more colours than the 8 available.

Wed 15th Feb (Well Flash Scoring)

A short while ago (The back end of 1983 to be exact) I wrote a VIC 20 breakout-style game called "Deflexor" which got published in Home Computing Weekly. This game had a neat effect which made the score disappear and then reappear, digit by digit. I liked this and wanted to use it again so I promptly stuck it in (and the effect!). I am also going to keep the original flashing score effect and to add the icing on the cake, the display will alternate between the two styles. You may think that this is a bit extreme but it all adds up to better, and more interesting presentation.

Thu 16th Feb (Years)

The game involves battling against enemy craft of various eras and to remain true to the arcade original, I wanted to display the year appropriate to each level. To keep the main game routine as lean as possible, I added another loop which simply displays the year on the screen as well as calling the object scrolling routine and score plotting routines. This routine will be called at the beginning of each level until the player hits fire (allowing a tea, piss, shit or whatever break, if required). A big problem has arisen at this point which needs much thought. The year display routine is running very fast compared to the game itself and after a bit of investigation I realised that the game is actually taking two frames to execute. Although the two frame speed is still very reasonable (I didn't even notice it before), I need to decide whether to stick with two frames, or attempt to crunch the code to fit in one frame. A mighty decision indeed! Also fixed two bugs with the bullets today. The first one stops a parachutist from being blown up and was fixed by setting the object collision detect variable to 2. This will ignore bullet collisions while still allowing player (pick up) collisions. The second bug involved removing the bullets from the play area once they has reached the edge. I still don't know how to remove a sprite from the screen so I bodged it by re-positioning the bullets in a safe place "underneath" the players ship. From this position they can't cause explosions and are (very almost nearly) invisible.

Fri 19th Feb (Quiz Night)

No work today, went to a quiz night with the geezers from work.

Sat 18th Feb (Copper Pipes and Bitmaps)

The mighty decision has been made - for the time being anyway. I now realise that clearing the bitmap every frame using CLS is a really stupid thing to do because CLS is a s-l-o-w process. After ripping out the code and replacing it with the "Qblit" queuing system, the game ran significantly faster. This increased speed has encouraged me to try and get the game running in one frame. The CLS command slowed down in relation to the bitmap size and this was a restricting factor. Now that the CLS has been removed, I can increase the bitmap to allow the larger objects (such as clouds) to scroll completely off the sides of the screen before wrapping around. The result is fabby, but the bitmap size increase was not without it's Blitz quirks. Apparently the bitmap horizontal size has to be specified in multiples of 16 pixels - something which I couldn't find reference to in the manual. More quirks later on - this time with the Qwrap command. I think there is a problem when the result of the expression is so high over the maximum limit that it would still exceed the maximum once it has been Qwrapped. Finished off today by adding purple copper bar shading onto the title screen text. This is good when you have a restricted palette of eight colours, because the shading can utilise all 15 shades of colour.

Sun 19th Feb (Plotting Routines)

Up until now, the level started with maximum enemies which disappeared for good once hit. While this is ideal for a game such as Space Invaders, it is not the case with this game. I need to devise a method of re-incarnating enemies on screen once they have been destroyed (The game runs on a time limit you see). This will be processed in two stages in the actual game logic. Stage one involves adding a small routine which is scheduled in the joystick handler. This routine will activate after a fixed delay, examine how many objects are "free" and set an "add object" variable to a random value from 1 to 3. In the main loop, when a deactivated object is found, the second plotting stage will add an enemy if the "add object" variable is set, and then decrement the variable. Now that this logic is in place, I can start the level with a blank object table and have the objects allocated after a short delay by the new routines. Did I mention that, at this stage the enemy planes start at random positions around the perimeter and fly in random directions ?

Mon 20th Feb (Players and Lives)

I had three tasks to do today: 1 - add players and lives, 2 - add the explosion routine for your ship and 3 - find a suitable background wind noise for the game. Unfortunately, the first one took up so much sweat that I had to leave the others. I encased the entire game logic in another loop which had the job of cycling through the players and picking out the next one with lives greater than zero. Once all the players had zero lives, the loop terminates and returns control back to the mega parent loop which redisplays the title screen. Notice that these loops avoid the need for the GOTO command which is widely regarded as causing unstructured or "spaghetti" programming. Anyway, the routines work fine and include a clock wipe to the colour of the next players current level.

Tue 21st Feb (Pub Time)

Arrived at the pub at 10.00 and left at 2.00am. Needless to say that not much was achieved today.

Wed 22nd Feb (More Explosions)

Up 'til now, your ship has been invincible, but that would have made the game a tad too easy so today I added the explosion routine. As the ship is a sprite, I will use the same sprite channel and just cycle through a number of explosion images. Sprite images need to be either 4 or 16 colours and as the game bitmaps are 8 colour, the bitmap explosions have to be redrawn in Dpaint in 4 colour mode. What I have done is have an 8 colour Dpaint image which contains the bitmap objects, and another 4 colour one for the sprite objects. The sprite palette is not important because the sprite colours will dynamically change in the game. Okay what happens now when you collide is that a flag is set which switches out the joystick routine and actions an explosion routine instead. I have added a small counter so that the explosion happens at the right speed and at the end, control is returned to the player loop for the next player. The sprite being only four colours, has to change from the pea-green ship to a red and orange explosion and this is easily achieved by altering the RGB values of the sprite before and after the explosion. Did I mention earlier that the game is currently running in a frame (on level 1 anyway)? Well it is, and because of this the frame scheduler has to change slightly. Actually this is working out really well at the moment because I have in fact killed three birds with one big boulder. The main frame scheduler shares frames between four routines - these being joystick, objects, joystick again and parachutists. Because the game was running every other frame , the joystick was being read every fourth frame which is ideal. However now that the game runs every frame, the ship rotation is too fast. The simple solution is to replace the first scheduled joystick call with a dummy routine so that we get back to the original 4th frame read. Instantly I have a spare schedule slot in which to place any code I wish to dream up without degrading the game speed. In itself this is a corker, but there's more.... The firing routine was also being actioned too fast (ie. the gap between bullets was too close for comfort) and since I reduced the joystick reads, its absolutely perfect now!

Thu 23rd Feb (Bowling)

No work today due to ten pin bowling where, incidentally, I came first out of five.

Fri 24th Feb (Time Bombs)

Each level runs on a time limit. At the end of each time limit, the large end-of-level ship appears and once destroyed, the level is complete. Following on in the age-old tradition of timer bars, the timer is displayed in - guess what - a bar which decreases in length until it disappears completely. As well as depicting the time more graphically than a number, it is also faster to update in CPU terms, than numbers. The bar is decremented simply by drawing a line over the last pixel, in the background colour, and then decreasing the x-co-ordinate by 1. As in the original arcade version, the timer bar will be depicted as a series of mini enemy ships instead of a solid rectangular bar, but unlike the original the bar will be located top right instead of bottom right. I think another one of those Blitz quirks may have influenced by decision on the timer location because no matter how hard I tried I could not get Blitz to display a slice lower than 255 pixels down the screen. In any case, having an additional slice, albeit only an eight pixel one, would have slowed the game down a treat, so maybe it's for the best after all. Oh yes, I stuck in the logic which allows an enemy ship to launch a bomb. This is scheduled every so many frames so that there is only ever one bomb being processed at any one time, and there is a suitable gap between each one. The bombs, which look like barrels full of Orangeboom, are launched upwards initially and then arc around - a la gravity style, until they end up falling downwards at a fair rate of knots. The problem with this game is that you never know whether you are viewing the game sideways on or from above, but the bombs fall towards the bottom of the screen, after all it's only a bleedin' video game. Intelligence for the bombs was fairly straight forward to implement. The bombs change direction via a table of vectors which is sequentially processed during the bombs voyage - sod all that sine wave stuff, I was never any good at that. They collide using the same logic as the enemy planes which avoids extra coding, but new code was required to deactivate them once they had disappeared off the bottom of the screen. You can't have your cake and eat it as they say.

Sat 25th Feb (Sound Advice)

I like to work on different aspects of the game very frequently, mainly 'coz I get bored easily. Today I thought I would have a go as improving the sonics contained within the game. Now then, sound is definitely as area where I think I have the edge. The kit I am using contains a 12 stereo channel mixer (that's 24 mono channels) which is the best investment I ever made (Only 200 quid at Tandy). The mixer currently has two A500 input channels (One with L-R reversed), one CD32 input, one PC Soundblaster input and one audio CD input. The headphone monitor output is fed into the A500 plus via a Stereomaster sampler cartridge, and I have an Action Replay brick stuck in the side also. I really only use the Action Replay for stripping out modules and samples from other software, for further manipulation. A lot of PD stuff such as Blitz's Defender, PD Asteroids (The good one), and more recently, a blinding Pac Man clone called "Puc Man" which graced the cover of one or two Amiga mags actually feature samples taken from the arcade originals. This really does bring the game to life, but after searching high and low (Southend, London West End, Yarmouth, Blackpool), do you think I could find an original Time Pilot - not on your nelly. Armed with my memorised sounds of the past and the Action Replay, I started scanning tons of coverdisk software for the nearest substitute sounds and, slowly but surely, built up a TP sound portfolio. A few sound tips, firstly get Octamed and secondly get Audiomaster. I experienced crashes in Blitz when running "Tracker" modules, probably due to the interrupts or something, so I tend to use "Med" modules taken from Octamed which work perfectly, but make sure the Octamed module speed is set to 6/33. Modules saved from the Action Replay cartridge are in Tracker format, so they need to be loaded into Octamed and saved straight back out again in Med format. Samples saved out from Octamed on the other hand, may not work in Blitz so these need to be loaded into another package such as Audiomaster and then saved straight back out again. Don't worry, this sort of thing is common on all platforms, on the PC for example to convert Quattro Pro v4 spreadsheets to Microsoft Excel v5 with the best success rate, you need to save and load them in (yes you've guessed it) Lotus 1-2-3 v4 format, and you've already read about the Amiga to mainframe print fiasco.

Sun 26th Feb (The First Executable Boot)

Although Blitz Basic is definitely not public domain, the guys at Acid have very kindly allowed executable stand-alone Blitz programs to be released into the Public Domain at no expense. All they ask is that Blitz Basic is mentioned somewhere in the program, as this allows for a bit a free publicity. Today I had a go at producing a self-booting Time Pilot disk and this is how I went about it. Firstly take a blank formatted disk, open a shell and type "INSTALL" thus making it self-booting. Secondly create an S directory using "MAKEDIR S" and copy a start-up sequence from another disk into this directory. Alternatively simply create a start-up sequence file using "ED" or any other text editor. You only need one line in the file which contains the filename of your Blitz program. Now copy all of the necessary sound and graphics files over to the new disk, and also copy the libraries that you need into a "LIBS" directory. Determining exactly which libraries you will need is a bit tricky, you could try copying all of them, or alternatively try using a bit of common sense and experimentation. There is also a neat PD program called Snoopdos which displays which libraries your program is using. Finally load up Blitz, insert your new disk and select "Create Executable File" from the compiler menu. To my amazement, this worked first time and gave me the confidence to add a loading screen. This gives the player something to look at fairly rapidly after booting and is very easily achieved. The screen won't appear until the Blitz program has loaded but this isn't a problem as the program will usually spend some time loading it's own data files. The screen is set up in Blitz mode for text output and once the appropriate graphics have been displayed, Blitz is switched into QAMIGA mode to facilitate file loading.

Mon 27th Feb (Amiga Personality)

Now that I have coded a large percentage of level 1, I do not believe that the game will run on a 512K machine although this still needs to be tested. I am designing the rest of the game such that the games full potential will be realised on the more powerful machines such as CD32 and A1200, but cutbacks will automatically be made to suit the lower spec machines. This task is complicated by the huge array of possibly Amiga configurations but luckily Blitz has provided two useful commands to ease the pain. The "Processor" function returns the fourth digit of the processor type (0 equals 64800, 2 equals 64820 and so on) and there are commands to check the amount of both "Chip" and "Fast" memory. Given these two variables, the program will decide which features to knock out and how many objects will be available. This "Amiga Personality" will be displayed on the loading screen.


...and that, as they say, is that.