Wartbed:Architecture/MVC

From Dark Omen Wiki

Jump to: navigation, search

WARTBED Architecture
Documents related to technical design aspects and implementation details.
For a general overview of WARTBED, see the WARTBED Design Document

Architectural documents:

* Modules * Networking * Model-View-Controller
* Audio * Scripting * Terrain Rendering

WARTBED

0.1 "Clausewitz"
0.2 "Jomini"
...

Model-View-Controller ("MVC") is a software design architectural pattern and principle (sometimes also considered a design pattern) that defines how system components and responsibilities are separated and intended to interact. The main principle is the separation of system "logic" (rules or inner mechanics), user input (system-user interaction), and sensory representation (GUI, sounds, etc) from each other. The purpose if this is to loosen couplings and promote modularity. The WARTBED system architecture follows this design architecture.

Contents

WARTBED's Model-View-Controller Design

Note! That discussed here is the current state of WARTBED, but not how the final MVC implementation will be. With the coming client-server session management some of the structures here will be invalidated as discussed in controllers, below.

Everything that can interact in a game world is a "game object" (or an "entity"). The WARTBED game objects exists in a virtual universe solely defined by its own logic and knows or cares nothing about their representation - they are pure Models. In principle, since all game logic takes place in the Model layer, a WARTBED game can run completely in the abstract without any graphical or auditory output at all. Every entity have one or more corresponding representations (views) that may read "their" entity but not change it. However, as is common in games software, the models CAN signal the outside world by sending messages.

In the conventional interpretation of MVC, the model and views are completely separated and only communicate through a controller. Sometimes, for reasons of efficiency, the view can observe the model. Though this observer pattern design is frowned upon or rejected by purists, it is common in computer game programming.
+------------+     +------------+     +------------+
|            |     |            |     |            |
|            |     |            |     |            |
|   Model    |<=== | Controller | ===>|    View    |
|            |     |            |     |            |
|            |     |            |     |            |
+------------+     +------------+     +------------+
      ^                                      |
      +--------------------------------------+
WARTBED assumes a pragmatic stance and though using a strict division of responsibilities between models, views and controllers, also accepts that architectural fundamentalism is not in the best interest of game development. The WARTBED MVC structure allows view objects to observe (though not change) model objects, and models can signal events by broadcasting messages to observers subscribing to it. Models still know nothing about the functionality of any subscribers, who are responsible for processing and responding to messages.
    +-----------------------------------+
    |               Model               |
    +--------------+---------------+----+
                 ^ ! The model can ! ^
                 | ! send messages ! |
                 | !               ! | 
The controller   | !               ! | The View can
issues orders to | !               ! | read the Model
model entities   | V               V |
  +--------------+----+        +-----+------------+
  |   Controller      | -----> |      View        |
  +-------------------+        +------------------+
                    The controller can
                    direct the view
The controller module is essentially a game session. It ties together a set of participants (agents that wish to interact with the game world) with the models and views.
                                       Models

                                       +---+     
Players                             >  |   |-+   
                                   /   +---+ |-+     
    +---+             +---------+ /      +---+ |                 
    |   |-+   <-----  |         |          +---+ 
    +---+ |-+ ----->  | Session |         
      +---+ |         |         | \    +---+     
        +---+         +---------+  \   |   |-+   
                                    >  +---+ |-+ 
* Humans                                 +---+ | 
* AIs                                      +---+ 
* Observers            Controller
                                       Views

Model and View

As example, assume a space game, where the main Model will be the class "Ship".

The Model and View classes: Notice that the Model interface (abstract base class) doesn't know anything about the specifics of its views. Also notice that it is required of any View to register itself with its Model.

//----------------------------------------------------------------------------------------------------------
// Basic classes: f.i. in (made-up file) "MVC_base.h" 
//----------------------------------------------------------------------------------------------------------
 
typedef shared_ptr<Message> MESSAGE;
typedef std::set<View *> VIEW_SET;


//-----------------------------------------------------
// Model base class
//-----------------------------------------------------
 
struct Model
{
    mutable VIEW_SET views;
 
    virtual ~Model() {}
 
    void registerView( View *pView ) const
    {
        views.insert( pView );
    }
};
//-----------------------------------------------------
// View base class
//-----------------------------------------------------
 
struct View
{
    virtual void receiveMessage( MESSAGE &msg ) {} = 0;
 
    View( Model const &rModel ) { init(rModel); }
    virtual ~View() {}
 
    void init( Model const &rModel )
    { 
        rModel.registerView( this );
    }
};


//-----------------------------------------------------
// Example model class, f.i. in "Ship.h"
//-----------------------------------------------------------
 
#include "MVC_base.h"
 
struct Ship : Model
{
    VECTOR3 position;      // Example game 
    long    hull_points;  // object data
};
The Ship class: As can be seen, for a Model-layer class, in this instance "Ship", being an Model is fully non-intrusive. The effect is that it can now send messages to any registered representations.

//-----------------------------------------------------------
// Example view class, f.i. in "game_display.h"
//-----------------------------------------------------------
 
#incluide "Ship.h"
 
struct ShipView : View
{
    Ship const *pShip;
    OgreSceneNode *pNode;
 
    ShipView( Ship const *pShip ) : View(pShip), pShip(pShip) {}
    void receiveMessage( MESSAGE &msg ) {}
 
    void update() { pNode->setPosition( pShip->position ); }
};
A View of the Ship: A specialised view needs, however, to implement the receiveMessage() function, and must pass an Model to the superclass constructor. Also note that the ShipView stores a (const) pointer to its associated Ship object: Views can see and read its Model (but not alter it).

Example representations

View objects are similar to the Observer design pattern and hooks a model. Typical representations are

  • The graphical model (3D model, each individual unit)
  • An iconic representation (regimental banner, attached to formations rather than individuals)
  • Audio (a helicopter constantly playing Ride of the Valkyries)

Controller

Note! That discussed here is the future MVC architecture of WARTBED. Atm the client-server design has yet to be implemented wherefore the MVC diagram is as above.

In real-time tactics games, no units are directly controlled by the player. Instead, all game objects are interacted with through orders. Therefore, the task of the Controller layer is to read input (from players, network or AI) and dispatch orders.

In WARTBED the Controller is two-fold. The server-side Controller is the Session class. A Session contains an universe of models and a set of subscribing actors. The client-side Controller subscribes to a server and contains a tableau of views representing a universe, about which it really knows nothing beyond what the server-side controller relays. The client-controller makes requests to the server-controller, which in turn interacts with the universe.


 Views            Actors        ~      Server            Models
                                ~      session          (universe)
+---+            +---------+    ~
|   |-+   <----- |         |    ~
+---+ |-+ -----> |  Contr. | <--.
  +---+ |        |         |     \
    +---+        +---------+    ~ \   +---------+        +---+    
                                ~  \  |         |        |   |-+    
                                ~   > |  Contr. | -----> +---+ |-+
                                ~  /  |         |          +---+ |
+---+            +---------+    ~ /   +---------+            +---+
|   |-+   <----- |         |     /
+---+ |-+ -----> |  Contr. | <--ยด
  +---+ |        |         |    ~
    +---+        +---------+    ~
                                ~
                                ~
  Application-side              ~       Server-side
Personal tools
communication