Mostly written in Jan 04 with more added Feb 05.
Often when I experience a creation I like, I have wanted to create something similar myself. As young as 5, one of may favourite things to do was write stories like the ones I enjoyed reading, which for much of primary school were adventure stories which involved making choices and later on, throwing dice to determine success in various endeavours. I always loved computer games and when I became able, I started trying my hand at creating them myself. Similarly, as one who likes music and stage plays, I have done a bit of writing in those areas as well. I especially like the two together – musical plays – and I have done my share of writing in that genre, and hope to do more in the future. In short, those creations I like to experience I often like to create myself. This is not the case for everyone; many people love books of various kinds or visual art in whatever style and never think of putting pen or brush to paper themselves and that is just as well, because too many creators and not enough observers would not be a good thing. But I’m one of the creators (though not one of the masters), and this document is the long story of my attempts at creating computer games.
I mention a lot of dates here, so I should say I was born in Apr 80, went to primary school 85-91, high school 92-96 and university 97-99. My brother Colin, who gets referred to a bit, is two years younger. This is both a technical and autobiographical document, so different readers will read different parts of it.
In Sep 91 we got a Tandy Colour Computer 3, which was fairly primitive even then – 24kB RAM, no hard disk. It came with a BASIC manual and I learnt to make small games. For the first year or so it stayed at my grandparents’ place (we didn’t have a colour TV to plug it into) so I would write code on paper and type it all in and debug it there.
When we brought the thing home (and soon got a colour TV) there was more time for me to use it. I decided to try and write one of my dice-rolling adventure games in BASIC. I had no idea at all of data structures and sensible algorithms (few do at age 12) – the code branched in the same way as the story did, and the only use of subroutines were to automate the dice-rolling as you fought with enemies. I worked on that for about a year, by which time the code was taking up so much space that Out of Memory errors were happening at run-time. Also, the 18kB of code was taking two minutes to load and save onto cassette tapes, which often were unreliable – often I would get the dreaded IO error. The development of this game was put to an end when I couldn’t load the program from either of the tapes I was using, due to IO errors. There were many tears that day.
One day in Jun 93 I typed in the program for a game from a book. That’s what we did before the days of electronic media, and I can’t believe the patience I had in typing out things like that. It was an adventure game called Haunted House, where you explored a house and its surrounds using commands like SOUTH, GET AXE and OPEN DRAWER. It slightly spoiled the game that I made a few copying errors, but it was a good one and I used the framework to make a number of similar games, which the book showed you how to do. The code had (a) a whole lot of DATA lines with lists of nouns, verbs, object descriptions, room descriptions and the exits from each room; (b) a simple engine for parsing the inputs and managing where you are, where the objects are and what objects you have and (c) a number of hard coded special cases. Haunted House had a 8×8 grid and I can still draw much of it from memory. (I think there was another version with a 6×6 grid and a subset of the objects, with a different method of getting through the house). I used this framework (the book showed you how to do this) and made games based on four different real life houses with up to 25 rooms, and I started one with a 5x5x3 house in a story, but that one never got properly finished.
So the text adventure was a favourite genre. Only two moving games stand out in memory from that era. One had a 50×80 grid which scrolled around in a small window in the text screen. You had to move your purple square around to get all the yellow squares and avoid the red squares which chased you. The other game was on a 4 colour graphics screen in a world of about 30 screens, each defined by a series of numbers in a DATA statement, the main genius in the program being the code which interpreted the numbers and drew the screen up accordingly every time you moved from one screen onto another. It would have been hard for anyone to make a good game in that environment. BASIC is interpreted rather than compiled, so if I had written a line wrong, I wouldn’t know until it got to that part of the program. The CoCo was painfully slow to do what now is quite trivial. Now it’s normal to update a 800×600 screen 50 times a second. Back then the highest resolution was 640×192 with 4 colours, or less pixels and 16 colours, but they were too slow if you wanted to redraw everything at once. Normally anything fast used the 24×32 text screen with its 9 colours, making use of the 64 colour palette. These days we have big hard disks to store almost limitless code & data (and we have many programs to create the data), but then everything was hard coded.
In Apr 94 we got a Nintendo and a lot of good games, which at the time were way above anything I could imagine making, but I started at making a simple platformer but that was at the end of the CoCo era. Even now I look back at the NES games as the best ones I played. Maybe it’s because what we play with at age 14 can make a bigger mark on us than when we get older. Maybe it’s because I know I’ll never create anything of a higher standard than that of the NES era. Maybe it’s just better looking at a TV screen that at a computer monitor. Older people I know fondly remember the games of earlier days than the NES, while younger people are enamoured of the highly impressive games of today. My dream has long been to make a large-scale 2D platform/adventure game.
Fortunately times moved on and in Oct 95 we got a 486 and Dad used Modula-2 (similar to Pascal and Ada) in his work. One Friday night in Jun 96 I decided I was going to learn to program in Modula, and by Tuesday I was playing tetris. Later on in the year I converted it from text to graphics screen (graphics in this case would have been easier to start with) and for the first time my friends were taking home disks with something I’d made.
For a long time Colin had known an algorithm for creating 3D (“magic eye”) pictures where one looks through the picture rather than at it and sees things at different depths. When I found documentation on the bitmap file format I was able to improve this; instead of a random pattern with a hard coded image, we could draw the pattern we wanted and the image, and the program’s output was a file we could manipulate. Being able to load and save bitmaps was an important step (one I now take for granted); no more hard coded graphics. Paintbrush was now part of the development kit. I also got clever with the palette (it was normally a 16 colour screen then) and did a lot of cross-fading tricks.
As you can tell, the graphics module provided with Modula didn’t provide very much. Back then the ambition was a small but complete platform game but I still didn’t have the programming know-how (though I thought I did). The furthest I got in the Modula era was a man running and jumping on things. The 486 didn’t run Modula’s programs fast enough to redraw the whole screen very often, so we had a fixed screen. Animation was achieved by rubbing out the man and redrawing him at the new position. Being held back with speed, a friend suggested I look in the direction of assembly language.
Around Aug 97 a CS lecturer told me about A86, a simple assembler. I learnt to program in assembly language and with the help of Ralf Brown’s interrupt list I got things to happen faster than they did in Modula. Assembly language is good for optimising time-critical inner loops, but using it to write whole programs takes ages. The code is made up of simple instructions and it’s hard to know what code does without adequate comments.
The height of my achievements using A86 was a set of screens with Mario-style tiled graphics. Your man could run and jump around. One screen had a couple of yellow balls which chased you. Touching them was fatal, as was falling down a hole. Each area was bigger than the screen size and would scroll around appropriately – for the first time I was redrawing the whole graphics screen every time through the main loop, much easier to program than rubbing out and redrawing the moving objects. The game had two editors with it, both written in Modula to edit the different areas. One was to edit the list of objects in the area and their starting positions. This list would include the player and any enemies, and could be conditional on the entry code to the area (which depended which area you had come from, which could be used to make sure you appear on the correct side). The other editor was for the tiles, which mainly served as background but some of them were solid and some you could move through but still stand on.
One of the downsides of assembly programs with interrupts is that it’s easier to crash the computer. Having the program crash whenever you press CapsLock was funny, and there were a lot of times when I had to restart, but in Nov 98 I tried one trick too many and the PC never recovered.
In Jul 99 I got the DJGPP compiler working. I’d had a go at using it before, but without success. We had a Pentium by then, and after a bit of learning how to write to the screen, I was on my merry way again and enjoyed the ease of C as compared to assembler. In Oct 99 I got hold of the Allegro library, which took an incredible amount of work away from me. Every graphical procedure you could reasonably ask for is provided, as well as lots of handy functions relating to music & sound effects, keyboard & mouse and things I had never heard of. The example programs which come with Allegro show off its features well and the code for them is written well enough that I was able to learn to use much of what Allegro had to offer without a steep learning curve. I bemoaned not having grabbed DJGPP & Allegro three years earlier.
Over a quarter of my uni studies were in computer science, which made me a much better programmer than I had been. The most valuable part of CS for games was the 2nd year subject Data Structures & Algorithms. In my Modula days I didn’t know about abstract data types, so I had lots of global variables making a mess of my code. Some people may learn to code well without studying CS formally, but it was at uni that I became a competent coder, though I thought I was already when I started.
Time now to describe the game engine I made. This gets very technical, so you if that’s not what you came for you might want to skip forward a bit.
Firstly, the game world does not rely on an observer to exist. The code for the drawing is kept separate from the code for manging the world. The graphics code is simple and I’ll get to it later.
The most important class I have is the Object. This class has attributes like position, velocity and a lot of other things I’ll mention later. There are lots of extension classes of Object because there are lots of different kinds of objects. Almost any character or object in the game world will be of class Object or an extension class of it, which usually will have a few extra attributes apart from what it declared for an object, eg some kinds of object can come in different colours. There are a lot of virtual functions in the Object class. This is because you want to be able to loop through all of them and say something like “O->draw()”, even though the drawing routine will be different for each kind of object. (I don’t have that kind of draw function, mine is more complicated). Every extension class that needs to will have an implementation of this virtual function. The base Object class has an empty function for these.
I have a class called Stage, which manages all the objects. So what happens when the game runs? The first thing to do is loop through all the objects and find out how they want to move. This is easy, since most objects don’t think. There is a virtual function move() in Object, and any kind of object which needs to do anything here will have a move() function, and the others will do nothing at this time. The move function is where any enemy AI will go. It is also where you look what keys are pressed and set any move variables, eg “leftmove=key[KEY_LEFT]; rightmove=key[KEY_RIGHT];”. But most kinds of objects don’t need this. By keeping this process away from the physics, it becomes cleaner if you want some characters of the same kind to have different AI routines (or to be controlled by a player).
The next thing which happens in my main loop is the Physics I procedure, which loops through all the objects and calls their onebody() function. This function carries out the physics for that object. If it is affected by gravity, you could have “vy-=g;”, where g is the accelerartion of gravity. If it is a walking character you could have something like “if (leftmove) vx=-walk_speed; if (rightmove) vx=walk_speed;”. Again, some objects do nothing here. I don’t change any positions here, but the velocities are changed so that the positions will change correctly.
Next in the main loop I call Physics II, which is very complicated. It is about two-body interaction. Consider a rule whereby if a missile hits a character, the character is injured. This is easy to implement, because you usually just have to check for overlap of the two objects. But consider a requirement that a character not penetrate a solid object, even by a small margin. The collision detection is now more detailed; we must find out exactly how far through the time unit the penetration actually occurs. We then have to adjust the player’s velocity according to the laws of physics. To do this we need to find the angle at which contact occurred, which adds more work to the detection algorithm. Having changed the velocity, we have to check that no new collisions will occur as a result of the change. These sort of collisions get very complicated.
There was a way to avoid all of this hassle. If I had decided not to have any of these collisions except with a non-moving grid, I would have saved myself months of work. That’s what I should have done, but I didn’t because I didn’t want to be confined to a grid and I thought the algorithm I’m going to describe would be easier to get working. As it is, it doesn’t work perfectly.
So here’s how Physics II works. You loop through every PAIR of objects on the stage. (Some pairs will never interact at all, and I use a net data structure which lets me iterate through only the pairs I want). With some pairs you will need to run a routine every time, or whenever they are touching. These two-body routines can do things like changing velocities, destroying objects and sometimes bringing in new ones. It is hard to change which objects are on stage during a complicated loop, so new objects are put on a waiting list, and objects to destroy have a togo flag set. Togo is normally 0, but if you set it to a positive number it will count down by 1 every time, and when it gets down to 0 it is removed, so by setting it to 1, it will be removed that time.
When the pair of objects is one of the dificult cases I mentioned where collisions must be detected accurately and resolved, the detection routine is run for that pair and if there will be a collision, the collision notification which is returned is put in the heap. A heap is an ordered collection of things; in this case, the collision notifications are ordered according to what time (how far through the time unit they will occur).
So how does the detection happen? I never bothered to do this efficiently, but I needed it to be accurate. The velocity specifies how many units each object will move vertically and horizontally during the time unit. We use this to work out at exactly what times both objects will move, and we move them one step at a time and test if they are overlapping. If they are, then we return a positive notification. I could have done this more effificently by looking further ahead, but the potential existed for objects to move through a stage of overlap, which is dangerous if another collision occurs at that time, leaving our original pair overlapping without having dealt with it. I wanted to make sure no pairs EVER overlapped if they weren’t allowed to. If all of the difficult collisions were with pairs which were never allowed to overlap, a lot of this tricky work could have been bypassed. We could have let the whole time unit run and then see what penetration has occurred, then make the necessary adjustments. But I also wanted to allow pairs which has this solid property at some angles but not others, like a platform which a character could jump up through and then stand on. This is a case of overlap being allowed, but penetration from some angles not being allowed.
I haven’t described how we test for overlap and collision angle, so now it’s time to discuss the Shape class. Every object has a shape, just as it has a position and velocity. For a while there were only a few kinds of shapes allowed: Point, circle, rectangle, horizontal line, round rectangle. All of these can be thought of as a round-rect, but a rectangle has radius=0, a circle has its width=height=0 and for a point all three are 0. To see whether two round-rects are overlapping, we combine them to make a larger round-rect where the radius is the sum of the radii of the original two, the height is both the original heights added together, etc. Then we test whether the distance between the positions of the two objects falls within the shape, which for a round-rect is easy maths. The other thing we need to calculate is the angle of contact. For this we again use the combined shape and the point on there representing the relative positions of the objects. In most collision cases this will be close to the edge of a shape, so we return the normal angle (at right angles to the edge at that point) which again is easy with a round-rect.
So the three things we need to do with our shapes to use them for two-body physics are (a) combine two shapes, (b) test whether a point is in a shape and (c) calculate the normal angle at a point. I realise the shape combination hasn’t been explained very well, so I’ll try to explain it better. Suppose you had one of your shapes (s1) fixed in one place. s2 has a pencil stuck through its middle. Move s2 around s1 so they are touching on the outside all the way around and neither shape rotates. The shape you have drawn is the combination of s1 and s2. If you took the combination of s2 and s1 (other way around) the result would be the same shape around the other way. If you did this with a rectangle and a circle, you would have a round rectangle. Combining a square and a diamond would give you an octagon. You can see features from both shapes in the result. So if the shapes overlap, the pencil mark is inside the shape you’ve drawn. Thus the combined shape can be used to tell when there is an overlap.
There are other kinds of shapes as well, and I’ll use some notation here to describe the three methods above: s1 & s2 is the combination of two shapes and F(s,x,y) checks whether point x,y is in shape s and returns the normal angle.
Firstly there is a no-shape, which doesn’t collide. A no-shape combined with anything else is a no-shape, and the point-in function will always return false.
Another kind of shape is one defined as another shape offset by a certain amount, denoted by O(s,x1,y1). O(s,x1,y1) & s2 = O(s&s2, x1,y1). F(O(s,x1,y1), x,y) = F(s, x-x1, y-y1).
Another kind of shape is a composite of two child shapes, denoted by T(s1,s2). T(s1,s2) & s3 = T(s1&s3, s2&s3). F(T(s1,s2), x,y) = F(s1,x,y) or F(s2,x,y). See the problem with this “or” later on.
The most difficult and important shape I created was the polystroke – a convex shape made up of curves and line segments, with the convenient property that any two polystrokes can be combined to make another polystroke. This was mainly to create polygons, but the curves needed to be available so that circles would combine with them properly.
So the shape was a basic part of my complicated physics system. It didn’t always work well, as I’ll describe later. There was no scope at all for rotation, but that would have made the physics too complicated anyway. And as it’s easier to draw 2D lo-res graphics the way you want it to appear, it’s worth leaving all general rotation out of the game.
Back to the discussion about the collision heap. Having gone through all the collidable pairs to generate the heap, we start with the first notification, moving its objects up to where it occurs and then resolve it. Some objects may have had their velocity changed by this, so we remove any notifications with those objects from the heap, do the detection again for those objects with any they may collide with and put any new notifications in the heap. We continue until all the collisions in the heap have been resolved.
So how do we resolve one of these collisions? We look at the relative velocity of the objects, find out what is the component of this in the direction of contact, and alter the velocity of one or both objects in this direction so that it becomes 0. This originally seemed like a good idea, but there are three problems which need to be addressed:
Problem 1: Suppose we have two identical boxes, B1 on top of B2 on the ground, under the influnce of gravity. When gravity is applied (in Phyics I), both boxes have their speeds changed from 0 to g (downwards). B2 is going to hit the ground, so in resolving this collision B2′s speed goes back to 0 (same as the ground). Then B1 and B2 will collide. As we’re treating these as of equal mass, resolving this collision will set both their speeds to g/2. Then B2 will hit the ground, so it goes back to 0. Then B1 and B2 will collide, and get speeds of g/4, and so on. You can see that some method is required which brings all three together.
Problem 2: Computers don’t work out mathematical problems exactly. Sometimes because of the way two shapes come together, even after the collision is resolved the velocities are such that another collision is just about to occur. I called this “scraping”, because the two objects are usually sliding along each other at this point. What is sometimes needed here is a “nudge”, whereby the position is altered very slightly so the objects have room to move along each other. This is dangerous because one of them might be moved into an illegal overlap with a third object.
Problem 3: Friction. Just as we walk by means of friction forces along the ground rather than some decision automatically adhusting out horizontal velocity, I was trying to implement the movement of my characters by means of friction as part of the collision between them and the ground.
So here was the best solution I could come up with to make it all work. We have a method which resolves these multiple body collisions. Whenever we need to deal with a collision, we collect up any other objects which have collided with the two we’re looking at, and work out a solution for all objects at once. Even ordinary two-body collisions will use this, even though it is more complicated than before. Here is how a multiple body collision is resolved:
Loop through all of this until no changes are being made any more
. For all of the colliding pairs
. . If the current normal speed is still substantially positive, apply a small impulse (acceleration) on the pair including friction. This could be proportional for high speeds [so it's O(log v)], and constant for smaller speeds. If not, do nothing, and wait for the other pairs to right themselves.
When we come to nudging, we use the same kind of nested loop. Inside the loop, if the objects are still overlapping, we move them a little bit further apart.
I mentioned an impulse there. For each pair we know what the normal angle is, the two-body function has defined the mass ratio (which determines which object will move; if both, in what ratio), the two-body function has also defined what amount of friction will occur and whether there should be any extra shear speed assumed (this is a fancy way to make walking happen – instead of tending towards a shear speed of 0, when this is tweaked the friction will cause the shear speed to drift towards some other speed). So the impulse function alters the velocity of one or both objects by the given amount in the direction of contact, and if friction is called for, the velocities are also changed in the shear direction by up to the same amount multiplied by the friction coefficient, tending towards a shear speed of 0.
One problem which befell this grand scheme was concave shapes. When the combined shape for a pair of objects is concave and the point of contact is in a concave corner there is no unique normal direction. On an outside corner anything might do, but in the case of an inside corner we want the shape’s calculated normal angle to be such that when the collision tries to resolve, the impulses shift the velocity so that we get out of the corner and don’t get stuck in there. This took a lot of work and I never solved it properly.
There ends the long discussion on Physics II. If you think it was long to read, it took months to program. If I had thought it would take half that long, I would have given up on the idea of proper physics like that. I would have settled for a system where the only solid objects are on a fixed grid, no collisions between two moving objects will require resolution, and all objects needing to collide with the grid can be considered rectangles. I’ve been able to code up systems like that in a few hours. But back in Jan 00 I thought knowing the physics well meant being able to implement it properly without too much effort, and I didn’t want to give up on the idea of riding on moving platforms.
The Physics III routine moves all the objects along according to their velocity. In the simplest case this would be “px+=vx; py+=vy;”, but if they have already done some of the moving in Physics II, this is taken into account. Any objects which have their togo flag set are removed from the stage, and and new ones on the waiting list are added.
The drawing is entirely separate from the physics. A simple way to do it is to have a draw function for each class which extends Object. The draw function needs to be told where in the game world we are looking. The main loop chooses what part of the game world will be shown on the screen (probably centred on the player) and objects on the stage have their draw function called.
One issue which arises when drawing 2D graphics is the order things are drawn. If you are using graphics functions which observe a Z-buffer, you don’t need to worry about this. I did things a complicated way. Instead of using ordinary graphics instructions, the draw function put instructions into a picture-tree which was made up of drawing instructions sorted by a Z value. After going through all the objects, we go through the picture-tree and execute all the drawing instructions in the correct order. Typing this up now, I thought of a possibly simpler way: The draw functions initially tell the caller at what z-values they want to be called back. After going through all the objects on the stage we have a collection of object and z pairs, and we sort them by z and call the objects’ draw functions again, which this time do the drawing.
And I added another level of abstraction again. Instead of the draw functions, each object class had a see function which described itself to a View, which stored information about what could be seen using a minimum of space. The View is then drawn. The advantage of this is that all the graphics code is kept in one code file rather than all the separate classes, so if I was going to use a different graphics API, the code needing to be rewritten is all together. The other use of this abstraction is if the game is going to be broken into client and server. The server creates the View and sends it to the client, who displays it. I never did much in the client-server area.
And there ends the bulk of the discussion on my game engine. You wouldn’t expect it to be used for the style of puzzle game which usually has all objects confined to a grid.
In 99 my friend Trevor had designed a style of puzzle. You had to get your characters (a happy face with a star drawn around it) to their homes. There were doors that needed to be opened with keys, various devices which cold be turned on and off, levers where a star landing on one side could bounce a star sitting on the other side high into the air, blocks which had to be pushed into place and numerous other features. He drew them with a 4-colour pen, so there were often four different homes the stars had to reach and four different coloured doors. I would spend whole lectures in Sep-Nov 99 trying to solve these puzzles, and many suggested it would work well as a computer game. So in 00, this game (Puzzle Stars) is what I worked on, although I had plans to use the engine for other games which wold make better use of its accurate physics. Having designed the concept of the game, Trevor also wrote the music and put all the puzzles together while I did all the programming and drew the simple graphics based on his drawings. Not being a good graphic artist myself (I was using lo-res anyway) it isn’t an art-heavy game, which helps keep a small download size, as does MIDI music and minimal sound effects.
In May 00 we got an internet connection at home, and this opened the door to lots of other hobby game developers like myself. I read lots of discussions at GameDev.Net about numerous issues in game design and got quite interested in what plot I could develop in a future game, but I never got that far, being busy with Puzzle Stars at the time. Later on I joined the Allegro community as well. There is always a lot of action on the message boards at such sites – not just discussion about making games but about life, from the mundane to the profound to the profane. Some may spend more time corresponding on message boards than on the hobby that brought them there.
In Apr 00 Johan Peitz from Sweden released a colourful platformer called Happyland Adventures. The program was simple (very simple enemies, simple physics, and most of the graphics in tiles) but the design was excellent and the game has always been popular, especially with the Dec 00 release which incorporated all the extra features I would have suggested. It makes me wonder why I have spent ages trying to get certain features working when I cold have done things more simlpy and have an impressive game to show off already. Johan continues to impress the Allegro community with games through good ideas and hard work, while the majority of us wish we could finish what we start. Perhaps you should be reading stuff he’s written rather than this.
I never learnt any C/C++ at uni, so all I knew was what I had seen from other people’s code. In Dec 00 someone suggested the free online book Thinking in C++ (www.bruceeckel.com), which told me a whole lot of things I didn’t know about C++, and I was able to rewrite much of the Puzzle Stars code to properly use the object-oriented features of C++ and STL.
In Jun/Jul 01 Colin & I entered a competition in which groups spread over at least three countries had four days to make a game. There were eight of us in our group, with one in France, one in Canada and four in different places in eastern USA, including a boy aged 13. We tried to make an outdoor pacman game, but we bit off more than we could chew and didn’t end up doing it well. The other four groups managed impressive 3D games in the 96 hours. I enjoyed the challenge and the connection with fellow developers around the globe. That was the first of several such competitions I entered. All the others are mainly for individuals although people can still work together. Usually entrants may use existing code and data, but the specific rules describing the game to make are released at the start of the allowed time. One thing I like about these occasions is that I (hopefully) find I can make something in three days. Larger scale efforts always take longer than you think they will, but given a weekend one can design a simple game and get it working within the time limit. Puzzle Stars is the only large-scale game I’ve made and the others were in such competitions.
Around 01 I developed a pro-open-source and anti-Microsoft philosophy, like many computer nerds. There are a number of reasons for this. A programmer likes to be able to see what is happening in a program and play around with it and be able to fix any errors. Most computers run Windows because most software is written for Windows and most software is written for Windows because most computers have it. This wouldn’t be a problem on its own; one standard that everyone follows is often a good idea. But MS charge very high prices while others provide alternative software for free, so I don’t think MS deserve to hold the standard. I very much hope to see free software take over from proprietry in every area it can, and I bemoan the fact that many are going with the easier but more expensive option which will not help the world in general.
A note about piracy while I’m at it: Software companies are always crying foul about the levels of piracy and how much money they are losing. I feel that those who illegally copy software are doing an injustice to those who make software, often unpaid themselves, for anyone to use for free, only to have those people steal someone else’s product. The same applies to the music industry: The record companies complain that they are losing money when people pirate music when it is those who perform and record music for free who have a right to complain that they are not receiving patronage because people are giving it to those signed with the big companies.
Unfortunately my philosophy doesn’t fully affect my practice; I’ve always worked on a PC with Windows (and even the CoCo’s OS was made by MS) and created DOS executables and may try again at getting a Windows compiler working. But I do release code along with my games where appropriate. One reason I am unfamiliar with the games at the highest level is that I am tight with money and don’t want to buy anything. There are plenty of free games around and those who made them did it both for enjoyment and so you and I could play them without paying, rather than paying for someone else’s. OK, enough about my left-wing Christian views.
Puzzle Stars was basically finshed in Dec 00, with the Mar 01 version being similar, with a few bug fixes and the code changes to use C++ better. Between then and the Sep 01 version, I changed the puzzle file format significantly. This is always a difficult thing to do when you have files in one format already. I changed the saving routines to the new format, saved all the files in the new format then changed the loading routines to the new format. Fortunately it all worked, but I made the terrible mistake of failing to keep a copy of the intermediate code, which loads in the old format and saves in the new. Subsequently, Trevor and my cousin Adrian have created puzzles using the old version, and they couldn’t be converted to the new version. The new puzzles were quite good, so I decided to end development of the game then and leave the Mar 01 version as the final DOS version. Linux Games still had the Sep 01 version with the source, and later someone did some more superficial work and bug fixes on it. I wish I could bring the two together again – to bring the old puzzles forward to the new format and make the game worth working on further. Features I would add include joystick support and 2-player support.
One of the hardest problems many developers on my level face is how to make an editor that does most of what you want. The Puzzle Stars editor used the same graphics code as the game with a GUI around it. Any object you put in a puzzle has a position which you can edit (or alter by dragging it around) and different kinds of objects had different attributes you could edit. Some could be one of four colours, so there was a set of radio buttons to edit that, some had boolean attributes which used a check box, some had other numeric attributes which could be changed. Making the editor put these in was not too difficult, but the editable attributes could only be numberic, colour or boolean. For any other kind of attribute I wanted an object to have, I had to do extra GUI coding as well as define how it would be saved to a file.
An ambitious idea I had to solve some of these problems was to save game content using the code which would create them. This removes the need for any specialised loading code and lets you hand-code anything you need. All you need is a scripting system. So my biggest coding project of 02 was a C++ scripting system. Like the accurate physics in 00, I again underestimated the difficulty of the task, and spent months for less yield than I hoped. Compiler Construction was one of the CS subjects I enjoyed and understood, and I’d always expected that some sort of scripting system was going to be necessary anyway if I were to make a game with dialogue and thinking characters. Scripting is enormously useful in many areas of a game.
A system which parses and executes scripts is large but not too difficult, but the difficulty comes when you want a script to access functions and variables defined in the program. You have to inform the system of any functions and variables it may want to use. When you have hundreds of indentifiers you want the scripts to recognize, it won’t do to register them all manually. My idea to get over this problem was a precompiler to which you feed any header files declaring functions and variables the scripts will need to access. The precompiler reads these headers and for each entry, produces a line of code which will register that identifier. This generated code can then be compiled with the main program.
It gets tricky when you consider the different types available in C. In a CS project where there are only a few simple types, it’s easy to handle them. But as well as the basics types and any structs which may be invented, there are pointers to those types and functions or pointers to functions, and the functions may have parameters and return values of any type, it was a tough question even as to how to define my type Type! I managed this satisfactorily, using basic_string <int>, though I don’t know how well-defined it is.
This project stalled on problems like operator and function name overloading and some of the difficult C++ constructs like templates. One thing I gained here was experience with Bison, which I used to help a friend with CS assignments. I was surprised that no one else had successfully made such a usable system as far as I could find. Hopefully someone else will succeed with this soon. One option out of this problem is to move to Java.
In late 01 I was unable to find a MIDI player which would display lyrics for multiple tracks, so I made a crude program to do this and in time made other developments in the MIDI programming field. In Dec 01 I wrote an article on code which manipulates MIDI music while it’s playing. In Jul 02 I was one of two contestants in the Back2Hack, in which we had eight days, but were limited to the use of a library written to simulate the constraints of a game system like the NES, with limited resolution, colour and speed and with three square wave channels for the sound. As part of my entry I wrote a MIDI driver for the system which used it perfectly. Later in 02 I tried to make a MIDI player with more useful features for singers, but I decided that I might as well wait until I can team up with other open source developers doing something similar.
One roadblock I saw in the distance but never spent time looking into was the dificulty of creating a good GUI. The editor in Puzzle Stars used Allegro’s GUI functions and a few of my add-ons but didn’t turn out all that well. Working on software for Windows in May-Jul 01 I had the privilege of using the GUI builder and excellent libraries which come with MSVC++, but in the open source world there’s nothing quite as good. As I really don’t want to make Windows-only software and haven’t got to learning to use another GUI library, I won’t be able to make a good editor, which would require menus, text boxes and the like as well as using a lot of the drawing code the game would use. There is a lot more going for Java than C++ when it comes to GUIs.
In May 03 I went in another SpeedHack. This time one of the requirements was “3D elements”. I made my first real 3D game, and many other entries were 3D. Most of the good ones suffered from control problems on slow computers, and I developed a method of allowing the player better control when the computer is stuggling with the demands of the graphics. I wrote that up into an article as well. I didn’t do much more game-related work in 03.
When I originally wrote this document in Jan 04, this was the end of the story, but now there’s more to tell before I conclude. One of my failed projects was a C++ scripting engine. The Swedish-Brazilian programmer Andreas Jonsson had been working on the same thing, and he is far better at keeping his code in order. His system AngelScript was working but had not yet risen to prominence when I found it. It was user-friendly enough for me to use and I changed the Puzzle Stars save routines so that each puzzle was saved as the code needed to reproduce it, removing the need for all the load functions. I made a precompiler for AngelScript along the lines of the one I tried to make. I added this functionality to the old version of the program which was used to save the newer puzzles which hadn’t been converted into the other format. Thus all the puzzles were able to be saved in the new format. I also added joystick support and a groupmove function and made it easier to save & load positions or to make a recording of your attempt and play it back at any speed. AngelScript has come a fair way since then and I look forward to using it in another project, perhaps in a similar way.
In Aug 04 I discovered Adventure Game Studio, an excellent tool for creating adventure games in the style of LucasArts. I’ve experimented with it but haven’t set out to make anything with it yet. Although I like to code things myself, AGS looks like my best chance to make an adventure game of any great size. AGS games can demand large amounts of 2D art, because all the scenes need to be drawn, whereas a programmed game can make use of tiles and generated graphics. There’s plenty of scope for scripting, indeed a large AGS game will necessarily have lots of dialogue. AGS allows for spoken dialogue, and should I make a large game I expect I’ll create a tool which organises all the dialogue files and streamlines the recording process, although I haven’t successfully used Allegro’s recording routines yet.
I’ve long participated in discussions at GameDev.Net and allegro.cc and had never met any of the other members in real life. I’d seen a few people from Adelaide on GameDev and thought I might try to meet some of them one day. In the Allegro community (which is smaller and closer, being a more specific community than GameDev), some people discussed the idea of a convention where a large number of the members could meet. A worldwide convention was obviously impractical (although the AGS community had one!) but the natural reduction of this was informal meetings of a number of people from within a country. A map on which members placed their location shows plenty of Allegro.cc members in Sweden, England and the Netherlands, so plenty of people from those places could get together. I had not long seen this discussion when I got an email from Steve Taylor, another member from Adelaide, introducing himself. A week later I went to his house and for the first time I got to talk with someone in real life who had the same kind of story to tell as this one.
It didn’t end there. Though we may have been the only active members of the Allegro community, there would certainly be a good number of other game developers among the million people of Adelaide, and Steve looked around to see whether there was a group of Adelaide game developers. He found such a group, and two weeks later he and I met up with a group of others, mainly programmers like ourselves.
Also in Jan 05 I solved a problem I’d thought of for a few years: In a 2D 2-player game, how do you choose the camera coordinates for the two players so that neither camera ever looks outside the (rectangular) allowable area, so the cameras join together when they are close enough and split when they are not, and so that there is continuity in the camera positions. That’s another thing which I could add into Puzzle Stars, if I put in a 2-player mode.
That’s the story up until Feb 05. I guess my story serves as a warning to others. Don’t bite off more than you can chew. If you change file formats you must keep the code you used to convert it, indeed backing code up regularly is a good idea, but one I’ve never practised. In software, things invariably take longer to do than you think they will. Aim low and you may succeed. If you do then aim higher.
So, what are my game development plans for the future? There are a lot of things I’d love to have in a game: Mario-style physics, a Zelda-style story with an elaborate map, a branching plot, lots of dialogue (voice acting seems like a lot of fun unless you have to do too many takes), a colourful world with a lot of greenery. I like the idea of setting a game in suburban Adelaide, writing non-linear game music (an operatic game is getting too ambitious). I don’t want to go 3D, I want to keep anything I make (or a version of it) small enough to fit on a floppy, although that’s becoming an issue for less people. But to attempt a production with too many of these ideas is foolish in the light of my story here. My ambitions have always been bigger what I’ve had the capacity to create. I hope to participate in more SpeedHacks, where 72 hours after starting I’ve hopefully got something I can upload and be proud of. But I think God wants me to do better things than to spend a great proportion of my life working alone on a great game project. I may continue to work on some of the big problems I’ve described here, but I’m not going to start on a big game without someone else doing it with me who is equally passionate. Hopefully one day I meet an artist (IRL rather than online) or two whose dream has enough in common with mine that together we can finish what we set out to do. I’ve decided a similar thing in the musical theatre realm – I might write small pieces alone but I won’t get into a big project unless I meet another lyricist or composer or two who has a similar ambition. My partnership with Trevor in Puzzle Stars was alright, although his skills lie in a similar area to mine (his degrees are in Music and Maths/CS). Being primarily a programmer, with some skills in music and design, my ideal partner would be a 2D artist who can also help with creation of game content. And whichever things in the list which began this paragraph (features I’d like to implement) coincide with his list would govern how our product would look.