If you can read this, you have JavaScript turned off.
Please turn it on for optimal browsing experience.

The aim of this article is to present the architectural patterns proposed by Umbra, but possible to implement in any application.
The basic design pattern proposed by Umbra is the one I like to call the Master of Puppets, for the lack of a better name. The basic concept behind it is the division of the game code into one or several adapters, called UmbraModules, that are all run and managed by a singleton master object, the UmbraEngine.
The engine, acting as the puppeteer, pulls the strings of its puppets, the modules – that's how the whole idea can be descriptively presented. The engine takes care of the game's internal loop, during which it does not perform any game-specific tasks, but only operates on the modules.
In each iteration, the engine does the following tasks:
The modules, or the puppets, are adapters, meaning, they all implement a unified interface that is manageable by the engine. They implement at least four methods that will be called in each and every iteration of the game loop by the engine. These methods are responsible for:
The implementation of each of these methods is up to the developer, so they can depend on any resources available to the module, as well as use any methods that are implemented in it.
A possible configuration of the modules might be:
The main idea behind how a module works is the clear division of the phases of its operation. The module works in three semi-independent phases. These phases are:
The input phase is obvious, thus I will skip te description.
The processing phase operates on any data that is required and available. This data should be stored insode the module that's updating itself or, if necessary, in external objects that are not modules. Retrieving data from other modules is highly discouraged in this phase since it might change before the rendering phase is reached.
The output phase doesn't process any data, but only uses it to generate a display. It is perfectly safe to fetch data from other modules at this stage, since the processing phase of all modules is already done. On the other hand, data modification, although technically possible, is highly discouraged – again, because there still might be modules depending on it.
The advantages of the use of such patterns are rather obvious, but let me enumerate them nonetheless:
As an advocate of the described patterns, I don't see any obvious disadvantages. Still, I guess there might be a slight performance drop, especially in case there are many small, but specialised modules, for instance, an AI director that does not parse any input or render anything. Its rendering and input parsing phases are still triggered, returning immediately – but still wasting some CPU power on function calls. This is only a hypothesis, since no benchmarks have been made to prove or disprove this.
Another problem that might appear is the increased memory useage. The increase might not be tremendous and will probably be negligible on desktop machines, but if the architecture were to be used on a portable device, usually restricting memory useage to a ridiculously small amount, it would probably require some extra brainpower to successfully implement it.