View Architecture
Documentation

Jonathan Lugo

May 11, 2005

1

Table of Contents

Table of Contents

1Introduction

1.1Overview

1.2Design Goals

2Components of the Framework

2.1Abstract View

2.2SkyNet View

2.3View State

2.4Devices

2.5Terrain Block

2.6Graphics Objects

2.7Media Packages

2.8Action Commands

3Device Framework

3.1Creating and Loading a Device

3.2Existing Devices and How They Work

3.2.12D Device

3.2.23D Device

3.2.3Others

4How View Relates to the Model

4.1Entities and GUIDs

4.2Adapter to the Model

4.3Proxy Game Object

5Terrain

5.1Model vs. View

5.2Separation of Terrain

5.3Representation to the Devices

5.3.1As a Matrix of Terrain Tiles

5.3.2As a Collection of Area Mappings

6Possible Changes or Additions

6.1IArea Interface Changes

6.2Terrain Block Optimizations

6.3Action Commands

6.4Media Package Change Event

1

1Introduction

1.1Overview

The View architecture works off of a Service Oriented Architecture (SOA). By this we mean that the view serves as a sort of service that fires view-related events to a collection of devices, each uniquely designed to interpret the information. In addition to the firing of events, this architecture keeps a view-related state that is accessible by all of the devices. This state comprises all the information needed to visualize the world in a sort of snapshot. The view in general is designed to represent a collection of entities each of which are identified by a GUID. These entities are either treated like terrain or like a free body existing above the terrain. Working together, the view, the state and all the devices make up a powerful framework for representing the game to the user.

1.2Design Goals

When designing the view, we had two main goals in mind. The first goal we had in mind was modularity and abstraction. Our design strictly follows the MVC pattern by requiring that all model-view communication take place through a set of adapters. The media package framework allows the model to specify how the entities are to look without actually dealing with the rendering process at all. Not only does the model not conceptually deal with any view information, but there exists no project dependency on the view assembly in any way. In other words, if the view project does not compile, the model should not be affected at all.

Our second goal was flexibility. We designed the view architecture to be highly extensible. One would not need to recreate the View architecture in order to visualize the game in a different way. In order to add new functionality to the view, the programmer may need to add new methods either to the adapter interfaces and the view state or to add new events to the view that can be fired to the devices. This view architecture has proven to be flexible enough to handle massive changes in the Model without requiring the developers to change much in the view’s components. In fact, during the process of designing the SkyNet framework, the model was rewritten three times. Each time, we were required to make only minor modifications to the view’s adapters and public methods.

2Components of the Framework

2.1Abstract View

The abstract view (AView) is responsible for defining which events may be fired to the devices. It is also responsible for managing the various devices that are subscribed to listen to those events. Lastly, the view serves as a call-back for the devices in order for the devices to be able to change something in the view’s state.

Each event consists of four (4) components:

  • A void delegate definition with the sender and an event argument as its parameters,
  • An Event Argument Class Definition used in the parameter list of the event delegate,
  • A public event definition in the AView to which a device may register an event handler, and
  • A protected method that allows subclasses of the AView to fire the event.

To add a new event to the framework, it is best to copy an existing event and change its name.

The abstract view also keeps a handle to the main form of the client application. An instance of a windows form can be generated from the handler by calling Form.FromHandle(view.GetWindowHandler()). A device can also hide the form by calling view.HideForm().

One of the special events fired by the AView is a tick event. This event is a simple event fired periodically. A rendering device for example might listen to this event in order to query the view state for the current snapshot of the game.

The source code for the AView and all the events can be found in:View\AView.cs.

2.2SkyNet View

The SkyNetView is an instance of the AView. This instance is primarily responsible for handling possible requests from the model. The SkyNetView offers a series of methods that loosely correspond to the methods found in the IViewAdapter interface found in the AssemblyController project. Many of these methods deal with changes that occur with the entities in the game such as location. Other methods deal with general features such as unit selection or the displaying of ActionCommands. If the view should support some new feature requiring a change to the adapters, this would be the place to add the new method.

