In the last post, I talked a little about how OpenGL support is going to work and about extending the support to include Fixed Function and even software rendering (though that will come online a little later). In this post I will start a little about the architecture of the XL Engine and how supporting different games has been implemented.
The main XL_Engine executable contains the core engine, it contains all the platform specific code, OpenGL and other core systems (sound system, scripting engine, networking layer, etc.).
The engine also contains an “Archive” system, which transparently allows file handling code to lookup and read files from many Archive file formats – such as GOB, LAB, BSA, ART and so on. Then for files that perform specific functions – say image/texture files or level/location/chunk data – the system can transparently load the appropriate data and have it converted internally to the correct format based on the current settings and type. For example, when using the Software renderer 8 bit images are kept in that format but are converted to 32 bit as needed, based on the current palette and color map, for the OpenGL renderer. Currently the file format data is all internal but it is also possible to write Dynamic Library based plugins, similar to the way different games are supported (DLL/so).
Game code is implemented as plugins, each game consists of a game library (DLL/so), script files and any game specific assets (in the case of games like DaggerXL – these assets are things like icons, title screen, etc.). In addition there is a small text file that describes the game so that it can be added to the list of games in the launcher. The engine has a dynamic library handler that supports Windows, Linux and OS X – there is very little code difference between systems and it is all handled by the Plugin system built into the engine. So for game and plugin code, the engine is used to handle all the OS and engine work – including things like input, file handling, script engine and so forth – allowing the game code to be platform agnostic. Obviously the same is true for all the scripts written as well.
Game plugins register various callbacks with the engine – so that they can receive input, start up game flow and UI scripts, handle pre and post render events, update and handle other events. The game will setup console functions (and potentially variables) and script functions, create entities and register game specific “logics.” Logics are self-contained functional elements, written in code or script, that make objects do things. As an example, a “Door” logic will cause a door to open or close when it receives and activation message. An entity is controlled by one or more of these logics, which are either assigned by the game code itself, through scripts or from the level data. Entities are handled by the core engine but Logics allow them to be controlled from game code, scripts and even shared logics built into the engine.
Anyway, this description just scratches the surface – there is plenty more to talk about in future posts, such as threading model, resource loading, virtual processes allowing for multiple plugins to run simultaneously (such as the editor and one or more games), networking model, script based game flow, script based UI and more. Stay tuned for future posts.