Component Architecture I

Czech technical University in Prague
Faculty of Information Technology
Department of Software Engineering
© Adam Vesecký, MI-APH, 2019

Game Model

Game Model

Game model is the smallest subset of the game,
determining its overall state.

Game Model

  • Each game consists of two main parts: assets and gameplay
  • Gameplay and all mechanics form a game model
  • Game model can be divided into several parts (core model, view model,...)
  • Game uses an engine to update its state and interpret it to the player
  • With each update, the current state of the model is drawn on screen

Various models for various purposes

View model

  • the one represented on screen as a result of processing all other models

Networking model

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

Core model

  • describes a state of a game at any point in time
  • tightly coupled with networking model (if there is one)

Physics model

  • all entities taking part in physical interaction

AI model

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

Example: Super Mario Bros.

Core Model

Core model should be designed in a way for which it can be easily
detached from other parts, simulated and tested independently.
Very difficult to achieve for complex games.

Example: Chess

Chessmaster 2000 (1986)

Chessmaster 11 (2007)

Example: Chess Architecture

Example: Chess Game Models

Chessmaster 2000Chessmaster 11
View modelSimple spritesAnimation states, themes, skins,...
Networking modelNonePlayer's info, time, board pieces
Core modelBoard pieces, time, AI algorithmBoard pieces, time, AI algorithm
Physics modelNoneCollision checks for correct placement
AI modelDavid Kittinger's engineKing engine

Example: Pacman

Pacman Architecture

Example: Strategy

Heroes of Might and Magic I

Heroes of M&M 1 (Real Diagram)

Example: Point-and-click adventure

The Longest Journey Saga (1999-2016)

Example: Point-and-click RPG Adventure

Dune (1992)

Example: Text Adventure

Belegost (1989)

Adventure Architecture

Adventure Events

Example: Arcade

Geometry Wars (2004)

Arcade Architecture

Object-oriented approach

Example: Platformer

Platformer and Objects

Platformer and Scene Graph

Issues

  • dragon may have an ability to use mana
    • opt. a) rework the object hierarchy
    • opt. b) move mana to a base class
  • mage may have an ability to transform himself into a dragon
    • opt. a) create a new object DragonMage
    • opt. b) add a reference to an object the mage ha transformed into
  • orc may have an ability to walk on foot
    • add more states
  • mage may have an inventory of items affecting his abilities, items can be composed together,...
  • we might want to add a dozen of 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

Generalising

This may work for attributes but not for game logic

All-purpose object pattern

  • Used in 90's
  • One class determines behavior of every game object
  • Lots of switches and if-checks

Example: Doom2

Issues of object-oriented approach

  • The most common way of expressing object hierarchy is via OP and inheritance
  • This approach works well for games with a tiny model and a 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 takes places.

Object-oriented approach summary

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

Component-oriented approach

Component

  • A unit of composition with specified interfaces and explicit context dependencies
  • components are basically plug-and-play objects
  • prefers composition over inheritance
  • it is not about how to organize your models but how to tie them up

Component

Linked together, components get things done

Architectures

Monolithic

  • discussed in previous chapter
  • traditional OOP way
  • problems with deep and wide hierarchies

Object-centric

  • each game object is represented in runtime by a single class instance
  • Early games: Thief: The Dark Project (1998), Dungeon Siege (2002)

Property-centric

  • each game object is represented only by a unique id
  • cache-friendly (components are stored contiguously in memory)
  • identifiers: integer, string, hashed string,...
  • early game: Deus Ex 2 (2003)

Architectures

// Object-centric

interface GameObject {

  id: number;

  position: Vec3;

  rotation: Quaternion;

  health: number;

  attack: number;

}

 

// Property-centric

interface GameObjects {

    ids: number[];

    positions: Vec3[];

    rotations: Quaternion[];

    healths: number[];

    attacks: number[];

}

ECS/ECSA pattern

  • ECS+A - Entity-component-system + attribute
  • game object is just a container for data and logic
  • can be easily integrated into scene graph

ECS/ECSA PATTERN

The overall behavior of a particular game object is fully determined
by the aggregation of its components (and attributes).

Terms

Entity (GameObject)

  • represents a single entity, usually a node in a scene graph

Attribute

  • member variable replacement, contains data

Component

  • instantiable entity that defines functional behavior

(Sub)system

  • superior component responsible for a system (Renderer, GameManager, AudioSystem)

Message

  • method call replacement, used to communicate among components

Event

  • type of a message; something that already happened (usually a broadcast)

Command

  • type of a message; something we want to happen (usually a multicast or a unicast)

ECSA Pattern

  • For some implementations, components contain data and systems contain logic
  • For others, components contain logic and systems orchestrates that logic
  • There is no clear definition. The important thing is that data and logic are treated separately

Example: ECSA

Example: ECSA Architecture

Example: Atomic GE Base Class

class ATOMIC_API Object : public RefCounted {

public:

    Object(Contextcontext);

