Entity-Component-System For React JS
Clevyr was hired to write an interactive content creator for the web. This project would need to be able to create static images as well as videos out of simple elements like text and images. We had to have second-by-second control of what would be displayed on the screen, and we would have to support animations of and user interactions with the displayed elements.
What Is an ECS?
Because of these needs, we knew we would need to use an Entity-Component-System (ECS) framework because of its role in creating interactive graphic projects for the web. An ECS is software architecture that is primarily used in video game development. An ECS has three primary components:
- Entities — the things that populate your program
- Components — the data associated with your entities. These components are organized by the data itself and not by the entity. This is what sets it apart from an object-oriented and data-oriented design.
- Systems — the logic that transforms the component data from its current state to its next state
We will go more depth into each of these components a little later.
A simple breakdown of ECS starts with the concept of entities (the E in ECS). At its core, an entity is just an object with a unique id that represents a single item or element. Each entity is given meaning by attaching components (the C in ECS) to it. Each component defines an adjective or group of adjectives.
For example, a position component might contain X and Y coordinates. By attaching that position component to an entity, you give it those coordinates and therefore a position. But positions can change over time, and to change components or attach or remove them from entities, we use systems (the S in ECS). Systems analyze all the entities in every game loop and perform any necessary changes. For example, if we attach a gravity component to an entity, it will start being pulled on the y-axis. A positioning system might check for the existence of a gravity component on every entity. If it has one, update the entity’s Y coordinate value in its position component. In this way, the entity will “fall” down the y-axis. This combination of entities, components, systems, and a game loop (or timer) makes up the basics of ECS.
Initially, we thought of using HTML canvas to display the various elements on the screen. However, we realized that because most of our elements resemble simple HTML elements, if we used HTML and CSS instead of canvas, we could save a lot of time and effort. In addition, since we are rendering the rest of the application using ReactJS, we would be able to use ReactJS components as well.
Here is how the game system would be set up so far. The database would load up a list of entities with their associated components and feed them into the ECS. A timer based on requestAnimationFrame also needs to be loaded into the ECS. A visibility system would update an entity’s visible component based on the timer and the entity’s time component. Each entity has an element component to determine which HTML element / React component would be displayed to represent the entity.
Since we are using CSS, each component needs to be positioned absolutely and we use top, left, width, height, and visibility to position and size it. Whenever the ECS framework updates a value in an entity component, MobX will automatically detect it and tell React to re-render the appropriate display components. At this point, we now have a simple working game model, but there is one major thing missing. How are we going to update the ECS system from the rendered DOM?
Our first implementation was to simply expose the list of entities to React and allow it to mutate any entities it wanted. Although this did work, it was a bad idea because we no longer had a one-way data flow that is ideal for complicated logic systems.
Taking cues from frameworks like Flux and Redux, we added a concept of action components. These components are always added to new entities (action entities) that are then added directly to the ECS framework. The ECS systems can detect action components and mutate other entities in some way. Then, all the active components and their entities are purged at the end of each game loop. In this way, the ECS systems have full control over all entity and component manipulation. We no longer have to search the whole codebase to track down where entity mutations might be occurring.
Another benefit of the ECS-React approach is that it can easily be adapted to use SVG elements and even HTML canvas where needed. You just have to display those inside React and send any applicable information from ECS to them. For example, we used SVG elements to display rectangles and circles, but we also could have rendered a Canvas element and drawn the shapes directly onto it.
Combining an ECS framework, ReactJS, and Mobx, we were able to build a very stable and flexible content creation system for our client. Soon, we are planning on open-sourcing our ECS implementation to allow others to easily start experimenting with React-powered games and game-like applications.
Clevyr builds cutting-edge, scalable technology software solutions, including artificial intelligence for IT operations, digital twinning, predictive analytics, and cognitive computing — plus much more! Check us out at clevyr.com or drop us a line at firstname.lastname@example.org.
Join The List! Sign up here to get the latest news and updates delivered straight to your inbox.