This is an old revision of the document!
The Cafu Engine can be used both for developing single- or multiplayer games that ship as individual products, as well as for products that support multiple, independent games in a single program that the user can select from at runtime.
For example, after starting the program, the user might choose from a list of online game servers (each possibly running not only different game maps, but entirely different games), or a list of available single-player games, and join one seamlessly without restarting the program.
The fact the multiple games can be present at the same time makes it worthwhile to keep all related files and program code well organized, so that games can be developed and shipped to end users modularly and independently of each other and of the Cafu core engine.
In order to achieve these goals, all files, data and program code for a game are stored in one common directory, which in turn must be a subdirectory of Games/
.
For an example, see the Games/DeathMatch/
directory of the DeathMatch example game that ships with Cafu:
Although you're largely free to organize the contents of the game directory as desired, per convention some of the resource files must be kept under fixed names or in given directories, so that the Cafu Engine can find and load them when it is newly initializing the game.
The following sub-sections list and explain most of these “fixed” files and directories.
File EntityClassDefs.lua
defines all entity types that can occur in the game.
The file is read both by the world editor CaWE and the actual game code in order, and for each entity type specifies details like names, dimensions, properties, etc.
Directory Code/
contains the source code for the implementation of this game.
The source code is compiled into a program library that the Cafu Engine dynamically loads and binds to at runtime whenever it initializes for a new game.
The program libraries are known as “DLLs” (dynamic link libraries) under Windows, and “SOs” (shared object) under Linux. Independent of the platform, this library with the binary code is referred to as “DLL” in this documentation, and it is kept in another subdirectory of Code/
as well.
The DLL is expected to have the same name as the game, and thus expected to be found in
Games/DeathMatch/Code/build/.../DeathMatch.dll (Windows) Games/DeathMatch/Code/build/.../DeathMatch.so (Linux)
where ...
is a path that is automatically created by the build system according to your platform, compiler and build variant.
The ...
path is also known to the Cafu Engine so that it can load the library.
See section The game source code for more details about the game source code.
, GUIs in GUIs
, world files in Worlds/
, and so on.
The source code for the DLL is in Code/
, inside which you can organize and arrange the source files at will.
The first function that the engine calls in the game DLL is GetGame()
.
For our example game DeathMatch, we have defined this function in file
Games/DeathMatch/Code/DeathMatch.cpp.
Please check out this file for more information on the function signature and documentation!
The next steps to get more familiar with the code is to check out the
cf::GameSys::GameI interface,
and its implementation in GameImplT
.
The core engine will call the methods of the cf::GameSys::GameI
interface, e.g. those to have new entities created after a map file has been loaded or when another player joins the game, and it's the job of the game code to provide implementations for these methods.
See the code for class GameImplT
in order to see how it was done for the DeathMatch game.
With the BaseEntityT
pointers to newly created entities, the engine will also call the virtual methods in the BaseEntityT
interface, in order to let entities know about events or to have them carry out tasks.
These methods too are supposed to be overridden by the concrete entity implementation, and are in fact the essence of implementing a game:
An entity is considered a state machine that lives in a virtual world, interacting with the world and other entities, and for example its BaseEntity::Think()
method is expected to update it over a small amount of time whenever the method is called (by the server code inside the engine).
This document is not complete, and we will continue to improve it.
The class hierarchy is shown in
but these two documents need to be merged and updated and completed, where necessary.
If you have questions about anything that is mentioned in this document (or is missing and should be mentioned), please let us know! We will be happy to answer you questions and use the answer to improve this text.