I just thought I’d post a progress report, because it probably seems like I’ve been sat on my arse doing nothing – which on the whole, is probably true.
One of the main goals with The Midnight Engine, was its openness… this is part of the holy grail of all game development, the data driven engine (DDE); in this case I actually think it’s particularly important.
To me the DDE splits into two parts, the data and the scripting engine. The first is pretty obvious, one big database with all definitions for everything in the game. In TME this is a Access Database that gets exported to XML for the engine to read. It holds tables for Characters, Strongholds, Regiments, Waypoints, Races, Genders, Areas, etc… Part of this is also configuration options. For example just one variable change will change how the recruitment model works… however there is also a need for some form of code scripting to allow a developer to make code changes without actually changing the engine. More on this later.
TME covers two destinct aspects, the frontend and the backend. The backend is the game engine and is completely seperated from any graphics output. This part of the engine can be used by 3rd parties and is indeed used by Andrew Smart’s wonderful War of the Solstice. The frontend is game driven and for my covers Lords of Midnight and Doomdark’s Revenge primarily. There are currently two versions of the frontend, the older LOM and the much newer DDR.
The transition from LOM to DDR has seen the frontend engine change dramatically. In fact most of it has been re-written. And this is where my current slowdown has occured. Sometimes writing frontend GUI code is just damned tedious – add this to my requirement for openness.
The frontend is configured through a series of XML files, every screen, every gadget is held in an XML file. This stops the ending from being recompiled for every screen change. Now ultimately this is a honouress goal, however in the short term all functionality needs to be coded. Which in the end means that development of the engine and therefore DDR goes slower than I would like, but development for other scenarios or games that follow are easier. And crucially, this is what my eye is on. Yes we all want to play a nice shiny new LOM or DDR, but I also want to play The Citadel and Eye of the Moon.
So that’s a bit of background, what have I been doing latley?
Well I have the framework for the GUI in place and many of the gadets are fully operational. The last few days I’ve been adding data collection functionality. What this means is that when a screen is displayed, or screen fragment (think panel at the bottom), the screen has a entity attached to it. All controls/gadgets/widgets that belong to that screen can retrieve data about the entity and display it without the need for any engine code.
Here is an example. ( This is generic XML, the formatting has been changed only to show it here… I need a diff plugin to show XML/HTML tags )
[guage id="ID_WARRIORS" zorder="2"]
Now this gadget can show everything it needs without any engine code at all. What actually happens is… the gadget is bound to the variable character. This is a unique identifier of an entity. The gadget is also bound to the variable warriors and element total. So when the screen is displayed or refreshed, the gadget can obtain the correct data from the correct character and process it for itself and display the result. Now the access to the data can be complex. We could for example say riders.race.name or even liege.stronghold.warriors.race. Each time the data engine knows where to do the relevant lookups to pull in new parts of data. In that case we Get the character record, then the liege character record, then the stronghold record etc…
Using this method, the display of data is just then down to the interpretation of the gadget. With this version of the guage gadget, a knuckle (warrior) is displayed proportionally along the horizontal access of the background image.
In the following example the time is displayed by moving a sun icon into set positons on a curved image.
[guage id="ID_TIME" zorder="2"]
Gadgets can also be enabled/disabled based on this information. Eg. a button may be bound to location.canHide
To take that one step further the engine has bult in collections that a gadget can access. This can be used say if you wanted to list all the lords that are loyal to another lord qryLordsLoyalTo. Or all the lords at the current location qryLordsAtSameLocation. By binding a datagrid or a selector to one of these queries we can then display all the information about those other lords.
[cell source="name" format="string"/]
[cell source="time" format="hours"/]
[cell source="race.name" format="string"/]
[cell source="warriors.total" format="number"/]
In time I would like to remove the predefined collections and just allow a very simple SQL type language to select the data.
The other stage of this is to action events. When a button is selected something has to happen…
[button id="ID_LOOKLEFT" zorder="1" OnClick="Cmd_LookLeft" /]
This tells the engine to run the internal code command Cmd_LookLeft. Which currently looks like this.
GUI_EVENT ( Cmd_LookLeft )
character& c = TME_CurrentCharacter();
Character_LookLeft( c );
LOOK_PANEL( MODE_LOOK );
return TRUE ;