FIT CTU

Adam Vesecký

NI-APH
Lecture 4

Components

Game Model

Game Model

  • all mechanics and rules are incorporated into a game model
  • game model can be divided into several parts: domain model, view model, networking model,...
  • a game engine updates the model and interprets it to the player
  • with each update, the current state of the model is drawn on screen

Game Model

Domain Model

  • contains rules, game mechanics and essential data to the gameplay

Presentation Model

  • a model represented to the player
  • e.g. played sounds, animated sprites

Physics model

  • all entities that take part in physical interaction

AI model

  • all data and structures that are processed by AI (navigation maps, behavioral trees,...)

Networking model

  • everything that has to be in sync with other models on other devices

Example: Super Mario Bros.

Game Model

  • a complex system can only be modelled by a model that closely resembles the original system
  • a simple domain model can be found among games that can be modelled as a state machine (i.e., turn-based games, puzzles, adventures)
  • for complex games like GTA, only a domain model for base mechanics makes sense

Example: Chess

Chessmaster 2000 (1986)

Chessmaster 11 (2007)

Chess Model

  • we have here both the attributes and the game rules (in makeMove())

Chess models

Chessmaster 2000Chessmaster 11
Domain modelBoard, pieces, time, game rulesBoard, pieces, time, game rules
Presentation modelCGA Sprites, beep soundsAnimated 3D objects, 3D sounds
Physics modelNoneRigidbody engine
AI modelDavid Kittinger's engineKing engine
Networking modelNoneSending move commands

Example: Strategy

Heroes of Might and Magic

Heroes of Might and Magic model

  • we have here only the attributes

Example: Text Adventure

Example: Text Adventure

  • we have here both the attributes and the rules

Example: Pacman

Pacman architecture

  • we have here only the attributes

Object-oriented architecture

Example: Platformer

Hierarchy for the domain model

Issue #1: Adding physics

Other Issues

  • dragon may have ability to use mana
    • opt. a) rework the object hierarchy
    • opt. b) move mana to a base class
  • mage may have ability to transform himself into a dragon
    • opt. a) create a new object DragonMage
    • opt. b) add a reference to the object the mage has transformed into
  • orc may have ability to use a ranged weapon
    • add more states
  • mage may have an inventory of items affecting his abilities
  • we might want to add a dozen features during the development without the necessity of rearranging the class hierarchy
Not every set of relationships can be described in a directed acyclic graph

All-in-one pattern

  • used in 90's and early 2000's
  • one class determines behavior of every game object
  • lots of switches and if-checks

Example: Doom 2

Object-oriented architecture: summary

  • the most common way of expressing object hierarchy is via OOP and inheritance
  • this approach works well for games with a tiny model and weak emergence
  • in case of more complex games we can end up with thousands of dependencies
  • inheritance is insufficient relation for relationship modelling
  • we need to use composition, and that's where the component architecture comes into place

Summary

  • simple
  • fast prototyping
  • easy to debug
  • hard to scale
  • not flexible
  • game objects may have features they don't need

Component-oriented architecture

Component

  • a unit of composition with specified interfaces and explicit context dependencies
  • components are plug-and-play objects
  • prefers composition over inheritance and DOP (Data-Oriented Programming)
  • behavior of an entity is determined by the aggregation of its components
  • Dungeon Siege (2002) - one of the first games featuring component-based systems

ECS Pattern

  • Entity-Component-System (+ Attribute)
  • common pattern for component-oriented libraries and engines
  • game object is just a container for data and logic that will be supplied by attached components
  • can be easily integrated into the scene graph

Terms

Entity

  • a single entity/game object

Component

  • instantiable unit that defines functional behavior

System

  • a superior component responsible for a bigger scope (HealthSystem, StatsSystem, ScoreSystem)

Attribute

  • data attached to an entity
  • some engines use data components instead of attributes
The naming varies. Some engines use Behaviours for Components, Components for Systems, Properties for Attributes etc.

Example: Platformer

  • attributes are DATA, components are CODE

ECS Architecture in C++

ECS example

The greatest dilemma in component architecture

How to divide responsibilities appropriately?

Example: Pacman

Pacman

Root

  • parent of all game objects

Maze

  • model of the maze, contains location of dots, power-pellets etc.

GameSystem

  • controls the game as a unified whole (e.g. switches game modes, announces game over)

BoxBehavior

  • game logic of the center box (randomly spawns the ghosts)

PacmanBehavior

  • controls the movement of Pacman using the InputManager

GhostBehavior

  • simple AI logic, chasing Pacman

Example: Platformer

Component-oriented architecture: summary

  • scalable
  • data-oriented
  • components are easy to reuse
  • easy to make new object types
  • polymorphic operations for components
  • everything is assembled at runtime
  • static code analysis will not reveal potential issues
  • the code must be written in a generic way
  • refactoring may become annoying
  • harder to debug

Messaging

How components communicate

By modifying the container object's state

  • e.g. shared state machine
  • indirect communication
  • difficult to debug

