In this blog entry, I will be mainly be covering the most time-consuming task of this module – porting all of our code to the new framework and utilising the OGMO editor as well as empowering the level designer to create, well, the levels for our game. In a nutshell, we had to scrap all of our object creation code from the previous framework, think about what kind of attributes for classes we need to vary based on level design, and create/hook up these entities in the OGMO editor.
Creating the Tilesets
The most time-consuming aspect here is having to go through all of the different types of objects and create them in OGMO editor to be used in a sensible way. A particularly gruelling example is the tiling system for creating “ground” and “static platforms”, as tilesets can get as big as 35 different types of tiles, where most of them are different only in that they have a different image. When originally considering how to approach this, a lot of conscious decisions were made (potentially sub-optimal decisions, but they seemed like the best idea at the time), but to explain them I would need to first explain the implications and limitations of the OGMO editor.
OGMO is really, really bare-bones. If I had to compare it to anything, it’s like a paint program with different brushes that you put on the canvas and it saves the position, size and colour of the brush. It’s a placement tool that forwards information, but receives no information back. It can’t think, and it’s about as clever as CSS/HTML. It doesn’t do logic, and it’s mostly useful for arranging your items.
Coming back to the problem with tile sets – each tile looks different. However, an OGMO entity is represented by a single image. This is the first problem and decision point – you could just choose to have one entity called “tile” or something like that, and then write a fancy and sophisticated system which determines how each tile should look at run-time. However, there’s two problems with that, one of them being more conceptual, and the other being technical:
- There might be variation in tiles, and the type of tiles used might affect the aesthetic of the game. In my personal opinion, and also from the articles I’ve read about level design (http://www.myedac.ca/what-is-a-game-level-designer/), the level designer is primarily tasked with fulfilling the work of the programmers via creating engaging gameplay experiences using the mechanics implemented, but also fulfilling the work of the art team by showcasing the art in the best combination possible through the levels. An automated system does not give that power to control the ever-so-important aesthetics of levels.
- Time constraints due to the complexity of the task. As mentioned before, we had over 35 different types of tiles on the Olympus realm of our game. A lot of this came from differentiating between ground and platforms, as well as the perspective area on tiles which the player walks. Developing an automated system to determine which tile image should be used where would result in quite a specialised, inflexible system, and I figured it would take more time than just manually creating a separate entity for each type of tile.
Looking back at the decision, it’s probably for the best that I did not try to write the automated tiling system. One of the reasons being the fact that the art was very non-standardised and varied wildly throughout the different realms. For example, in Hades, there’s two types of “main” ground in order to make it tile properly, and the user needs to alternate between them to make it work. Another one being that new tile types kept getting added as we needed them and the system would have needed to adapt to these as well.
This means that the specialised system would have needed to be changed and extended, whereas it already sounds quite complicated to begin with, and extending it would take even more time.
However, having had this hypothetical auto-tiling system would have potentially saved loads of time for the designer, because locating the correct tile to use from a list of tiny preview pictures is not the most pleasant of user experiences. Furthermore, it would have made creating the actual levels a lot faster and the levels we pumped out might have been better as a result.
Weighing these pros and cons up though, I think I made the right choice by just hard-putting in the entities, as I think I avoided a potentially big time-wasting pitfall. Developing the auto-tiling system would have taken more time for me to do (albeit the time spent would be less dull than creating entities in OGMO), might have imposed restrictions to the art, taken off power from the designer and would have been susceptible to weird edge-cases where it’s difficult to decide what tile to use, or where we actually don’t have enough tiles to deal with all of the cases.
If I did it again
If I did it differently, the only thing I would attempt to change is to try and automate the creation of the entities ever so slightly – like a script that reads a file of tile folder paths and generates the entities for you. However, a lot of the time spent on this was also on standardising the source asset file/folder structure, as well as creating texturepacker files and such. Although to be honest, I should have looked at trying to automate some of that as well.
Hooking up entities with our framework
This section of the blog is a bit more code-focused, as there was more than just pure labour involved in it. For quite a few objects in OGMO, we needed to expose some variables to the level designer as they’re useful to tweak when creating levels. The most obvious example here is the moving platform. The distance that the platform covers can vary highly, and the game designer definitely needs to be able to set the patrol range they want, so I started looking into how I might be able to do that.
Since OGMO saves everything in XML files, the framework reads them in with the help of the pugi-xml library, stores the properties of the object to create and then creates them via an object factory. From figuring this out, it became quite clear how one might approach exposing variables of specific game objects – by extending the specification of the object to create. The basic specification provided with the framework reads in things like the object’s physics shape, plist file and the class name to use for creating the object.
So the obvious idea here is to create sub-classes of these factory specifications and just fill them up when creating the specific types of objects. And so the CGCMovingPlatformFactoryCreationParams class is born:
As you can see, the only thing it does is include an extra special parameter. This parameter can then be added in OGMO as a property of the moving platform entity and that way it’s encoded in the XML document representing the level. Next, the property needs to be read in from the XML file and the appropriate specification instance needs to be created. This is done by identifying the class name for each object. So a CGCObjMovingPlatform will always need a CGCMovingPlatformCreationParams instance in order to be created. The code to do this is relatively simple, and I’ve tried to avoid code duplication as much as I could:
However, there are clearly some imperfections with the way inheritance was used, as there are properties that are common to different types of objects, but the sum of all properties for a particular object type is unique. The ZOrder or SpriteFrame properties are good examples, as well as the TriggerMessage. This is the result of not foreseeing what properties will need to be exposed, and is a good scenario for some refactoring to be done and expanding the inheritance tree for the creation parameters. Some of the creation parameter classes do in fact inherit from one another, but it could be done better. Then again, creating the perfect inheritance hierarchy would make the classes that depend on it slightly less flexible, as inheritance is also a type of coupling between classes.
Finally, let us see how the creation parameters are read in for each class:
Fairly straightforward and not much explanation is needed.
This process needed to be repeated for every class that can be different depending on its parameters, not only the ones for the level designer to tweak. A primitive example would be the CGCObjGround class and its SpriteFrame property. As discussed earlier, I created entities for each type of tile, and the SpriteFrame property is precisely what identifies which image to load for the ground tile. It is not to be set by the level designer, but rather set in the entity itself. This allowed me to create a generic background object class as well that could be used for any animated/non-animated object that does not interact with the player. To accommodate it to the framework, I had to create a physics shape for it, but took care to disable it to not waste resources at initialisation time.
If I did it again
If I were to do this again with (potentially) more time on my hands, I would definitely try to automate some of this by use of macros and/or post-processing scripts. The idea to do this would stem from the Unreal Engine firstly, as I know that it uses macros in front of variables that the user wants to expose to the editor. It really should be as simple as that when exposing variables and the way we did it made time consuming to expose extra variables later. If we had written an automated system to do this (I can’t really foresee how complicated that would be though, might be more trouble than it’s worth, since you’d need to create classes and switching code automatically), exposing more variables would be painless and we could have put in way more flexibility in the objects we create. This would mean that the level designer could create all sorts of wild levels where objects behave in clever and interesting ways, but it would also have meant that the level designer would need to wait longer before creating levels while we set up this fancy automated system.
All of the OGMO editor hardships are something I take as invaluable experience for the PS4 project. Putting stuff into OGMO was essentially developing the toolchain. We could not develop a sophisticated one because the level designer was essentially blocked while we did it, but it is definitely something very well suited for an R&D phase of development. Taking into account how much time it would save in the long run, developing a sophisticated toolchain is now one of the top things on the list for the PS4 project – we can’t work on a case-by-case basis for 8 months after all.
GCLevelLoader_Ogmo.cpp – https://drive.google.com/open?id=0B_BnvnFZLH7mdUtqbUdBUjNxVDg
GCObjMovingPlatform.cpp – https://drive.google.com/open?id=0B_BnvnFZLH7mWnU5Y0tvUG02RWM
GCMovingPlatformFactoryParams.h – https://drive.google.com/open?id=0B_BnvnFZLH7md1B0UVNjWTNCSFk