Introduction

This section is about ensuring we can compile the pre-supplied libraries (allegro, mappy and AXL) and the approach we will take with coding the game.
First lessons are always a bit dull and contain lots of tedious code and explanations, but fear not, once this is over with it should all make sense and future lessons can get straight into the game without worrying about it again.

Structure

To make it easy to find, all the files associated with the actual game will be prefixed with 'game_'. The main file, i.e. the one that we can call our start point, is game_transam.cpp. It has an associated header file game_transam.h. At the top of each lesson's game_transam.cpp will be a comment describing what the code will be doing. To keep things central we are going to store all of our function declarations and globals in the one header file. We are also going to put all of our subsequent #include statements here too. So all we have to do for any source file we create is add to the top line, #include "game_transam.h"
This first tutorial is going to initialise allegro, set up the graphics mode, create a constant game timer for controlling the game and display an arbitrary image so we can see something. In effect, this lesson will serve as a basic introduction to the AXL framework way of working.
If you are manually creating the project make file then as well as the files mentioned in the Introduction, you will need to add the files game_game.cpp and game_transam.cpp. Remember the code is stored in the same named directory as the lesson, under the AXL_Projects\tutorial\code directory, e.g. this lesson 1 is stored in the directory 'version1'.

AXL and the main game_transam.cpp file

The main menu ('Overview', etc.), at the top left of the screen describe the AXL library fully. What we it essentially does is takes away the tedious coding of timers, bitmap loading, allegro setup and graphics/animation handling. It can (and in the tutorials, will) use very simple XML based files for telling the framework how to initialise allegro and what all of our graphical resources are.
This is a basic main source code file for setting up any game, it does a lot really, as it loads up XML files and bitmaps, initialises Allegro, creates buffers and leaves us in a graphical state:

#include "game_transam.h" using namespace AXL_Projects; Framework* GameFramework; AnimationLibrary* GameLibrary; Configuration* GameConfiguration; int main() { GameFramework=new Framework("config.xml","animations.xml"); GameLibrary=GameFramework->GetGraphicsLibrary(); GameConfiguration=GameFramework->GetConfiguration(); //YOUR CODE GOES HERE! delete GameFramework; allegro_exit(); return 0; } END_OF_MAIN();


Breaking it down,

#include "game_transam.h"

As mentioned before this is our main header file that references all of our external libraries. To put AXL in context we need to tell the code we are using it.

using namespace AXL_Projects;

Our default namespace. This just lets us ensure the method names inside AXL are unique.

Framework* GameFramework; AnimationLibrary* GameLibrary; Configuration* GameConfiguration;

These pointers let us get our hands on the AXL system. 'Framework' is the parent and is used for setting up the system and contains helper functions for sound, etc. 'AnimationLibrary' is the object we use for accessing all of the graphics and animations we might use. 'Configuration' is the object we use in case we want to access any of the configuration settings, including updating them.

GameFramework=new Framework("config.xml","animations.xml"); GameLibrary=GameFramework->GetGraphicsLibrary(); GameConfiguration=GameFramework->GetConfiguration();

Here we initialise the framework and tell it the configuration and custom settings are found in config.xml and all the graphics and animations are found in animations.xml. It also tells the system that we want it to initialise the system, create all our buffers and leave us in a graphical state ready for doing allegro coding. We then populate our pointers so we can start using them.

delete GameFramework; allegro_exit(); return 0;

