The Allegro Wiki is migrating to github at https://github.com/liballeg/allegro_wiki/wiki
Now we have a rough design sketched out we can start programming! Later on I'm going to introduce several standard C modules I use in my projects to make development easier and quicker. However, first of all I'd like to talk about my programming philosophy and methodology. I am effectively a self-taught programmer with a limited knowledge of both the C language and programming. Despite this I have developed ways of increasing the chances of working on and finishing a project.
Programming Philosophy & Methodology
All programmers are different, and consequently everyone has different approaches to dealing with problems and ways of working. In my experience the hardest problem with finishing a project, (any project), is not a lack of knowledge or experience, but rather a lack of motivation. Creating a game takes both time and effort and this increases the more complex the game gets. Even a simple game takes much more time to finish when a proper title screen, menu system and polish are added. Many projects are started with a period of rapid development, but this tapers off once the realization occurs of how much more work is required before the game is finished.
The way I program combats this to some extent, and aims to encourage regular development and the completion of a project. My programming philosophy is pretty simple but paradoxically requires more work to finish a project. This is because I will create routines that give an immediate result, but will need to be removed later. For example I will create a simple text based status bar which would later be replaced with a nice graphical one, or I will hard code control routines for keys to get a control system working immediately, and then replace this with something more flexible in the future.
You may well be wondering why I do this! Well, the answer is very simple. Creating immediate visual results is very motivating and this encourages continuing development. Visual results can be anything which visually highlights the code you have done and what you can do to improve it. For example, you could try to work on the chase logic for enemies and then implement the logic alongside the code to draw them. Alternatively, if you first wrote the code to draw the enemies in a non-moving method or even simply moving up and down, then the task seems easier and the program seems more like a game.
This brings me to my second point, interactive visuals are even more motivating than static ones. So, moving monsters are naturally more interesting than static ones, and seeing them move encourages the programmer to write the code necessary to make them interact with the player even more.
So we have seen that visual results and interactive elements encourages development. This is because when you see the visual progress that has been made through the programming it helps motivation enormously. The most motivating part of any game is code that lets the player move around and interact with the game. Therefore the quicker a game can let the player control or interact with the game in some way, the better. For our game “Free Dungeons”, letting the player be able to move around the map (even without any collision detection), is much more encouraging than first working on say non-visual work such as configuration files. Giving the player control (even in a limited form) is also more motivating and exciting than working on something visual but non-interactive such as shooting or monster movement. Obviously these functions are needed as well, but they automatically become much more motivating when the player can move around and interact with them.
The order of what is programmed first is important, and spending the least amount of work to get visually interactive results provides increased motivation. Because of this desire for immediate results, some early code will have to be stripped out as the project progresses and this is why this approach actually results in a greater amount of work. However in my experience this methodology does make it more likely that you will continue developing a project.
Despite the importance of visual results, every project can benefit from a framework of standard functions. These can be used in every project for common tasks such as setting up a timer system or opening and writing to a log file. By using such a framework then a project can start much more quickly, and without rewriting code used in existing projects. The framework I will use for this project is built up of several files, each consisting of a source and header file:
Every project I start normally has a file that is named after the project itself. This source file contains the standard main() function which is split into calls to 3 other functions: startup_game, main_loop and shutdown_game. These functions are also contained in this file and help to nicely separate the project into the 3 phases common to all programs.
The header file contains standard defines used in the project such as the game name, start date and author. These game defines are used to write a header section to the log file. I also tend to put any general game resources such as bitmap and sample declarations here as well as other commonly used defines.
These files contain the standard logging functions I use to keep a log for debugging purposes. The header file also contains some special defines for use with a SET macro. In my experience one of the worst bugs a program can have is a memory error because the error can appear at random, and in unrelated parts of a program. Memory errors are normally caused by mistakes with writing to memory via pointers, but can also occur with arrays and structures.
I have previously caused memory errors by accidentally writing past the end of an array or an array of structures. This causes great difficulty in tracking down the error, as C itself has no error-checking functions unlike languages such as Java. The SET macro is my attempt to provide a level or protection for myself when using arrays and arrays of structures.
Instead of writing:
test_array = 4; // Array player.score = 4; // Array of structures
SET(test_array, 2) = 4; SET(player, 2).score = 4;
While this is more cumbersome and less elegant, each operation now has bounds checking enabled and will instantly report any bound errors (with the location in your project it occurred), both to the log file and to the screen. Additionally if the BOUND_CHECKING define is deleted and all files are recompiled, then the bounds checking will be removed for the release version of the project. This provides an extra level of security for projects in development and can be removed in the final release for a speed boost.
These files form my simple Resource Manager designed for use with Allegro. These consist of special defines to keep track of all bitmaps and samples created and destroyed. With one simple function call to rm_shutdown before the program ends all bitmaps and samples are freed automatically. The rm header file must be included by every source file that creates or destroys bitmaps & samples, but the automatic destruction of these resources stops the programmer having to worry about doing it manually. In addition there are 3 logging levels to make it easy to keep track of the bitmap and sample resources your project uses.
These files are a modified version of Chris Barry's source code which he has kindly let me use. They provide an automatic screen update method for using Triple Buffering, Page Flipping or Double Buffering. Triple Buffering provides the smoothest update for scrolling but is not always available in which case Page Flipping or Double Buffering will be used.
These files provide a high resolution windows specific timer which is more accurate than the allegro timer system. The timer system allegro uses is limited to a resolution of about 100 timer calls per second, while this timer can be used at more than 240 times per second which can prove useful for some projects.
The source code and binary executable for this article contains all of the source files mentioned here and also opens up a 640 x 480 x 256 color screen mode and shuts down cleanly with full logging. I have also created a new tile set for the project.
These graphics are based on a smaller set I did for an Amiga version of Dandy several years ago:
Finally, I have added a few lines to the standard framework. These load and display the new tile graphics before waiting for a key press and exiting. The reason I added these lines is simple as without this the program would seem very boring as all we would see would be a black screen. However by drawing the tiles to the screen we can immediately see the progress we have already made, and we can imagine using these tiles to draw a level. So where as we would be disappointed with a black screen, we now can run the program and be more motivated to continue working on the project.
So run the executable and imagine using those tiles to display a full level, for that is what we will do in the next article!