Orbital Obliterators

EXPAND . FIGHT . CONQUER

The Game Engine

The game engine is at the heart of everything, it has to manage every single tick of gaming experience, from the process that displays how much in-game cash you’ve got to the bit that makes the sound work. Its a vast, fast network of code and clever. – Tom Day, 2015

For those that need reminding or those of whom who have just clicked onto this article, the contents below are relevant to the game “Orbital Obliterators“, and the process taken to make said game.


Understanding System Capabilities

To build a game engine you need a good handle on what you need it to be able to do, and what you’re going to put it in charge of. These are your artifacts, and your resources are limited almost always when programming a game, so you must assume that you need to be efficient from the word go. One of the most useful things that was conducted was the production of UML use case diagrams, for example below is what the player will be getting up during a normal session.121

Pictured above in  is the use case diagram for a player turn, one of the most important elements of the game. During a player turn, a player can manage their Forces, Nodes and place multiple orders all in real time. The players turn won’t end until they have pressed “End Turn”, and until that moment, they may do whatever they like up to there movement / attack limit, this concept is taken directly from Sid Meier’s Civilization V (2KGames Inc., 2011) which is discussed in the focus group study. This approach was chosen to allow more than just “the plotting of attacks” to be done in a turn, as this seemed slow, and not as immersive.

Game Engine Structure

5

The flowchart above shows the architecture  of the initialization of the Game Engine. The entry point is that of when the game is loaded up. The Game Engine loads its core components as the application loads up to save load time on the actual game load. It then takes in either a saved game or a new game configuration and passes it to the World Engine to process and generate before the game state is then loaded and the game can begin. The sub processed “Load PUIs” loads up a suite of all the Purchase/Upgrade Items in game which are then configured further down the chain at the Game EngineStarts’ section. Once the game is loaded, it will then listen for click events from the current player detailed below.6

Above  shows the main turn based logic that the Game Engine uses and listens for whilst a player turn is in session. The key components here are the clicking of Nodes. The first check that occurs is whether or not the player owns the node that is selected, and further to this, whether or not a ship is currently resident within said node. After establishing this it then opens the FloatPanel and unlocks and displays the relevant information across the relevant tabs. The user may then select further menus and options until they either end the turn or enter a new mode. This happens in “deploy ship mode” and on click of all Ship buttons that are clicked. Each mode is passed to the Game Engine so that it understands in what context to handle the next click. Most of the ownership checking occurs within the ‘Node’ class itself before instructing the Game Engine that it has been clicked from which the Game Engine takes over and handles the request.

The reason for this being that the Game Engine acts as the central resource, it holds all the relevant data within itself and doesn’t allow any other class to write to it. This means that only the Game Engine itself can authorize a change in game state, or a change in Node ownership of ship position, making the possibility of synchronization mismatches virtually impossible.

Sight Process

Focusing on the player turn GUI for now, the next core element involved is the Sight stat, which is detailed in the Game Statistics System article, which is calculated using the formulae detailed in Creating the AI Decision System article. Below shows the process that occurs when the Game Engine draws the Ships on the map grid relative to a new placement.7

This highlights again the Game Engine role in controlling the data flow of Nodes and Ships in the game, whilst also showing how prompts are shown when enemies are in sight. This information is readily accessible again through the central layer of the Game Engine, allowing an open system of information free flow throughout the game. This in turn means that new systems can easily hook into one another and share data relevant to their functionality.

Game Engine Model8

The Game Engine model pictured above shows how the external classes interact with the Game Engine. As discussed briefly above the Game Engine must maintain referential integrity, all the data passing through the Game Engine must be the same at the time of request to different classes and functions. Therefore each class has a private embedded pointer to the Game Engine class within them, to allow then to read the data from the engine whenever required, but if a class wishes to modify the data sets in the Game Engine it must call one of the public methods in the game engine to carry out the task for them. This use of properties via getters and setters allows the whole game to stay in sync, as well as maintain that no duplicates are accidentally created and not removed. It is this model that has kept the development of the project far cleaner, with virtually no record of issues relating to data integrity and data duplication, it also keeps resource usage to a minimum, by not using threading technology at this point to further reduce chances of data mismatching. For a networked game, which is a possible extension to the original spec in the future, data integrity is of utmost importance, and having it controlled at this stage paves a strong foundation to build networking functionality upon.

Sound Engine & Threading

The Sound Engine model differs from the pattern by making use of threading, as without such the sounds tend to overlap and interrupt each other, resulting in a poor user experience and constant interruption of the games general immersive nature. To address this threading is used in accordance with the diagram below:9

