Gamestate and World simulation in Godot (part 3) - Getting deeper

So, this devlog comes with some delay, personal life sometimes takes it's time.
But here I am, sharing with you what I've learned so far about programming patterns, architecture ...and little... coding adventure... (pun intended)

As I'm continuing the quest to find an ideal (or at least decent) way of representing my game state (or persistent world), I've looked around and found some stuff, how useful will it be I don't know, but, at least, a bit more knowledge on the subject doesn't hurt.

Programming - patterns vs architecture

While desperately searching relevant information, I stumbled upon a few talks, blog pages, and so on. Somewhere in the middle of it I've learned that I should look for programming patterns, so here's a list...

  • FLYWEIGHT PATTERN - Keyword of this pattern is "re-use instances", to me Godot's MultiMesh, is a good example of this, a single visual instance repeated with only slightly changed parameters, allowing to save processing power and memory, a win win. Also shaders and resources are a good example of this, if I find a way to apply this to other things that would be great.
  • ENTITY COMPONENT SYSTEM - to me it looked similar to MVC (model view control) at a first sigh, how wrong I was... a Unity conference explains the advantages of it, and how you should design your game in order to take advantage of this architecture, yes, it's not a design pattern, at least, that's what I was told, and the reason is because ECS is in charge of cache contiguity or data locality (that is one of the main advantages of using this architecture) in other words, if Godot is not designed upon that architecture, you can't make use of it (unless you make your own branch that implements it).
  • Data Locality -Still, in some cases I believe Godot does it, as a matter of fact in the GDScript documentation page you can see the following statement: GDScript arrays are allocated linearly in memory for speed, cool!
  • OBSERVER- look, it's talking about signals!
  • COMPOSITION OVER INHERITANCE - (aka as component pattern) This should be something like: Instead of having one gigantic class representing each and every unit/entity (in my game could be an astronaut, a rover, a drone, a power plant or a harvesting area), you try to identify smaller functionalities common to most of your entities, say a mesh, a position, movement, health or in case of harvesting area could be amount of a certain resource, then you have a container class were you assemble all of this components.
    So if you subdivide complexity into smaller things then you're a composer! ...I mean, you're using composition.

Many thanks to Bob Nystrom that give to us and the chance to learn from his book for free (I should say, I was fooled at the beginning, I thought I had to buy his book in order to benefit from it, but I was wrong). I've initially linked the list above to the Wikipedia pages, but now all design patterns I'm going to read about and mention will be from this munificent book (pun intended).

Anyhow, applying the above is not easy as it may look like, so I've decided that I'll just try to go on using the knowledge I have acquired so far, hopefully being enough to make the code work as I want: fast enough to run on my crappy phone.

Just like SQL tables! ...Sorta

LOL, maybe this is a little detrimental to my image, but as I work quite a lot with databases, it comes natural to me to think at large scale simulation to something like databases, where you store some data type and reference to other tables and then you build an application on top of it, allowing to modify it's data accordingly to a defined behaviour.

So, I've tried to visualize my world in a similar fashion, using a diagram (not exactly a database diagram, but sort of).

data diagram

As you can see it really looks like a database diagram.

In the previous devlog I was first mentioning I was going to use resources, then objects, but to go really lightweight is better to use the Dictionary data type, it's quite powerful and it's used by, I think, most of Godot developers (so it should be stable).

There's still one concern tho, saving a Dictionary into a file, even compressed, is not that lightweight as I hoped, I surely can increase the compression ratio, and possibly there's also something more I can do in order to reduce size on disk of each savefile.

Anyhow, I already have re-worked on the unit entity type using Dictionary, so again it shows up only where it's deployed, and now it can also remember if it was moving somewhere and continue as soon as you return to the same location.

In the video below you can see the transition from orbit to ground (not finished yet), where the UI fades away nicely (but I would like to add a "zoom in" effect for the terrain, and show the actual terrain only when it's fully loaded).
Also you can notice that the unit appears only in the second location, if I give the command to move somewhere, return to orbit, and then come back, you'll see that the unit remembers the last command and continues it's path (although for some reason it resumes a few steps back).

Download video

To give little more detains on how this work, here you can see the "UnitsSpawner" node, that just looks at global data and instantiate units according to it. I'll work on the "BaseSpawner" as soon as I've worked a little more on designing the data structure.

The UnitsSpawner scripted node

This "UnitsSpawner" is in charge of placing units according to the gamestate.

Last minute update

As I'm writing I've already decided to change again the data structure.
As you can notice from the first diagram image most of the entities have a "location" field, and that location field is composed of other 3 fields that identify where the unit, resource, building, mission, etc. are. So I thought it would be better to use another hierarchy for data, something like this:

nested data structure

Look especially at the ground_tile group, it is composed of 2 fields containing data about the current tile we're in, below other entities that represent everything that can exist inside

This way, the most commonly used fields will not be repeated, each tile will contain everything: a base, a unit, a structure, resources and also local weather information.

Saving space on disk and in memory is a priority!

Global Weather and Resources

What is worrying me especially are the weather and resources, I shouldn't create them in advance, but have some sort of high level data group that will allow to create that particular weather entity on the fly, same as for the resources. Or else, by creating those in advance I'll get a huge database (my wild guess is around 1.5M entities per type, way too much).

So there's still some more design decision to take, at least before integrating that part.

And that's it for this week. See you soon!

Leave a comment

Log in with to leave a comment.