Forgotten Elixir

An enchanting engine where magic and technology intertwine

Overall architecture: a hybrid approach

created: 2025-03-13 03:26:20 UTC
last updated: 2025-03-14 02:49:16 UTC

Architecture is something that has stomped be quiet a bit over the past year. It's been about a year since I seriously tried to implement a basic game. The result of that effort was the space invaders clone that I link to in the first blog article. It was implemented in Swift on macOS utilizing the Metal API.

Objects played a pretty key role in the designed of the space invaders clone, along with building a tree out of nodes. It did take advantage of protocols so that way nodes could have child nodes of different types with their own behaviors and such, but it was very much based on a tree structure. At the top at a root node with everything as children or children of children of that. The update function really just traversed every node in the tree call its update and render function. Not a horrible design, but one I did not like so much. One advantage is, the organization is simple to wrap your head around, especially if you spend a lot of time in OOP land like I do. We used Java a lot in college and I work full time as a C# developer. So objects with references all over the place is how I spend 40 hours a week.

Last summer I got to messing with an Entity-Component-System (ECS). I also program some in Rust, and ECSs are a big topic for Rust and game development. It is also a big topic in C and C++ also, but for Rust, it really is probably the optimal pattern because of how Rust discourages long live references all over the place. The ECS focuses in laying out data in contiguous arrays, this is to help thing like cache hits. The problem with a more OOP approach is, you can be bouncing all over the heap between references, which is not free. Also, each new object is allocated on the heap, allocations and destructions of that allocated memory also has a cost. So you take generics and arrays and sorta put them together. A component is an interface that can be implemented by many different "objects." Components contain just data. You then shove these components into arrays of contiguous data so that way as you iterate through them, you maximize your use of the cache. Systems know the components they need and perform behavior using the required components. Entity's serve as keys. Each "actor" is an entity, which has an Id or some unique identifier that serves as a key to its relevant components in their respected arrays. 

ECSs are great. Although for this, I am trying a different approach. I want to sort of combine both the less ECS-approach with the ECS. In fact, my understanding is that this is sort of what Unreal engine does. It uses a mixture of both. I am also a bit of a believer in tech of, "there is no true way" of doing things. I find the answer is usually in the middle. Take different approaches and see if you can combine them to try to get best of both worlds. Will see how it works out.