Each sound effect is loaded in from file and held in the thread that is generated. That thread is then added to the thread pool so that no threads are lost in transition. At any time the Game Engine can call to shut down the Sound Engine on program exit at which point it will cycle through the threads in the pool and abort them, this allows for a cleaner exit whilst maintaining the use of threads within the Sound Engine. The loop that occurs by “is sound still playing?” is to address the sound loading ‘lag time’ which can occur. The benefit of this is that the Sound Engine ensures that the sound is actually heard by the player, a negative aspect of this was found when a sound is already cached and will occasionally play itself twice before the while loop breaks. This has been addressed with the use of the Sleep method within the Thread Object

A Note on Threading

Threading the Sound Engine was essential as without the threading it would not function. This statement could not be applied anywhere else in the code, and therefore most things that may have benefited from threading were not threaded, as the engine design would lose its integrity. This being said, an attempt was made to thread the ‘game load’ part of the code as the system does pause for over 5 seconds. But after attempts were made the development had been paused for this unaccounted task for too long, and thus was scrapped. The system will pause for around 5 seconds, but in playing other games, a player will always expect to see a pause when they hit the play button, so the severity of the issue was downsized. The only implication drawn from this is the possible design of a “Loading Screen” to be shown whilst the program loads in the background.

Class Structure Review

The class structure was originally much smaller, but there were impracticalities involved with them, as each class was so long it became harder and harder to read each section of code, parts of code became alien if they were older than a few days due to the mass of text bundled onto the screen. The solution to the problem was to break things down more logically, which also included the creation of the ‘CaptionsCollection’ class, which contains all the long strings of information, unit descriptions, player advice etc. in the game. This meant that there is now one unified place to look if there is grammatical or spelling errors, rather than trawling through the code for hours on end trying to find where the text was declared. Static structs have been used to store the majority of the descriptions and written communication with the player making the code more readable.

Classes like the ‘Node’ object couldn’t be broken down as all the functions within them were relevant to the Node itself, however rather than handling the pop-up box that acts as a tool tip for the node within that class too, this was broken down into its own class ‘FloatPanel‘. Further to this the use of partial classes has allowed larger classes that cannot be broken down into smaller classes to be seen in separate files to make the coding easier.

Inheritance

Inheritance was used with some of the classes in this project that needed to only build on classes that already existed. The use of inheritance came about later on the project and there is now the chance to reflect on its usage and whether the project could have benefited from more inheritance.

The ‘Player‘ class contains a number of properties, namely:

  1. The Players stats in a struct.
  2. The Players name.
  3. The Players type.
  4. The Players reputations
  5. The Players game information i.e. the prefix to be used to load player specific graphics.
  6. The Players home world Node.

All of the above are needed in ‘Barbarian‘ class but the barbarians need to store more than just the above. So in this case the ‘Barbarian‘ class inherits from the ‘Player‘ class, and has all of the above plus:

  1. The list of barbarian Refuges.
  2. The list of barbarian AIShips.
  3. The barbarian difficult level.

Illustrated more plainly as code:

public Barbarian(GameEngine inEngine, int inLevel) 
            : base(inEngine, 11, "Barbarian", Player_Types.Barbarian, 11)
        {
           //initialize
        }

This simple act of inheritance saves time and wasteful coding, with the use of reusable code and not to mention the largest benefit; the fact a Barbarian can be cast into a Player object and used in all pieces of code that require a Player object.

Custom User Controls

The WPF presentation framework (Microsoft, 2015) provides an excellent range of custom control types that allow custom GUI items to be created and replicated throughout the game. A prime example of this is the PUItem Show below:

4The areas on this control that can be changed are all the text fields and images programmed using XAML (Microsoft, 2015) , meaning that hundreds of variants can be produced rather than having to assemble a set up like this one every time. The ‘PUItem‘ class contains an enum containing all the possible variants and has setup information for each one, making the constructor declaration relatively simple. The whole class hooks into the global resource dictionary to allow a global configuration set to apply itself over the user control objects to save time in the programming of style sheets within each class.

WPF Resource Dictionary

The GUI was developed using WPF custom controls and a central resource dictionary that all the WPF classes drew there style sheets from. This made the process of development far quicker as less time was spent on the visual design due to the connected resource dictionary so more time allocation was available for the coding and implementation of different UI panels.

Conclusion

There can be no denying the fact that at the beginning of this project there was always the underlying doubt of whether it would be complete finished by the end due to the large scope of the project and the amount of research involved in order to successfully establish a fully-fledged game. That being said the development process has been efficient and constantly ongoing, sticking carefully to the time plan and through perseverance alone, the project is practically perfect. The highlights are as follows:

  • The game runs on multiple resolutions, and uses random generation to create some truly unique maps.
  • The game contains a truly diverse set of upgrades, Ships and Nodes, all differing in statistical advantages and disadvantages, giving the player a real sense of strategy by having to make so many decisions that affect the gameplay.
  • The Game Engine is at the heart of the game, which controls all the major game traffic, controls sound, animation, storage of objects and player statuses.
  • The GUI contains a vast array of easy to use and aesthetically pleasing user interfaces including overview panels and tool tips.

