Friday, December 27, 2013

Tank Battle Field HTML5 Game #4: The Object Model

Today's post is about the structure of Tank Battle Field game. Its object model.
Object model defines how objects are related to each other and determines the interactions with each other.

Tank Battle Field object model has two aspects. The containment model and the hierarchical one.

The containment model
As you can see in the picture below the objects are contained in a logical manner.



At the top there is the "Game" object which constitutes a global container which includes all other objects that are intrinsic to the game. It also constitutes a single entry point.
The "Game" object contains the following important objects:


  1.  "Model" object: defines the game logic and abstracts away logic from graphical representation. In turn it cotains
    1. "Field" object, that represents the terrain or the theater in which the game takes place. The aim of this "Field" is to set the dimensions, background and relief.
    2. "PrimaryTank" is the main tank of the game. The one controlled by the player.
    3. "Buildings" is a object containing a collection of buildings. It has also the role to render them and make necessary calculations related to their positioning on the screen.
    4. "Enemies" is the collection that contains the enemy units. This collection plays a role in coordinating AI enemy units movements.
  2. "Graphics" object contains all what is necessary for rendering the game on the screen. Among others it contains:
    1. "context" object which is a direct reference to the graphical device context provided by HTML5.
    2. "layers" array that contains the layers which will be displayed on the screen using the z-index order.  
    3. "layer_ground" object has the lowest z-index order and thus it is displayed the first. It contains the background, and the field details as well as borders.
    4. "layer_objects" object is the layer that contains static objects such as buildings. It is displayed second, over the "layer_ground".
    5. "layer_units" object is responsible of rendering ground military units including friend and foes.
    6. "layer_projectiles" object will contain transient objects such as shells, missiles, rockets as well as explosions. These objects are added to this layer at creation time then are removed when they expire.
    7. "layer_high" object will contain all flying machines like airplanes.
    8. "layer_widgets" object has the highest z-index order and is drawn last. It is responsible of displaying widgets on the screen such as a mini-map, primary tank status, notification messages or chats etc..
  3. "Settings" object is where the game is configured, in terms of control keys, navigation mode etc. For the moment it contains "Navigation" and "Keys" objects for setting the navigation mode and the control keys.
  4. "Res" objects contains resources needed by the game. Such as images, sounds etc...

The hierarchical model
Although that Javascript is not Object Oriented language, the Tank Battle Field game uses commonly known tricks to simulate class hierarchy and inheritance. The inheritance logic is hand crafted and does not use any library in order to keep it simple and minimal.
The concept of class does not exist in Javascript, everything is object but since hierarchy of classes is simulated in this section, the terms "class" and "object" refer to the same entity.



All objects in the game inherit from one super class which is ModelObjectClass. This gives the ability to get and set data and have an ID.

Objects that have dimensions, locations and rotation settings are of type ModelLocatableObjectClass. Note that the setX()/getX(), setY() /getY() coordinates functions represent the center of the object while the getTop(), getLeft() represent the top left corner of the object. It is also important to note that dimensions terms are not exactly the same as one might expect. Actually the width is the horizontal distance following the x-axis, the length is the vertical distance following the y-axis (which normally used to be called height), and height is the elevation from the ground following the z-axis. It is true that this is a 2D game, however the height (z-axis) will play a role.

Moving objects inherit from ModelMoveableObjectClass and have linear and angular speed, as well as acceleration.

VehicleClass contains commands to move forward, backward and to turn left and rights. It has also an import set of functions that determines how the vehicle will behave and how it is going to be rendered on the screen.

TankClass inherits from the VehicleClass and contains a turret object.
Other objects such as BuildingClass and Shell make use of this hierarchy of classes.

Initialization and data
Objects in the class hierarchy are instantiated using the new keyword, however the initialization does not take place inside the constructor, but by explicitly calling init() method and passing to it an arbitrary data object that each class might be expecting.
The reason for this approach is purely technical. Actually when instantiating an object using new keyword, the whole hierarchy of objects is instantiated and linked together via the __proto__ property.
So after the instantiation and the linking are done then it is possible to initialize using the init() method.

The data object given as parameter in the call to init() method, is used as momento design pattern, in the sens that it is used to save the state of the object so it can be saved or transferred via network in a multiplayer game.

Game loop: updates and rendering
As it is known by now, the game loop is a never ending cycle of tasks that is executed sequentially.
The loop reads the input of the user, calls updateModel() function on every object in the graphic layers. This method updates the internal state of the object, such as location, direction, health, etc...then the loop calls renderGraphics() on each object to draw itself on the screen, and finally updateModelAfterRendering() is called to update the state after the rendering phase. One example of the usefulness of the updateModelAfterRendering() method, is to reset the "fire" flag of the tank which was set by the updateModel() method and drawn by the renderGraphics() method.

Demo
That's it for now, as usual you can check the demo by going to http://tankbattlefield.eu.pn


No comments:

Post a Comment