Warning - mega text update approaching !!Original devlog post here
--------------------------------------------------------------------------------------Structuring The Universe
As interesting as spaceboxes and planets are, I decided I should start to spend some time laying down the framework for the game. In particular I wanted to tackle how I would handle the structure of the game universe and it's contained entities since this would provide the foundations for everything else to sit on. Given the scope of the game world I know that just blindly ploughing ahead with code will quickly get me in a mess and lock me out of wanted features without a major refactor, so better to have a good plan to begin with.
In the spirit of Elite, I want to create a huge game environment with thousands of different systems and planets and other objects where each entity in the game should be randomly decided upon to give a massive amount of possible combinations and variations. Given the potentially huge scope, each system and entity should be able to be easily generated on the fly when requested and discarded when no longer needed since it would quickly become unfeasible to generate the entire universe at once at the start of the game and try to hold it all in memory and update it all at the same time. Also, as well as being randomly generated, each system and significant entity must also be persistent such that when the player revisits them, the exact same one is generated again. Lastly the framework should be ordered in such a way that the game is able to cope with the massive range of scales which will be present, from parsecs to millimetres, without being hampered by floating point inaccuracy issues or other such problems.
To try and achieve this I've planned on creating a nested tree of game systems which, in order from parent to child, consists of the universe system -> galaxy systems -> solar systems and deep space systems -> and finally planetary systems. Each system will contain its children systems and a list of entities which exist within it. Using a tree structure like this means that at any one time, only branches of the whole tree that contain the player need to be generated and stored and all other systems and their children and contents can be safely deleted. Each system will also contain its own instance of the pseudo-random number generator (PRNG) used to determine its static content such as planets etc, and the first task of any system upon creation after determining its contained sub-systems will be to generate the PRNG seeds for those sub-systems. This will ensure that the same static content for each system will be generated each time regardless of the order the systems are explored in and independently of what generations might be taking place in other active systems at the same time. For generating dynamic content such as NPC trader ships and such, a global PRNG will be used instead since this is something you don’t want to be the same with each visit. Finally, for most intents and purposes, each system will act as a separate self-contained game instance which helps me deal with the mathematical inaccuracy issues since each system can use its own scale appropriate to its size and only needs be concerned with the positioning of its own local contents.
So far so good. With the above plan I should be able to create and populate a grander Elite style universe, but just like the original Elite it would lead to a universe that doesn't feel particularly alive or consistent in some ways. For example, imagine jumping out of system and immediately after jumping straight back into it again. You'd arrive to find all the dynamic content completely changed rather than similar to how you left it since the system will have been destroyed and re-created. Similarly, imagine you follow an NPC ship after it jumps into another system by jumping to that same system straight after it. You'd arrive to find it wasn't there since the system you jumped to didn't exist before you entered into it yourself and the NPC will have simply been deleted after it left the previous system. Related to this problem is that I also know I wish for the player to be able to indirectly command multiple game entities that may or may not be in the same system as the ship the player is currently piloting so that they can potentialy control armies and such.
Clearly game entities in some circumstances need to have life-times beyond that of the player’s current system and need to be able to still extract information about their surroundings and interact with the system they are occupying in a sensible manner, at least for a limited time. Thus those additional systems also still need to be created and stored in memory. However, why bother consuming the time and resources needed to generate a planet texture, or have the NPCs' AIs calculate precise ship manoeuvres for that matter, if those things can’t be seen because they are happening in an external system the player cant see. Therefore I've decided that systems and entities will have two levels of resolution, the macro and the micro. All render objects and frame to frame logic and updates will exist in the micro instance and will only be generated when needed, and the macro instance will contain only statistics about the entity and high level logical updates.
To facilitate this I've come up with a list of entity statuses and associated rules which will determine when and how micro and macro level instances and updates for entities and systems are created and destroyed. The entity statuses are: minor
- entities that are inconsequential to the player at the current time. static
- a special case of minor for entities which are persistent such as space-stations and planets which can store persistent data. significant
- minor entities are upgraded to this after being actively observed by the player (through an observer status entity or currently watched witness status entity). This status only lasts a limited time period after leaving the current scope before being downgraded again. witness
- an entity owned by and under indirect control of the player and is therefore capable of transmitting information about its current surroundings to the player although the player cant directly view its system. observer
- an entity capable of directly viewing its system such as the players piloted ship or remote cameras.
Each active entity will exist in its macro instance by default and its micro instance will only be active as long as there is another entity of observer status in the same system. Similarly, systems will only have their micro instance active if they contain an observer status entity, they will activate their macro instance if they contain any entity with significant, witness, or observer statuses, and will destroy themselves and their contained entities if they contain none of the above. Finally significant, witness, and observer status entities are all capable of spawning systems they jump into, whereas minor status entities will be destroyed upon leaving their current system.
Hopefully these plans will be enough to create a large scale universe which appears to be living and breathing even without the direct influence of the player. Now for the hard bit, I have to code it all up. Sorry for the big wall of text and the lack of pictures but I've been doing a lot of thinking and planning and not much else recently.
Thanks for reading.