This files serves as the bible of architecture constraints and guidelines that we will follow to develop the Game Engine
It comes as the first task we have to do, in which Matheus, Mario and Alex will research common patterns such as Entity-Component-System (ECS) and Mediator design patterns.
The Mediator Design Pattern is a behavioral design pattern that centralizes communication between different components (or "colleagues") in a system. Instead of components interacting directly with one another, they communicate through a central Mediator. This reduces the complexity of dependencies and allows components to remain decoupled, making the system easier to extend and maintain.
-
Centralized Communication:
- The Mediator acts as a hub for communication between different components.
- It ensures that no component directly depends on another, improving modularity.
-
Decoupling of Components:
- Components (or colleagues) only interact with the Mediator.
- This eliminates the need for components to know about each other.
-
Enhanced Maintainability:
- Changes to the behavior of one component do not directly affect others.
- New components can be added with minimal impact on the existing system.
-
Simplified Interaction:
- Complex systems with many interdependent components become easier to understand and manage.
In our case the MDP will be used to manage communication between the various subsystems of the game engine. This pattern will help decouple key components like rendering, user input, game logic, resource management, and networking. By implementing a Mediator, we can ensure these subsystems interact centrally, maintaining a modular and maintainable architecture.
- Subsystem Decoupling: Each subsystem will interact only with the Mediator, eliminating direct dependencies.
- Centralized Management: The Mediator will orchestrate events such as user input, game state updates, and rendering.
- Flexibility and Scalability: Facilitate the addition or modification of subsystems without impacting the rest of the engine.
The Mediator will act as the central controller coordinating the following subsystems:
- InputHandler: Handles user inputs and communicates them to the Mediator.
- Renderer: Renders graphics based on data provided by other subsystems.
- AudioManager: Plays sounds triggered by game events.
- NetworkManager: Handles client-server synchronization.
- GameLogic: Implements game rules and notifies the Mediator of significant events (e.g., collisions, state changes).
Each subsystem will act as a "colleague" reporting its events and actions to the Mediator.
- Simplified Communication Flow: Reduces cross-dependencies between subsystems.
- Maintainability: Changes can be applied more easily due to centralized interaction logic.
- Scalability: Easier integration of new subsystems or features.
- Simpler Unit Testing: Subsystems can be tested in isolation.
- Mediator Complexity: As more subsystems are added, the Mediator can become overly complex.
- Single Point of Failure: If not designed carefully, the Mediator can become a bottleneck.
The Mediator will handle key events, such as:
- When the player fires, the Mediator will notify the
Rendererto display the shot and theNetworkManagerto send the information to the server. - When the server detects a collision, it will notify the Mediator, which will coordinate sound playback via the
AudioManagerand update graphics through theRenderer.
graph TD
PlayerInput --> InputHandler
InputHandler --> Mediator
Mediator --> GameLogic
Mediator --> Renderer
Mediator --> AudioManager
Mediator --> NetworkManager
NetworkManager --> Server
Server --> Mediator
GameLogic --> Mediator
The interaction diagram illustrates how the Mediator Design Pattern coordinates the communication between subsystems. Here's how it works:
- Player Input: Player actions are captured by
PlayerInputand sent to theInputHandler. - Input Handling: The
InputHandlerprocesses the input and forwards it to theMediator. - Game Logic Coordination: The
Mediatorsends relevant inputs to theGameLogicto update the game state (e.g., player actions, collisions, or movements) and theGameLogicsends back events or game state changes back to the Mediator for further coordination. - Output Notification:
- The
Mediatornotifies theRendererto update the visuals. - The
AudioManageris notified to play sound effects related to the input or game events. - The
NetworkManagersynchronizes the local actions with the server.
- The
- Server Communication: The
NetworkManagersends data to the server and processes responses, which are then passed back to theMediator. - Final Updates: Based on server responses, the
Mediatorupdates subsystems likeRendererto reflect changes in the game world.
The Game Loop with Subsystems is an architecture that organizes the client into distinct subsystems, each responsible for a specific functionality, while the Game Loop coordinates the sequential and linear execution of these subsystems.
-
Game Loop:
- The core of the client, controlling the game's execution flow.
- Runs the subsystems in the required order for each frame.
-
Subsystems:
- InputHandler: Captures player input (keyboard, mouse, etc.).
- NetworkManager: Manages communication with the server, sending commands and receiving updates.
- GameState: Stores the current game state (positions, entity statuses, etc.).
- Renderer: Renders graphical elements on the screen based on the game state.
The Game Loop follows a well-defined sequence of steps, ensuring that each subsystem executes its function at the right moment:
-
Input Capture:
- The
InputHandlerprocesses keyboard/mouse events and converts player input into commands.
- The
-
Message Sending and Receiving:
- The
NetworkManagersends player commands to the server. - It also receives game state updates sent by the server.
- The
-
Game State Update:
- The
GameStateapplies updates received from the server, modifying entity positions and statuses.
- The
-
Rendering:
- The
Rendererdraws the updated game state on the screen, ensuring the player sees real-time changes.
- The
A Game Loop with Subsystems is the best approach for this client. It provides a simple and efficient structure, with clearly defined subsystems for input, communication and rendering.
-
Simplicity:
- The linear structure of the Game Loop is easy to understand and implement.
- Each subsystem has a clear, well-defined responsibility.
-
Modularity:
- Subsystems are independent, allowing them to be modified or replaced without affecting the rest of the code.
-
Performance:
- Since the client does not handle complex logic, this architecture ensures low latency and high efficiency.
-
Ease of Integration:
- The Game Loop naturally connects subsystems with the server, simplifying communication and game state synchronization.
-
Scalability:
- New features can be added as new subsystems without altering the core loop.
In R-Type, all game logic is processed on the server, while the client acts as a graphical and input interface. Using more complex architectures, such as Entity-Component-System (ECS), would introduce disadvantages:
-
Unnecessary Complexity:
- ECS is designed to manage logic and behavior in games, which is unnecessary on the client since the server handles these functions.
-
Overhead:
- ECS would add unnecessary abstractions, making maintenance harder and reducing code simplicity.
-
Client Focus:
- The client needs to be lightweight and efficient, focusing on rendering graphics and capturing inputs. ECS would be excessive for these responsibilities.
This is ideal for:
- Clients acting as graphical and input interfaces, with logic processed on the server.
- Projects where simplicity and performance are priorities.
- Small to medium-sized games that do not require complex systems on the client.
If the client needs to dynamically create entities (like players, enemies, or projectiles) based on server messages, we can integrate a Factory into the NetworkManager subsystem. This maintains modularity and simplifies entity creation.
-
Purpose and Control:
- Mediator Design Pattern:
- A design pattern focused on orchestrating communication.
- Components call the Mediator to notify events and the Mediator decides how to forward information to other components.
- Game Loop with Subsystems:
- The main loop is imperative. It explicitly decides the order and methods each subsystem should execute.
- There is no notification between subsystems. The flow is linear and controlled by the loop.
- Mediator Design Pattern:
-
Relationship with Subsystems:
- Mediator Design Pattern:
- Subsystems depend on the Mediator to manage communication. They notify the Mediator about specific events and wait for it to make decisions.
- Game Loop:
- Subsystems do not directly depend on the loop. Instead, the loop directly calls each subsystem to perform its tasks.
- Mediator Design Pattern:
-
Complexity:
- Mediator Design Pattern:
- Can be more complex, especially when dealing with many event types or advanced communication logic.
- Game Loop:
- Simpler and more straightforward, particularly in a client where calls are predictable.
- Mediator Design Pattern:
The Game Loop with Subsystems architecture is a practical, efficient and modular solution for the client, perfectly aligning with its responsibilities: capturing input, synchronizing with the server and rendering graphics. Its simplicity and extensibility make it ideal for this type of project.
If we want to add new subsystems or features, this architecture provides a clear and scalable path for the client's growth.
There's a big community behind SFML, and they have various libs that will supercharge us:
SFML extension, notable features (particles, animations, resource management, time measurement utilities as clock stopping and better vector support)
SFML 2.x compatible and crossplatform.
This is a MUST, plenty of drawables we can 'easily' add to our project. We'll have to validate it works correctly with Thor.
Docs include setup and tutorials. Master/main branch is SFML2.X
Asios (networking) wrapper finetuned for using it in SFML.
You can find the API documentation in the doc sub-directory, build it with Doxygen.
We'll have to do our due dilligence to see if it's worth.
SFML 2.x support
Layered map builder, cool animations for backgrounds.
Be careful, it's not popular and may have lots of problems.
SFML2.x support