The SkyNetView also is responsible for making the calls to its base class to fire events when appropriate. Also, as a subclass of AView, it is responsible for implementing the callback functions exposed to the devices. The SkyNetView keeps the view state as a private field. Often the interface methods will call a method in the view state then call on the base AView to fire the corresponding event to the devices.

The source code for the AView and all the events can be found in:View\SkyNetView.cs.

2.3ViewState

The state of the view is defined in SkyNetViewState which extends an abstract class namedAViewState. The AViewState class acts simply as an interface for the concrete view state. The view state’s main purpose is to manage the information pertaining to each game object as well as the terrain. All stored information acts as a snapshot of world in a format that is usable directly by the devices.

For each non-terrain entity that the model has ever referenced through the interface methods, there exists a single GraphicsObject that stores information about it. Devices have access to these graphics objects through the view state directly.

The terrain is managed by a helper class called the TerrainBlock, which will be discussed below.

The source code for the abstract class is located inView\AViewState.cs, and the code for the concrete implementation is in View\SkyNetViewState.cs.

2.4Devices

A device in the view architecture is defined by the IDevice interface. This interface requires only a few methods from the device pertaining to initialization and termination.

We designed this interface that way to make devices highly customizable. The most interesting feature about the devices is that they are loaded by SkyNet dynamically when the client application is started. The devices are explained in depth in a later section.

2.5Terrain Block

The terrain block serves as the manager for the terrain objects. Its primary means of representing the terrain is as a grid of tiles that are each covered with a specific type of terrain. The terrain block keeps a mapping of IAreas to the type of terrain that area encompasses as well as a matrix of terrain types. These two representations are described in detail in a later section.

The code for the TerrainBlock can be found in:View\Common\TerrainBlock.cs.

2.6Graphics Objects

The ViewState keeps information about each entity specific to how the entities are to be displayed. This information includes location in the form of a bounding rectangle, its media package,

2.7Media Packages

The media package was designed as a means of abstracting the representation-specific information out of the model so that the model could describe how an entity should look with a single name. This name corresponds to a zip archive that is read by objects named MediaPackage in the view. These archives are loaded on demand by the view, so they can be introduced dynamically while the game is currently running. This framework is definitely one of the View’s greatest sources of flexibility and independence from the model.

A media package to the View is an object that acts as a sort of file system for one particular entity. Each object that can be rendered has one media package that determines how the object should be displayed. The devices are able to retrieve both properties and file paths from the package using a key-value approach. If a definition for a given key is not found within a media package, then the media package will generally return null.

The keys defined within a media package are specified by convention by the devices that use the media packages. For example, the 2D rendering device assumes that the file path returned by the media package for the key image corresponds to an image file of the icon used to represent the entity on the map.

The media package framework is specified in detail in a separate document titled the Media Package Spec.

The classes that make up the media package framework can be found in: View\MediaPackage_New.cs.

2.8Action Commands

Action commands are another means of abstraction between the model and the view. Rather than abstracting the appearance of an entity, these commands allow the user to invoke commands on the entities in the world without the view having any part in the execution of the action itself. The action commands are specified and managed entirely in the Model, so new actions can be designed without altering the View at all.

The model may send a collection of IActionCommand objects to the view through its view adapter. The action command interface requires each command to have a name that can be used as a caption for the button in the View. The action command also has properties stating whether it requires the user first to select either an area of the map or an entity’s icon in the selection panel. If neither is required, simply clicking the action command should cause the device to send the instance of the corresponding IActionCommand object back to the model through the SendCommand method in the request adapter. If the user clicks an action command that requires a selection, the device waits for the user to click on the map or click on an entity’s icon. The command as well as the extra information is sent back to the model through a similar method in the adapter.

The IActionCommand interface is defined in: View\AdapterInterfaces.cs

3Device Framework

3.1Creating and Loading a Device

As stated before, a device is simply an object that implements the IDevice interface. It is common for one device to compile into its own dynamic link library (dll), but it is also possible to compile multiple IDevices into a single library. Currently in order for the SkyNet client to load a device, a copy of the device library must be put into the AssemblyController\devices folder in the installation directory.

Once a device is dynamically loaded into the system, the view will first call the Initialize method. This method is where the device should perform any operations required before listening to any events from the view. Once the device is initialized and the view is ready to begin execution, it will call SetView on the device. In this method, the device is expected to add event handlers to any of the view’s available events. At this point the device should be fully functional.

