There are several hurdles to writing a game or a demo. The first is getting the cash together to purchase the equipment. The second is, of course, learning to program the machine we bought. And finally we have the actual creation of our planned game.
It's surprising then that so many people seem to master the first two stages but fail at the last one. Having splashed out good money on their computer, and gone to the trouble of learning to program, they fall at the final hurdle simply because the enthusiasm that carried them through the first two stages then forces them on into beginning a project without propare care, planning, and thought!
In this section I want to introduce the process of planning out a project - and hopefully pass on a few tips on how to make sure you don't end up abandoning your dream mid way through because you run up against obsticles which could easily have been avoided.
Lets begin by examining the role of the programmer. What exactly is it that a programmer does? He (or she :-) ) takes an idea, either on paper or in their head, and translates it into computer program code so that a working version of the idea can be created on the machine.
Notice one thing - the process starts with an idea! It does not start with the programmer immediately sitting down at the keyboard and starting to write program code. Before the programmer begins to code they need a clear plan of what they are attempting to write and how they intend to write it.
There is always a conflict in programming as to whether it should be considered an art or a science. In science, of course, we want to leap into the unknown and find out (through experimentation) where it leads us. In art we need an overview of what we are attempting to create before we begin - otherwise we will get terribly lost and our creation will suffer. (Could you imagine if every author just made up their fiction as they went along - with no idea at all what would happen from chapter to chapter, or how the story will end...?)
As a game writer you are both artist and scientist - but do not let the science get in the way of the art. Plan out your creation and make sure you understand exactly what it is you want to achieve before you begin to experiment with the code.
At the initial planning stage we are just trying to get our ideas on paper. You will be surprised just how many great ideas look really weak when they are drawn out in ink. Likewise, a lot of small ideas suddenly start to look very exciting when down in black and white.
Get yourself a pad of paper - squared paper is best because it enables you to test out ideas on how the screen will be laid out and what will go where. By drawing thumbnail sketches of graphics and layouts a lot of ideas can be generated. Don't forget to scribble down notes next to your sketches to explain what you are doing.
If your game has a story the try drafting a basic outline, for example:
This will help you get ideas for the game. As you write you may well find that new ideas pop into your head - expanding upon what you have already written.
This section is intended to be about planning, but I suppose it's worth stopping here to look at some of the most frequent planning problems and how to get round them.
Firstly there's the age-old problem of colourful displays versus speed of execution. If you want a display with lots of colours on but don't want to have large memory-hungry bitmaps (which slow the machine down) then there are a number of alternatives:
Then there's the problem of how much stuff you can have moving around the screen at once. There are many different methods to push up the number (and size) of the objects on screen:
Finally, the problem of memory space. This is always a big factor, particulary if we intend our game to run on a basic Amiga without Fast RAM. There are a number of factors to consider when planning the size of the game:
So how do we know when to stop planning and when it's safe to start experimenting with the code? Well, we need to satisfy certain criteria:
In order to find out about what is possible and what isn't we may need to write some prototype code to test out our ideas. For example, when I first created an isometric adventure game I needed to do a few test graphics and knock up a very very basic graphics engine just to test the feasibility of the idea.
You may wish to knock up a basic game engine to test (for example) a map scroller using a 256 colour screen - is it possible and how long does it take to blit the tiles each frame...? Is there time left over for blitting the spaceships and bullets...?
Note - you don't have to write the scroller or the spaceship moving routines: this prototype model is just for speed testing so we can get away with just blitting an appropriate amount of data into a bitmap each frame.
So - you've planned your game, and you know that it is technically possible, so now it's time to begin the process of writing the program code. But before you dive at the keyboard, there's one final bit of planning to do. Actually - this final bit can be done while we code - but I'm introducing it here because we will need to keep it in mind as we write.
I am, of course, refering to source code layout.
The layout and design of your source code is as big an issue in the success of your game project as good pre-coding design is! If you write spagetti code then this will slow you down, place unnecessary obsticles in your path, and ultimately hinder your progress in completeing the project.
There are many features which programming languages offer to help write compact, effiecient and readable code. We'll look at them below, and I whole-heartedly recommend that you use them.
What is structured programming? It's utilising the correct programming construct for the job. This means using a WHILE/WEND when one is required, and likewise a REPEAT/UNTIL when appropriate to do so, etc. Likewise GOSUB/RETURN and other such constructs.
There are many books on structured programming, and it would be impossible to discuss the subject fully here - but basically it's about breaking your programming down into 'choices' (IF/THEN) 'itterations' (FOR/NEXT, WHILE/WEND, REPEAT/UNTIL) and 'sequences' (straight code without choices or itterations).
It also involves designing your code into small chunks - each of which performs a particular function. Blitz provides GOSUB/RETURN as well as STATEMENT and FUNCTION constructs to enable you to do this. By using bite-sized chunks like this it's far easier to read and follow your program code.
Never, never, never use GOTO!! Goto is only permitted in structured programming under a rather strange exception known as 'backtracking'. Backtracking is a situation you are very very unlikely to encounter when coding a game. Indeed it's a situation you are very unlikely to meet in modern-day programming at all!!
So reasons to use structured code include:
Remember one thing: Documentation is free!!! It doesn't slow your program down, it doesn't make your program more or less likely to crash, and (as far as I know) it's totally tax-free in all countries around the world. :-)
Some people like to document their code like this:
For a=1 To 10 b=a*a ; Work out square NPrint "The square of ",a," is ",b ; Print result Next
Some people like to document their code this way:
; Print square for numbers 1 to 10 For a=1 To 10 b=a*a NPrint "The square of ",a," is ",b Next
And some people prefare both methods together:
; Print square for numbers 1 to 10 For a=1 To 10 b=a*a ; Work out square NPrint "The square of ",a," is ",b ; Print result Next
You should use documentation to describe what the code is doing and why it is written that way. If any complicated or involved algorythms are needed then it's a good idea to write an overview of the method used plus any known shortcomings or bugs.
Someone once told me that good documentation should be so complete that if you stripped away all the program code and just left the documentation, it would be possible to give it to another programmer and have him create an almost identically laid out program.
Modular design is really an extension of good structured programming. It involves analysing the program and designing out any repeating bits of code. Blitz provides serveral constructs to do this. There are GOSUB/RETURN's, but more importantly, statements and functions.
Lets suppose our game has a message bar at the bottom of the display. Now - every time we wanted to write to that message bar we could locate the cursor to the correct position in the bitmap and print our message. But this would be better written as a statement. The statement would accept the message text as a parameter, and then would handle the job of printing the message.
This may seem like a bit over-the-top for a bit of code which is effectively only two lines (Locate and NPrint), but it will come in handy if we wanted to move the message bar to the top of the game display - or maybe cleverly scroll the message onto the bar!
Modular design is about writing 'black box' sections of code, which accept inputs and (sometimes) give back output - but which are totally independant internally. When writing the bit of code which scrolls the screen, for example, try writing a single function which can scroll horizonatally across a tile map:
; -----Move the screen leftwards 50 steps at 2 pixels a step.
For a=0 To 49
scroll_display{-2}
Next
The above statement would not only scroll the screen - but it would keep track of which tiles need adding to the screen bitmap in order to maintain the tiled background in out game.
So what are the advantages of good modular design?
By building up layers of 'black-box' modules, rather than endless lines of 'flat' program code, you make the code more readable, useable, testable and future-proof.
You can go a stage further in Blitz 2 and use the INCLUDE compiler directive to actually separate different modules into different source files. You could have a file for all the scrolling procedures (initialise, move, shutdown, etc.), disk operations (loading data, graphics, level maps, etc.), and anything else you want to break down into a separate file.
We discussed modular design above. Macros and constants are yet another way to ensure we don't keep re-writing the same bits of code in many different places in our game.
Actually, macros and constants *do* write the same piece of code into many places in the code - but this time it's the compiler which does the job for us based upon a 'template'.
Occasionally, when we are programming, we find we are creating code which has a similar format (or layout), but not a similar function. We cannot use a statement or a function to simplify this code because it's the layout of the code which is the same - not what it does!
This is where macros come into play. Macros enable you to create a template with gaps in it into which you can insert the parts of the code which differs each time you use it.
It can be most useful in some situations - for example if you need to read entries into an array of a newtype structure. You may well find while writing out the data statements long hand that many entries are identical. There may be many numeric entries which are always initialised to zero, so why not use a macro to help you write the data statements for you? Just define a macro which contains all the static entries, while leaving gaps in it to fill in the dynamic entries.
Constants are basically the same thing, but simpler. A constant is just giving an (integer) value a name. If your game has a maximum map size of 200 tiles wide then rather than 'hard coding' the number 200 into the source code each time it is needed, try defining a constant (like #MAP_WIDTH) to 200 and use the constant name instead of the value.
With both macros and constants the compiler will take any reference to them in your source code and expand it out to the full code. So macros and constants have the following properties:
So, now that you are well on the way to creating the first in a string of blockbuster smash-hit games, you need to make sure you keep on track. The planning that you did before starting to code, and the modular/structured coding methods you are using, will help you greatly.
When you get some way into your project you may find you are becoming overwhelmed with the wealth of problems to be solved. The best way to ensure that you don't give up is to keep a list of 'Things To Do'. It can be very rewarding after a hard nights coding to be able to draw thick red lines through serveral entries on your list!!
If you find that you need to come up with a particularly tricky algorythm to achieve an effect in your game - sit down with a pen and paper and try and work the problem through. Then, when you think you know how to get what you want, try creating some test data and work through your algorythm on paper before you code it for real in your game. You'd be surprised by how many errors and potential bugs are trapped this way!