Basic concepts: ECS
What is ECS
Penal Engineer is built around the ECS (Entity–Component–System) architecture.
- Every thing (a wall segment, a floor tile, a chair, a prisoner, even the onscreen debug overlay) is an Entity.
- Every Entity has one or more Components.
- A Component holds a set of values (often just a single value).
- There are Systems registered at the engine. Every System operates a single responsibility. Mostly, a System is only concerned of a single type of Component.
In Prison Architect an entity is defined as a person and, as such, an entity is opposed to other types of interactable stuff: objects, rooms, etc.
In Penal Engineer the glossary is different: everything is entity, while PA's entity is colloquially called character.
Any entity can combine a various set of components. There is no strict typing bounding a set of components to a class of entities, unlike in OOP.
Example:
- A Prisoner is an entity comprising components:
- Position which consists of three values:
X,YandFloor- Used by a lot of systems including the Render System
- Sprite representing a string identifier of the sprite to render
- Used by the Render System
- Hunger which is a single floating-point value from 0 to 1
- Used by relevant systems to dispatch an action to take some meal
- ...and others
- Position which consists of three values:
In Prison Architect things are strongly typed: Object, Room, Entity. An entity, for example, has a predefined set of parameters containers (e.g. needs). A modder can only extend those containers which were specifically made such extendable by PA developers. Want to add a new trait? Uneasy if even possible.
In Penal Engineer there is no strong typing at all. Would you like to add a completely new component impacting a character's behavior and code a new system for that? Welcome! Not to say it's not possible to some extent in PA, but this is severely limited: for instance, there is no way in PA to alter the inmate's dossier to show the new params. PE solves that elegantly.
(If you're a programmer) Why not OOP?
For such a dynamic game where every entity can naturally attain traits of another class of entities (e.g. a prisoner becoming an assistant for guards doing some of their work) OOP just doesn't suit well. ECS provides with much more flexibility. We can mix components as we wish, and given the systems are coded properly and consider only specific components, this allows us to do various mutations of entities, granting an enhanced gameplay with much less headache than we'd have with classic OOP where such initiatives would imminently raise the infamous "diamond problem" and other stuff mandated by OOP strictness.
So, no types... at all?
Yes. In Penal Engineer there is no type known for an entity. Various systems rely upon presence of components, not a strictly defined type written somewhere inside the entity.
Prefabs
You might have a quick objection against this design: but there are logical types of entities yet! If the engine provides no enforcement of a specific set of components to expect on a logical type of entity (say a prisoner must always have a position and a sprite), and every time when you need to create an entity you have to list all relevant components by hand with no validation mechanism, then there is a risk of uncatchable errors slipping in, isn't it?
This is where prefabs come to the stage.
A prefab is just a definition matching some identifier (like Prisoner) to a set of named arguments (like X, Y)
and rules of mapping between the parameters and actual components (like arg X → component Position, field X).
When you click an object (say Chair) in the UI toolbox and then click on the map, the engine literally calls the prefab
registered for the object's icon you've clicked in the UI toolbox: "Okay, the player clicked at the coordinates (258, 73)
and the camera is at floor 3, so:" CALL Prefabs[Chair] (X = 258, Y = 73, Floor = 3).
A prefab is a named function accepting a predefined set of parameters and creating necessary components setting their values as necessary, and then creating an entity and adding those components to it.
Actually, prefabs should be treated as the canonical way to create entities in the game world. The game UI toolbox with various objects shows prefabs indeed. Constructing an entity right away by manually creating components and filling the prospected entity with them should only be used from a prefab code.
In Prison Architect a prefab stands for a Quick Room feature, and only allows to build uncustomizable rooms by templates.
In Penal Engineer the prefab term is much wider generalized, and prefabs are parameterized.
Don't worry: in the vast majority of cases you don't need to make any coding to define a new prefab. If you want to register a new object or character, you should just write several lines in declarative syntax (what arguments, what base prefabs, how to map args to components), and the game engine would do the rest.