Each event fired by the view will include an instance of the AView that sent it as a parameter. The device then is able to retrieve the view state or one of the adapters from which to make requests.

By convention, each device assembly should exist in the solution defined in View\View.sln. This convention was started because some of the devices depend on DirectX and not all developers had the DirectX SDK installed on their machines. In order not to require that all developers install any extra software, the devices were moved to a separate solution.

3.2Existing Devices and How They Work

3.2.12D Device

The 2D device renders the world using the normal GDI graphics framework provided by the .NET framework. All the action commands are displayed as windows buttons along the top of the frame below the main menu. The stats of an object are displayed in a simple text layout on a left-hand panel. When an area of the map is selected, a panel on the bottom of the form displays a clickable icon for each of the entities that can be selected in area. Clicking on one of those icons causes that entity to be selected alone.

This device paints the icon of each entity as specified in that entity’s media package under the key image. The terrain is rendered as a grid of tiles. It retrieves the terrain from the ViewState in the form of an array ITerrainObjects, which will be explained in a later section. The ITerrainObjects contain a reference to the media package that holds the icon of the terrain to display.

The 2D device also uses the tick event in the AView to refresh the objects currently being displayed periodically.

3.2.23D Device

The 3D rendering device uses DirectX to create a 3D visualization of the game. The entities on the map are rendered as if they were each a center-folded paper with the entities icon painted on the front. The device can zoom in and out and move the camera around the map. It allows the user to select entities by drawing a circle around them with either a tablet’s stylus or the computer’s mouse.

3.2.3Others

There are several other devices that use other technologies such as the sound device. The sound device pulls sound files off of the local computer to play to the user. Some of the other devices deal with input from the user.

One device that is available for developers to use is the debug console. The debug console displays log messages logged from within the program using the Logging utility. It also offers a graphical way to browse through the objects that exist in the system.

4How View Relates to the Model

4.1Entities and GUIDs

In SkyNet, both the Model and the View identify each entity with a globally unique ID (GUID). The GUID used in the model to reference an entity would be the same GUID used in the View to identify the correct object kept by the ViewState to modify. When Model’s ViewAdapter calls on the view to move an object or change it in any other way, it includes the GUID of that entity as the first parameter.

The ViewState and Terrain Block both keeps hash tables mapping a GUID to the objects they manage. If the GUID referenced by the model does not appear in either the view state or the terrain block, then the view must query the Model for relevant information regarding the entity referenced by that GUID. This process is described in the section labeled Proxy Game Object.

4.2Adapter to the Model

The IRequestAdapter is the interface for the model adapter. This adapter is used primarily by the devices registered with the View to communicate user input to the Model for interpretation. While the interface for the adapter is defined in the View project, the implementation of that interface can be found in the AssemblyController project. This allows the view to call on the adapter without creating a dependency between the View and the Model in any way. Only the client controller is dependent on the Model or the View.

Please see the in-code documentation for more details on the features supported in the model adapter. The IRequestAdapter interface can be found in: View\AdapterInterfaces.cs.

4.3Proxy Game Object

The proxy game object was designed in the spirit of maintaining the mutual independence shared by the model and view. By design, the view caches specific information about each entity referenced by the model. We do not, however, require the model to keep a record of what information had been sent to the view. Instead, the view is made responsible for querying the model for any information it requires about a specific entity. The view makes this query each time the model requests for the view to modify the information of entity whose GUID is not mapped in the ViewState.

According to this design, the view retrieves this information through the GetProxyObject method of the adapter. The model then returns an instance of the IProxyGameObject interface. These objects are containers for any information that the view might need in order to render an object. Included in this interface, among other things, are its location, owner, and media package. Once the view is given the proxy object, it can then generate the corresponding graphics object or terrain area.

The method by which the view distinguishes between graphics objects and terrain is discussed below under Separation of Terrain.

The request for the proxy object is made in the SkyNetViewState in the method named AddObjectIfNeeded.

The IProxyGameObject interface can be found in the shared user interfaces in: Common\SharedUserInterfaces\IProxyGameObject.cs.