By direct calls

  • fast, but increases coupling
  • we need to know what to call
  • getComponentByName().sth() way

By using a message broker

  • events and commands
  • each component can declare interest in relevant messages
  • e.g. listening to ITEM_PICK event and playing a sound

Message Broker

  • components should be notified of any state change that is relevant
  • can be used for returning values (danger of feedback deadlock)
  • a handler can be implemented inside components - OnMessage() function
  • processing can be instant or delayed/scheduled
  • Event - a message informing that something happened
  • Command - a message instructing that something should happen

Message Types

Unicast

  • a component sends a message to another component
  • in most cases, this can be handled by a direct call
  • example: pause the game

Multicast

  • a) component sends a message to subscribers
  • b) component sends a message to all objects that meet specific criteria
  • example: notify all nearby units that the player has entered the area
  • example: the player stepped into a puddle - play a sound

Broadcast

  • rarely used, usually for global messages
  • example: game over, debugging component

Example: Unity Messages

1 public interface ICustomMessageTarget : IEventSystemHandler
2 {
3 // functions that can be called via the messaging system
4 void Message1();
5 void Message2();
6 }
7
8 public class CustomMessageTarget : MonoBehaviour, ICustomMessageTarget
9 {
10 public void Message1()
11 {
12 // handle message
13 }
14
15 public void Message2()
16 {
17 // handle message
18 }
19 }
20
21 // sending message
22 ExecuteEvents.Execute<ICustomMessageTarget>(target, null, (x,y) => x.Message1());

Example: Unreal Message Bus

  • facilitates communication between application parts via Message Passing
  • messages are classified into commands and events
  • all messages are wrapped into IMessageContext

Message Broker Summary

  • facilitates event-based approach
  • components can react on any message that goes into the event bus
  • not intended for per-frame processing (less so for dynamics or related object movement)
  • once established, it's not easy to revise the messaging architecture
  • if there is something that should run every frame, it's better to use polling or direct call

Component-oriented game engines

Component-oriented game engines

Artemis framework

Atomic Game Engine

Unity

  • ECS architecture

Unreal Engine

  • hybrid object-component architecture

Godot Engine

  • node-based OOP architecture, signals

Example: Artemis Engine

  • Systems encapsulate logic, components encapsulate data
1 // new component
2 public class Health extends Component {
3 public int health;
4 public int damage;
5 }
6
7 // new archetype
8 Archetype dragonArchetype =
9 new ArchetypeBuilder()
10 .add(Flaming.class).add(Health.class).build(world);
11
12 public class MovementSystem extends EntityProcessingSystem {
13 public MovementSystem() { super(Aspect.all(Position.class, Velocity.class)); }
14 }
15
16 // create new transmuter
17 this.transmuter = new EntityTransmuterFactory(world)
18 .add(FrozenFlame.class).remove(Flaming.class).build();
19
20 // apply transformation to entity
21 this.transmuter.transmute(entity);

Unity

  • DOTS architecture (Data-Oriented Technology Stack), ECS superset
  • entities are game objects, components have data, systems contain logic
  • MonoBehaviour can encapsulate both data and logic

Unity Architecture

Example: Platformer2D

Example: Platformer2D Scene Graph

Example: Platformer2D Events

1 // RocketComponent
2 void OnTriggerEnter2D (Collider2D col) {
3 // If it hits an enemy...
4 if(col.tag == "Enemy") {
5 // ... find the Enemy script and call the Hurt function.
6 col.gameObject.GetComponent<Enemy>().Hurt();
7 // Call the explosion instantiation.
8 OnExplode();
9 // Destroy the rocket.
10 Destroy (gameObject);
11 }
12 // Otherwise if it hits a bomb crate...
13 else if(col.tag == "BombPickup") {
14 // ... find the Bomb script and call the Explode function.
15 col.gameObject.GetComponent<Bomb>().Explode();
16
17 // Destroy the bomb crate.
18 Destroy (col.transform.root.gameObject);
19
20 // Destroy the rocket.
21 Destroy (gameObject);
22 }
23 }

Component-oriented libraries

EnTT

Entitas

A-Frame

ECSY

  • https://ecsy.io
  • experimental ECS framework for PixiJS, ThreeJS and BabylonJS

Example: ECSY Framework

1 var world = new World();
2 world
3 .registerSystem(MoveSystem)
4 .registerSystem(RendererSystem);
5
6 class MoveSystem extends System {
7 execute(delta, time) {
8 this.queries.moving.results.forEach(entity => {
9 let pos = entity.getMutableComponent(Position);
10 pos.x += entity.getComponent(Velocity).x;
11 });
12 }
13 }

Lecture Summary

  • I know what a game model is and what is it made of
  • I know the pitfalls of object-oriented architecture in games
  • I know what a component is
  • I know the ECS pattern
  • I know messaging practices for component architecture

Goodbye Quote

The most important thing about each strategy game is Primalex - when a soldier with a bucket of paint repaints buildings to your faction, and then the enemy cannot get into themScore Reviewers