Issues Encountered:

The Game Engine construction has encountered several time hindering issues that are worthy to note for any future developments of a similar style they are as follows:

  • The WPF built in sound libraries are extremely limited. They wouldn’t allow a sound to be played over another, thus implying that if you were to have background music, every sound effect you played would interrupt said background music. This comes down to the fact that WPF wasn’t designed intentionally to be a game building technology, its worthy to bear this in mind when you consider developing a game in C#. There was a fix however, the simple importing of the Framework.Xact libraries allow the use of the far more diverse XNA (Microsoft, 2015) sound effect classes.
  • The Xact library wasn’t without problem as the sounds tended to overlap each other and interrupt each other even though the Xact library claims to use asynchronous methods when calling the ‘Sound.Play()’ functions. A fix for this was to manually thread the entire Sound Engine class in this game, but taking note to kill off any threads still going when the game closes as to not cause errors on shutdown.
  • As mentioned above, the resolution support is an essential part of a visual program and indeed a game. Not considering this core component in the early stages of development cost this developer a lot. The game never truly become 100% compatible with all resolutions due to the compatibility being added so far down the line, things still seem a little off centre and misaligned when not viewing in an optimal resolution. Paying more attention to the mathematics of point positioning relative to a standard rectangle size at the very beginning would have been key to avoid all these troubles.
  • Design of the visual classes is paramount, a faulty class system effected the development of this game in the early stages due to the bad design, meaning that some visual elements quite easily got mismatched and uncategorized, allowing visual anomalies to occur such as grid squares remaining highlighted even though the user has clicked away from said square. To remedy the problem a core re-write had to occur costing a good week of development elsewhere. Although the developer won’t deny that the re-write provided time to install better systems to allow for the pending updates, it still cost more time than it was worth overall to get the system working and visualizing the game state without irregularities.
  • Casting inherited objects from their base form presented errors when a base class object wasn’t an extended class. The work around for this was to use the ‘as’ operator to attempt a conversion and then use a null checker to see if it indeed can be converted or not. For Example:
Ship PotentialAI = Engine.GetShip();
Object PotentialObj = PotentialAI as AIShip;
if (PotentialObj != null) 
    { 
        //DO STUFF 
    }

Remarks

The Game Engine represents the glue that holds the entire game together. Some would argue that having such a top heavy system is not a good plan, but I find it to be the best solution in managing your data sets safety, as it rules out all possibilities of data mismatch. That being said, I’m not sure as to whether that is just me justifying myself or whether the truth lies in the fact I wanted to challenge myself, thus forcing myself into building a massive system. I’ll let you decide. – Tom Day, 2015.


Further Reading

Contained in the ePortfolio on this site are multiple articles outlining how this project was made and some of the research techniques and planning that went into the project as a whole. Below are a few honorable mentions:

Picture1 Project Planning

The critical part of a project by far is never the coding although we all want it to be. Planning a project with a good methodology is the key when it comes to success. Read More…

Picture4Conducting Research

Conducting research whether it is market research or research into appropriate techniques is the cornerstone of any modern project and was not underestimated in this project. Read More…

Picture3Carrying out a Study

Its important to look into what kind of game you’re really making… That way you can insure that you’re putting in the right level of cool when developing. Read More…

Picture5Game Statistics System

To keep a player entertained when creating a game that will intentionally last a long time, you need a robust system of content to keep them enthralled right up to the moment. Read More…

Picture2Inside the World Engine

The universe is a vast empty space of unimaginable possibility, this games most defining moment has to be its attempt to capture a little of that magic with the World Engine. Read More…

Picture6Creating the AI Decision System

To combat players not having any real friends they need someone to play against, the design and process to implement an AI decision system was the result of this problem. Read More…

<< Previous Article  |  Back to Start >>

References

2KGames Inc., 2011. Civilization V Manual. [Online]
Available at: http://www.2kgames.com/manual/civ5/civmanual_us.php
[Accessed 20 January 2015].

Microsoft, 2015. Windows Presentation Foundation. [Online]
Available at: https://msdn.microsoft.com/en-us/library/ms754130(v=vs.110).aspx
[Accessed 21 January 2015].

Microsoft, 2015. XAML Syntax In Detail. [Online]
Available at: https://msdn.microsoft.com/en-us/library/ms788723%28v=vs.110%29.aspx
[Accessed 18 February 2015].

Microsoft, 2015. XNA Game Studio 4.0 Refresh. [Online]
Available at: https://msdn.microsoft.com/en-us/library/bb200104.aspx
[Accessed 21 January 2015].