    /// Return type info.

    virtual const TypeInfo* GetTypeInfo() const = 0;

    /// Handle event.

    virtual void OnEvent(ObjectsenderStringHash eventTypeVariantMapeventData);

    /// Subscribe to a specific sender's event.

    void SubscribeToEvent(ObjectsenderStringHash eventTypeEventHandlerhandler);

    /// Unsubscribe from a specific sender's event.

    void UnsubscribeFromEvent(ObjectsenderStringHash eventType);

    /// Send event with parameters to all subscribers.

    void SendEvent(StringHash eventTypeVariantMapeventData);

    /// Return execution context.

    Context* GetContext() const { return context_; }

    /// Return global variable based on key

    const Variant& GetGlobalVar(StringHash key) const;

    /// Set global variable with the respective key and value

    void SetGlobalVar(StringHash keyconst Variantvalue);

    /// Return subsystem by type.

    Object* GetSubsystem(StringHash type) const;

... };

Example: Atomic GE Base Object

class ATOMIC_API Node : public Animatable {

  public:

      /// Register object factory.

      static void RegisterObject(Contextcontext);

      virtual bool Load(Deserializersourcebool setInstanceDefault = false);

      virtual bool Save(Serializerdest) const;

      

      void SetName(const Stringname);

   

      void SetTransform(const Vector3posconst Quaternionrotconst Vector3scale);

      bool LookAt(const Vector3targetconst Vector3&, TransformSpace space = TS_WORLD);

      

      void SetEnabled(bool enable);

      /// Set enabled state on self and child nodes. 

      void SetDeepEnabled(bool enable);

      void MarkDirty();

   

      Component* CreateComponent(StringHash typeCreateMode modeunsigned id = 0);

      Node* Clone(CreateMode mode = REPLICATED);

      void AddListener(Componentcomponent);

      void RemoveListener(Componentcomponent);

  };  

Example: Unity Game Object

public sealed class GameObject : Object {

  public static extern GameObject CreatePrimitive(PrimitiveType type);

  public unsafe T GetComponent<T>();

  public T[] GetComponents<T>();

 

  public extern Transform transform { get; }

  public extern void SetActive(bool value);

  public extern string tag { get; set; }

  public static extern GameObject FindGameObjectWithTag(string tag);

  public void SendMessage(string methodNameobject value);

  public void BroadcastMessage(string methodNameobject parameter);

 

  public Scene scene {get;}

  public Component rigidbody {get;}

  public Component rigidbody2D {get;}

  public Component camera {get;}

  public Component light {get;}

  public Component animation {get;}

  public Component renderer {get;}

  public Component audio {get;}

  public void PlayAnimation(Object animation);

  public void StopAnimation();

}

Unity Architecture

Game Components

RandomMovement

Profiler

CollisionChecker

HitReaction

Spawner

GameManager

ThreatReceiver

BonusCalculator

Healthbar

TrapController

Examples

Pacman

Pacman

Stage

  • parent of all game objects
  • renders all static objects
  • all components responsible for more than one object should be attached to some of their parents (e.g. EmptyObject in Unity as a group element).

Maze

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

GameManager

  • controls the game as a unified whole (rush mode, win/lose conditions)
  • may be responsible for collision handling (by killing pacman or a ghost)

BoxBehavior

  • logic of the center box

PacmanBehavior

  • controls movement of the pacman using the InputManager

Where is the game model?

  • The question is: is the scene graph a reflecting mirror, a stage or both?
  • We have several possibilities:
  1. Make the whole scene graph the game model
    • better for emergent games
    • the model is hardwired into the scene
  2. Store the game model as an attribute of the root element
    • better for progressive games
    • the model can be isolated and tested/simulated separately
    • we need to sync the game model with the scene graph
  3. Store the game model as a separate subtree of the scene graph
    • combines 1) and 2)
    • we can apply physics and AI to one subtree and render it in another one
    • the engine must support this approach
    • we need to sync several subtrees of the scene graph

Platformer

Platformer

Paratrooper

Paratrooper

Driving game

Driving game

Component-oriented approach summary

  • scalable
  • data-oriented
  • components are easy to reuse
  • easy to make new object types
  • polymorphic operations for components
  • dynamic typing - everything is assembled at runtime
  • all dependencies have to be wired together
  • code must be written in an utterly generic way
  • refactoring may become very difficult
  • harder to debug

Lecture 3 Review

  • Game Models: view model, networking model, core model, physics, AI model
  • Architectures: monolithic, object-centric, property-centric
  • ECSA Pattern: the overall behavior of a particular game object is determined by the aggregation of its components (and attributes)
  •  

    Terms
    • Entity (Game Object) - an aggregator of components and attributes
    • Attribute - contains data
    • Component - functional behavior
    • System - global component
    • Message - method call replacement
    • Event - a message informing what happened
    • Command - a message ordering what should happen

Goodbye quote

It ain't no secret I didn't get these scars falling over in churchRed Dead Redemption