Here we delete the framework. This frees up all resources used and exits allegro mode and quits the program. The observant will notice that the above is not exactly the same as the source code game_transam.cpp (if you haven't done so already, open this file). Well, it is the same code, just the source code contains some error handling and pads out the '//YOUR CODE GOES HERE'. On the subject of the AXL framework, the following:

Configuration::GlobalErrorString

Is a 'static' variable that we can access at any time to see if there are any errors. Blank string means no errors. We are using it in the game_transam.cpp (and mentioned in the 'Framework' main menu) to determine if any errors occurred during setup.
The AXL library documentation to the left also contains a function/method reference guide, that describes in detail each of the methods above.

Our first bit of code

In the actual code, game_tranzam.cpp, (it would be best if you open this file to follow what is being said below) we have replaced the '//YOUR CODE GOES HERE', effectively, with the following:

if(!SetupGame()) {...} else { GameFramework->StartGameLoop( NULL,NULL, NULL,NULL, TransAmGameLogic,TransAmGameDrawing, NULL,NULL, false) }

Inside SetupGame() is where we've put the GameFramework->GetGraphicsLibrary() and other setup code. The method StartGameLoop() will be described in the next section below.
Our simple first lesson will blit an image to the screen and nothing more (though it does run in a timer with full FPS based game control). To do this we access one of the graphics set up in the animations.xml file. We called it 'panel'. All animations/graphics are classified as animations objects (though it is possible to bypass the animation class and access the bitmap direct). This is done as follows:

Animation* DisplayPanel=NULL; DisplayPanel=new Animation(GameLibrary,"panel");

Because we created this object we need to delete it as the Framework knows nothing of it, this is found in the EndGame() function. The XML entry (animations.xml) for this is as follows:

<graphic id="panel" bmp_file="panel.bmp" isasheetgraphic="0"/>

id is the name we are calling it, bmp_file is the filename, and isasheetgraphic informs the loader that it is a standalone graphic file and not part of a sheet/tiled graphic.

Header File (game_transam.h)

#ifndef retrospec_tranzam #define retrospec_tranzam #include "../../../../axl_framework.h" #include "../library/mappyal.h" //game_transam.cpp bool SetupGame(); void EndGame(); //game_game.cpp bool TransAmGameLogic(); bool TransAmGameDrawing(); #endif

Most of this should be self-explanatory. First we are ensuring the header file is only included once, we are including the files required by the tutorial (namely, AXL and Mappy). The SetupGame/EndGame functions are to start/stop the game and the two functions GameLogic/GameDrawing are to handle the logic and drawing of our game. If the header path seems a bit nested, then modify your include path or copy the files.

Game Loop

In order for games to run smoothly and at the same speed on any computer we need to control the game time. The method we will use in this game (and what can be automatically done for you by the AXL Framework) is a FPS timer control (i.e. the game will run a certain number of frames per second, and any change due to a computer's speed (fast or slow) will be handled by the timer. With the AXL Framework, in order to make use of it's game timer control you simply supply it with a list of functions that do logic/drawing and it runs them, using the values found in the config.xml file.

GameFramework->StartGameLoop( NULL,NULL, NULL,NULL, TransAmGameLogic,TransAmGameDrawing, NULL,NULL, false)

This is it. The two entries, TransAmGameLogic/TransamGameDrawing are function pointers. Calling the function instructs the framework to start a FPS limited timer loop and perform all drawing/logic. It will call the Logic/Drawing functions when necessary. Returning true from inside either function tells the loop to stop running. Within each function you have full access to all the Framework/animation/configuration libraries.
All of the other NULL parameters are similar pairs of function pointers you can pass in. This is done so that you can toggle between different functions to make your code more readible. They are arbitrarily called, Logo/Menu/Game/Exit. Unless stated otherwise, the framework will default to the first non-null function pointer. We could have put our two anywhere, but stuck it in the third one because the label for this parameter is 'Game'.
Once either of our two functions return true, the StartGameLoop call will end and follow to our final block of code which calls 'EndGame'. which deletes the Animation/Graphic we created.

Game Code

One of the most import parts of the Framework is a member variable called DrawingSurface. This is a pointer to the current drawing surface. When you want to draw anything you use this bitmap pointer. When double buffering is used, it is simply a single bitmap. When video paging or triple buffering is used it is a pointer to one of 2 or 3 bitmaps. What this means is that you always draw to DrawingSurface and the Framework handles the drawing to the screen. Swapping between double/paging/triple buffering is just a config change to the XML configuration file.
So, TransAmGameLogic and TransAmGameDrawing are functions that we've created to be our game and are called automatically by the framework via the StartGameLoop. When using the 'StartGameLoop' timer control, any logic function (TransAmGameLogic in our case) is called once per frame (the default is to run at 60FPS) and the drawing function is called when necessary. This means that if you code your logic to increase everything by 1/FPS it will run as expected on any computer. If you do not like FPS limited loops and want to use you your own, e.g. a delta based system, then simply do not use StartGameLoop. The animations work just as well either way. This tutorial will use a FPS based looping system. The drawback to FPS timers, btw, is if your computer is particularly slow then drawing is not done as often as would be liked and things tend to 'jump' around in larger increments. This is because to compensate for the slow drawing speed, the logic routines are called more often.
Our game code is stored in game_game.cpp. Our code couldn't be simpler:

bool TransAmGameLogic(){ //update player logic which can quit if ESCape pressed //this does nothing else if(key[KEY_ESC]) return true; else return false; }

If you press ESCape it quits, otherwise it doesn't. Remember, returning true signifies the end. We'll see later how you can shell out to other functions to modularise your code.
Similarly, the drawing code is just as simple:

bool TransAmGameDrawing() { //draw the panel to the screen clear(GameFramework->DrawingSurface); //score panel - always top right. maybe only show if screen is > certain size blit(DisplayPanel->ReadOnly_CurrentItem,GameFramework->DrawingSurface,0,0,0,0,DisplayPanel->ReadOnly_CurrentItem->w,DisplayPanel->ReadOnly_CurrentItem->h); textprintf_ex(GameFramework->DrawingSurface,font,180,0,makecol(255,255,255),0,"version 1: simple draw. ESCape to quite"); return false; }

Firstly we blank our drawing surface, then we display a graphic that was defined in our XML. 'DisplayPanel' was mentioned earlier and is an Animation object that stores details on the graphic object. 'ReadOnly_CurrentItem' points to the currently active bitmap for this animation. For single frame animations (i.e. a static graphic!) this will always be the first and only graphic. It is simply a BITMAP*.
This may seem a waste, constructing an object just to get our hands on a graphic, but fear not as there is an easier and quicker way, that will be described in a later lesson.
Compile and run. You'll see a graphic displayed to the screen. Nothing spectacular, but bear in mind there wasn't much code really, once you remove the waffle and it is doing a fair bit - starting an allegro program up in any mode you want (if you change the config.xml file), reading animations, running in a timer loop, etc. all in half a dozen lines of code.

The whole point about the framework is to let it do all the mundane stuff, all you do is write the code to run your game and shouldn't worry about what happens internally.

Next

In the next lesson, we'll be moving around our map. Remember that now we have the initial framework of our code up and running, we can concentrate purely on the two functions (TransAmGameLogic, TransAmGameDrawing) in the next lesson.