Showing posts with label Game. Show all posts
Showing posts with label Game. Show all posts

Saturday, August 27, 2011

Baddies 4–Saving

Introduction

Objective

The objective of the saving system is, given a node, any node, serialize it completely and automatically without having to go through the mistake prone method of each time we add a member, having to remember to update the load and save functions.

To this aim, we will use the IntermediateSerializer class, with a few auxiliary classes to handle logical exceptions in our design and in the IntermediateSerializer class.

Considered options

There are several options when saving the game in XNA, the 3 more common ones are serializing using the XmlSerializer class, serializing using the IntermediateSerializer class, and finally, saving with a BinaryWriter class.

The reasons why I won’t use the XmlSerializer are explained in the conclusion in this post, so I won’t expand on it. The BinaryWriter, on the other hand, requires knowing the data you are going to read beforehand, as it’s in binary format and you need to select “chunks” of specific lengths to be interpreted as variables. This does not work well with the initial objective of the saving being automatic or not having to make custom save / load functions for each class. This leaves us with the IntermediateSerializer.

Serialization

Serializing with the IntermediateSerializer

The use of the IntermediateSerializer is best documented in these 2 articles by Shawn Hargraves: Teaching a man to fish, and Everything you ever wanted to know about IntermediateSerializer.

On the positive side, it’s simple (doesn’t require the multithreading gymnastics for the container that the XmlSerializer needs), and highly customizable (adding private members, excluding public members, setting members as references, dealing with collections, etc…). On the negative side, it only works on windows, but that’s an acceptable inconvenient, and it needs the full .Net Framework 4.0 instead of the client version (explanation).

Working with the Node

For our specific situation, we want to serialize a subtree of nodes, this nodes being any class that might derive from node. For example, we might have a situation like this:

Saving1

This diagram represents that there is a root node “Scene” with two added child nodes “Camera” and “Map” (ignore the UML notation, it was the only editor at hand). We want to serialize Scene without caring about what hangs from it and have everything serialized to XML.

The first attempt at serializing this launched an error of cyclic reference, as each Node has a pointer to it’s parent. To solve this we declared the parent member of a node as a ContentSerializerAttribute.SharedResource so instead of storing the parent, it just stored a reference to this. This serialized, but upon closer investigation of the XML code it became apparent that this generated “shadow” parents, as we had both the original parent that called the serialization, and the one each child was referencing, resulting in something like this:

Ssaving2

That’s because the children of each node are not references themselves, if they were we’d just have a very slim XML tree with just references, no content, and then the references at the bottom. Something like this:

Code Snippet
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <XnaContent xmlns:Utils="Baddies.Utils"
  3.             xmlns:Scenes="Baddies.Scenes"
  4.             xmlns:Nodes="Baddies.Nodes">
  5.   
  6.   <!-- Root of the tree-->
  7.   <Asset Type="Utils:NodeSerializer">
  8.     <root>#Resource1</root>
  9.   </Asset>
  10.  
  11.   <!-- References-->
  12.   <Resources>
  13.  
  14.     <!-- Scene node-->
  15.     <Resource ID="#Resource1" Type="Scenes:Scene">
  16.       <Name>Node</Name>
  17.       <ParentRelativePos>false</ParentRelativePos>
  18.       <Children Type="Utils:SharedResourceDictionary[int,Nodes:Node]">
  19.         <Item>
  20.           <Key>0</Key>
  21.           <Value>#Resource2</Value>
  22.         </Item>
  23.         <Item>
  24.           <Key>1</Key>
  25.           <Value>#Resource3</Value>
  26.         </Item>
  27.       </Children>
  28.       <Visible>true</Visible>
  29.       <Position>-0 -0 -0</Position>
  30.       <Parent />
  31.     </Resource>
  32.  
  33.     <!-- Camera node -->
  34.     <Resource ID="#Resource2" Type="Baddies.Camera">
  35.       <Name>Cam</Name>
  36.       <ParentRelativePos>false</ParentRelativePos>
  37.       <Children Type="Utils:SharedResourceDictionary[int,Nodes:Node]" />
  38.       <Visible>true</Visible>
  39.       <Position>0 0 0</Position>
  40.       <Parent>#Resource1</Parent>
  41.       <W>673</W>
  42.       <H>442</H>
  43.       <DisplayBorder>true</DisplayBorder>
  44.     </Resource>
  45.  
  46.     <!-- Map node -->
  47.     <Resource ID="#Resource3" Type="Baddies.Map.MapGrid">
  48.       <Name>Map</Name>
  49.       <ParentRelativePos>true</ParentRelativePos>
  50.       <Children Type="Utils:SharedResourceDictionary[int,Nodes:Node]" />
  51.       <Visible>true</Visible>
  52.       <Position>0 0 0</Position>
  53.       <Parent>#Resource1</Parent>
  54.       <DisplayTerrain>true</DisplayTerrain>
  55.       <DisplayGrid>true</DisplayGrid>
  56.       <DisplayCollisionMap>false</DisplayCollisionMap>
  57.       <MapWidth>16</MapWidth>
  58.       <MapHeight>16</MapHeight>
  59.       <TileSize>16</TileSize>
  60.       <Tiles>
  61.         <!-- Map tiles excuded for brevity -->
  62.       </Tiles>
  63.       <tileSetTex>
  64.         <Name>TileMap/tileset1</Name>
  65.         <contentRef>#Resource3</contentRef>
  66.       </tileSetTex>
  67.     </Resource>
  68.     
  69.   </Resources>
  70. </XnaContent>

To achieve that structure we need to set the children of the Node as references as well. The children of each node are kept in a dictionary, so to solve this “dictionary of shared resources” dilemma, I wrote a class to handle it, explained in this article. This is one of the few exceptions to the “not writing custom code for saving different data” but only because the IntermediateSerializer doesn’t support these type of dictionaries out of the box.

Another exception is that even if we mark everything as references, the first node to be serialized is not considered a reference because it’s the starting point of the serializer. To solve this I made a wrapper class to serialize that only contains the root node, as a reference.

Code Snippet
  1. /// <summary>
  2. /// Auxiliary class that takes care of
  3. /// the serialization of a Node tree.
  4. /// <remarks>
  5. /// Works by having a reference to the
  6. /// node and serializing itself, so the root
  7. /// node is also regarded as a reference.
  8. /// </remarks>
  9. /// </summary>
  10. public class NodeSerializer
  11. {
  12.     /// <summary>
  13.     /// Root node to serialize.
  14.     /// </summary>
  15.     [ContentSerializerAttribute(SharedResource = true)]
  16.     private Node root;
  17.  
  18.     /// <summary>
  19.     /// Serializes a node to XML.
  20.     /// </summary>
  21.     /// <param name="node">Node to
  22.     /// serialize.</param>
  23.     /// <param name="name">Name of the
  24.     /// file to serialize to.</param>
  25.     public void Serialize(Node node, string name)
  26.     {
  27.         this.root = node;
  28.  
  29.         XmlWriterSettings settings =
  30.             new XmlWriterSettings();
  31.         settings.Indent = true;
  32.  
  33.         using (XmlWriter writer =
  34.             XmlWriter.Create(name, settings))
  35.         {
  36.             IntermediateSerializer.
  37.                 Serialize(writer, this, null);
  38.         }
  39.     }
  40.  
  41.     /// <summary>
  42.     /// Deserializes the XML file provided
  43.     /// and returns the created node.
  44.     /// </summary>
  45.     /// <param name="name">Name of the xml file.</param>
  46.     /// <returns>Node serialized in that file.</returns>
  47.     public Node Deserialize(string name)
  48.     {
  49.         Node node = null;
  50.         XmlReaderSettings settings =
  51.             new XmlReaderSettings();
  52.  
  53.         using (XmlReader reader =
  54.             XmlReader.Create(name, settings))
  55.         {
  56.             NodeSerializer serial =
  57.                 IntermediateSerializer.
  58.                 Deserialize<NodeSerializer>(reader, null);
  59.             node = serial.root;
  60.         }
  61.  
  62.         return node;
  63.     }
  64. }

The last exception comes with the Texture2D class. I wanted that the serializing of a tree included the actual textures used, as not to have to do a “second” step when loading. This has 2 problems. First, the texture is binary data, so kind of difficult to serialize in xml. Second, the texture has a reference to the ContentManager that loaded it, so it creates a circular dependency that there is no way to solve, short of dumping the use of the ContentManager all together.

To work around these 2 issues I created a Texture2D proxy class, as shown here:

Code Snippet
  1. public class Texture2DProxy
  2. {
  3.     /// <summary>
  4.     /// Reference to the the parent class
  5.     /// that holds a ContentManager to load
  6.     /// this texture.
  7.     /// </summary>
  8.     [ContentSerializerAttribute(SharedResource = true)]
  9.     private IContentHolder contentRef;
  10.  
  11.     /// <summary>
  12.     /// Texture we wrap.
  13.     /// </summary>
  14.     private Texture2D texture;
  15.  
  16.     /// <summary>
  17.     /// Name of the texture in the
  18.     /// ContentManager.
  19.     /// </summary>
  20.     private string name;
  21.  
  22.     /// <summary>
  23.     /// Initializes a new instance of
  24.     /// the Texture2DProxy class.
  25.     /// </summary>
  26.     /// <param name="contentRef">
  27.     /// Content manager that will be
  28.     /// used for loading.</param>
  29.     public Texture2DProxy(IContentHolder contentRef)
  30.     {
  31.         this.contentRef = contentRef;
  32.         this.name = string.Empty;
  33.         this.texture = null;
  34.     }
  35.  
  36.     /// <summary>
  37.     /// Initializes a new instance of
  38.     /// the Texture2DProxy class.
  39.     /// </summary>
  40.     public Texture2DProxy()
  41.     {
  42.         this.contentRef = null;
  43.         this.name = string.Empty;
  44.         this.texture = null;
  45.     }
  46.  
  47.     /// <summary>
  48.     /// Gets or sets the name of the texture.
  49.     /// </summary>
  50.     /// <value>Name of the texture.</value>
  51.     public string Name
  52.     {
  53.         set { this.name = value; }
  54.         get { return this.name; }
  55.     }
  56.  
  57.     /// <summary>
  58.     /// Gets or sets the texture of the proxy.
  59.     /// <remarks>
  60.     /// The Get method has lazy
  61.     /// initialization of the texture,
  62.     /// in the sense that if we have the
  63.     /// texture name and not the texture,
  64.     /// it loads it when we request the
  65.     /// texture. This is useful for when
  66.     /// we load a texture via serialization.
  67.     /// </remarks>
  68.     /// </summary>
  69.     /// <value>Texture that we wrap.</value>
  70.     [ContentSerializerIgnore]
  71.     public Texture2D Texture
  72.     {
  73.         get
  74.         {
  75.             if (this.texture == null &&
  76.                 this.name != string.Empty)
  77.             {
  78.                 ContentManager man =
  79.                     this.contentRef.GetContent();
  80.  
  81.                 this.texture =
  82.                     this.contentRef.GetContent().
  83.                     Load<Texture2D>(this.name);
  84.                 
  85.             }
  86.  
  87.             return this.texture;
  88.         }
  89.  
  90.         set
  91.         {
  92.             this.texture = value;
  93.         }
  94.     }
  95.  
  96.     /// <summary>
  97.     /// Loads the selected texture.
  98.     /// </summary>
  99.     /// <param name="name">
  100.     /// Name of the texture to
  101.     /// load.</param>
  102.     public void Load(string name)
  103.     {
  104.         this.name = name;
  105.  
  106.         this.texture =
  107.             this.contentRef.GetContent().
  108.             Load<Texture2D>(name);
  109.     }
  110. }

What is serialized in the texture is the actual name of the texture, so afterwards we can load the name, and load the actual texture by request in the “get” field.  This makes for a simple method of loading the textures from xml, the only problem is a project can have many ContentManagers running, and we have no way of knowing which one is the one the texture is associated to. To get around this we create a IContentHolder interface.

Code Snippet
  1. /// <summary>
  2. /// Class that has a content manager.
  3. /// </summary>
  4. public interface IContentHolder
  5. {
  6.     /// <summary>
  7.     /// Returns the ContentManager
  8.     /// associated to this class.
  9.     /// </summary>
  10.     /// <returns>A ContentManager object.</returns>
  11.     ContentManager GetContent();
  12. }

The parent class that owns the texture implements this interface, and is required to pass itself to the texture as a reference upon creation. That way the steps when deserializing are as follows:

  1. When the serializer creates the parent class, the parent class creates the Texture2DProxy object and assigns itself as the ContentHolder.
  2. The deserializer fills the serialized data of the Texture2DProxy (the name of the texture),
  3. At some point, the game requests the texture for the first time, in the “get” field we see it’s not loaded yet, so we create it using the ContentManager of our parent, and we’re ready to go.

Thursday, August 11, 2011

Baddies 3–Editor

Showing the game in a PictureBox

The first hurdle when making the game editor with windows forms was getting it to render XNA in a form. For this I used a picture box and followed the tutorial at http://royalexander.wordpress.com/2008/10/09/xna-30-and-winforms-the-easy-way/ The only change I had to do was to make sure the back buffer size of the xna game was the same as the size of the picture box, otherwise weird stretching ensued.


 

Coupling game and form

There is a high coupling between both game and form in the editor, as this is the fastest and cleanest method of working the interaction between both of them. None of the two classes are intended for any reuse or generic use, so it’s the best decision. For this, we just store a reference to each other during the initialization of the program so they are linked, and provide methods to access whatever is needed.


 

Creating a map

Creating a new map is an essential part of the editor. I created a new form that took care of receiving all the necessary information and then launched an event with this data.
This event was caught by the main editor form and then passed on to the game class, where we just create a MapGrid node and add it to the root.


 

Loading a TileSet

To load a new tile set we create a dialog that uses the windows interface to load the required image file with the tileset. If the image is found, we create one TilePictureBox out of each bit of the image that is of tileSize x tileSize size and set it in the appropriate form container, so when the user clicks on one he can use it to draw.
Making a specific class instead of just using a normal picturebox was necessary to make the tiles react to the OnClick event.

Wednesday, August 10, 2011

Baddies 2.8–Map

The map is just a list of lists, holding all the tiles in a matrix. The only thing it has special is the fact that it holds the tileset image, with all the images of the tiles, as well as other extra graphics used for other drawing modes (for example the grid). When the map wants to draw the tiles (be it as the actual tiles, or the grid, or the collision) it passes the corresponding graphic to the tiles in their draw function.


The map tiles are not nodes because of the need to access them easily with a 2D coordinate system, and the special operations that we need to do with them. It’s one of the cases where efficiency is more important than following the tree structure.

Baddies 2.7–GUI Input Management

The game engine needs to accept input from several devices, mainly Xbox, Windows and WP7. For each of them a different input controller must be used.
The input device is an independent class, it has no power to actually do anything or change anything. Instead what happens is it interprets the input of the user using various means (selection boxes, touches, radial menus, etc.) depending on the device. Once it knows what the action is (select units in rectangle, interact with clicked position, etc.) it sends a message with all the relevant data, to be caught and acted upon by whoever is responsible.


Having a system like this prevents having lots of cases for the different controllers distributed all through the code, and also avoids duplication of work.


The basic idea is that the primary input of the user gets transformed into some kind of command with data that then the engine then interprets homogenously, without knowing who sends the message. Adding new input devices is therefore trivial, as the engine just receives messages of commands to execute.


As for the GUI elements themselves, they hang from the input device they are designed for (no sense having a selection box in the Xbox for example), and the input device object is always on the top of any other nodes so it gets the input / drawn first. The input device has a GUINode that is active at the moment. That’s the one which attempts to answer to the user event (say a keypress), if it consumes the event, that’s it.  If not, we send a message to the system, to see if any other node wants anything to do with that event.


Having the GUINodes independent of the InputDevice class makes it so if we want a standard GUI element (say a minimap), we just add the MiniMapGUINode to the InputDeviceNode, and we know it’s going to be on top, whereas if we want something more local (for example a speech bubble) we add it to the player node, and it’s going to be in the proper Z height, at the same as the player.

Tuesday, August 9, 2011

Baddies 2.6–Event Manager

In a tree architecture, getting the nodes to communicate without making a huge mess of links between nodes requires special attention. That’s where the EventManager comes in.


It provides a one or two way communication system among nodes in the system. The nodes don’t even need to know that the other node exists. It works on one to one and one to many modes with no difference.


The EventManager is a singleton, there is only one and shared by the whole system. Anyone can register a new event, with a specific name. Once an event has been added to the EventManager, anyone can register an EventHandler  to it, and anyone can trigger it. When someone triggers an Event, everyone who registered an EventHandler gets notified. As this system is built on the delegate system of XNA, it incorporates sending extra information along with triggering an Event, mainly arguments and who triggered it.


This works fine for general purpose messages (like print subtree, that orders the root node to print it’s subtree) or for messages that require a reply (someone asking for a content manager, just send an argument object with a content manager memberto fill, and check it in the sender class.)


The main issue with this system is security, as messages are not guaranteed to be answered, but the Debug.Assert function covers almost all the dead ends in this case.

Baddies 2.5–FSM and Scene

A FSMNode (finite state machine node), is a node with the special property that it has one active node, and that is the only one which gets updated and drawn. The FSMNode also has special methods to change the active node. A FSM is a pattern I find myself using a lot when I program games, so a generic Node-like FSM is a great deal.


Closely linked with the FSMNode is the Scene node. This is so because in any given game you have different scenes and only one of them active at any given time, so the FSMNode is the perfect place to hang SceneNodes. The one peculiar thing the SceneNodes have is a ContentManager, so the loaded content is local to each scene and when we swap scenes we don’t have to worry about what we load/unload. The common assets can be loaded in the Game ContentManager.


Seeing as the ContentManager class already caches and takes care of assets for us, there is no immediate need to make a resource manager and manage all assets globally. Again, we sacrifice a small amount of performance for simplicity of use.

That’s it for the specifics of those two classes.

Monday, August 8, 2011

Baddies 2.4–Camera

First off, to define what we mean by camera. My camera in this project is just a position in 2D space, a width and a height. It does not take care of rendering itself, and is independent of screen size.


The camera is a delicate element,  there are a lot of ways to implement it and a lot of variation in those ways. In this particular architecture is complicated because once we set up a camera, which by definition is a node, every node in the selected subtree needs to deal with it, and we want to avoid cluttering the draw function with a camera parameter that might even not be needed.


 

Methods I discarded

Using a singleton, easy to access from any sub node, very little security on who controls it, the game can only have one “view”, and it doesn’t fit in the spirit of the node based system. An easy patch.


Passing the camera by parameter on the draw, but this forces all draw routines to have a parameter they might not need (see GUI), creating an overloaded Draw is dangerous, as you let the user too easily forget to use the one with the camera. Another problem is even if you do it like this, you must position the camera somewhere, and it doesn’t make much sense to do so with a node, so we would have to add a special element to one of our nodes, which is the whole thing I was trying to avoid by using generic nodes.


Setting the camera as a static member of a main class, like the scene, and let anyone access it like that. That’s a more “local” version than the singleton, but it suffers from most of the same problems and a few more, like the variable can be accessed with no Scene created (BAD), and we mark just ONE type of node as capable of using the camera, thus limiting the use of the camera element.


 

Final method

The solution I found best is to derive the camera like just another node, that can be added anywhere. The node it is added to effectively takes on the camera’s position (by setting the position of the parent node to it’s negated position in every update of the camera), and that node and all the subtree it spans are displaced as required by just the normal draw mechanism, which includes adding the parent’s (now camera’s) absolute position to our relative position.


The other detail is we need a proper camera that is capable of culling. For this we implement a cull method in node, which does accept a Camera object, but is only used by the camera behind scenes, and only by those “affected” by a camera, thus removing the problem mentioned with overriding the Draw method. Every node can override this cull method to suit it’s needs, and the camera calls it every update, keeping only a list of elements that are inside the camera as the ones ready to draw.


That’s basically it.

Baddies 2.3–Node Updating

When dealing with a node – tree architecture, there are several functions that need to be called recursively down the tree (mainly draw and update, but there are others, such as cull, exit, etc…) AND they need to be overridden in base classes, normally by the user.


Implementing either one of these things is trivial, but doing them together and while keeping the system secure from any slips by the user is not. One possible solution is to remind the user in the documentation that when he overrides update, he must always call update on all the children of the node. But this is playing with fire, eventually someone is going to forget, and put a sneaky bug in the system.


The easiest solution I’ve come up with is putting 2 functions of each: Update and NodeUpdate, Draw and NodeDraw… where the single word function is an abstract function for the user to override, and the double word function is the one actually called in the tree update, which calls to the simple function, does some extra necessary stuff and updates the children.


This method is transparent to the user, who just needs to override the function as expected, and doesn’t let him fuck up anything important. Similar solutions might be made with delegates or callbacks.

Saturday, August 6, 2011

Baddies 2.2–Node Positioning

Each node in the game tree has two possible options when drawing, either relative to the parent node, or with absolute coordinates respect to the screen. This is done as some things like the GUI need to be relative to the screen, regardless of where they are hooked up in the game tree, and for most  of the compound objects (like a player with a sword and a shadow) it makes it a lot easier if you just put the sword and shadow relative to the player and forget about it (when the player moves, the sword and shadow will as well.)


But this apparently simple system raises some questions. First and foremost, do we keep 2 sets of coordinates? We keep the absolute coordinates and (needed for drawing from everyone) and the relative ones? Or we recalculate one of them?
And if we recalculate one of them, do we do it on demand? Or every cycle?
And finally, how do we keep this coordinates “safe” so there are no hidden bugs when the user modifies one set and not the other?


The answer I came with is to keep just the relative coordinates as position, and a variable parentRelativePos, which indicates whether the coordinates are relative to the parent post or not.  No double set of coordinates because data replication is a sure way for innocent bugs to creep invisible into the system, and still attack months later in the development. So by elimination we end up with just one set of data.


As for recalculating them, it will be apparent by now that for the vast majority of nodes, it is only needed to recalculate the absolute position it when drawing (for those relative to the parent position), and not at all for the rest (the not relative to the parent position nodes can just draw with their normal position variable, as it’s absolute coordinates).


So, the problem boils down to recalculating when drawing, or when the position changes. Doing it when the position changes is viable ONLY if we keep the position variable private, and all changes to it go through an accessor method that updates the position and the “drawPosition”, but that is still a possible nest of bugs (maybe we need to open the level of security of position to protected, or have some unacceptable access times in derived classes from node, and this is again giving a user full access to fuck up). So we recalculate the drawPosition every draw cycle, by adding the parent drawPosition to our own position. Just 3 additions per cycle of extra cost, not so bad when the alternative is ninja bugs all over the code.


In conclusion, one variable that is position, the Boolean parentRelativePos indicates whether it is a relative or absolute position, and the drawPosition is updated every draw cycle from our position and our parents drawPosition.

Friday, August 5, 2011

Baddies 2.1–Nodes and Tree Architecture

The game engine follows a tree based architecture, that is, all elements are nodes, and any node might be added as a child to someone else. Every node might have at most one parent. Specific cases and conditions can be dealt with from each individual node.
There are three main reasons I’ve opted for this architecture, to the point of redoing several months of work.

Low coupling

Ideally, in any computer science project there is low coupling and high cohesion. This means, in an OOP environment, that the best situation would be one where no class needs to know about any other to function. This is a goal worth pursuing, even though it is not always reasonable to stick to this guideline, as you need to sacrifice other factors (speed, mainly) to achieve it, and that is simply not an option in a game project.
But, low coupling is good, as I’ve found out in countless projects, and most games can be designed as to minimize coupling and be all the better for it. And a tree based architecture is awesome for this because since any node can be added to any other node, you can never assume a node will have a particular parent on whose internal workings it relies, therefore you must always write modular code.
This, of course, takes a toll on efficiency and forces us to use several communication mechanisms we shall see later.

Avoiding repetition

In almost all game projects I’ve done, I find the objects follow a hierarchical structure, and from each parent object I usually have to call the “Enter, Update, Draw, Exit” functions of all of its children, for which I have to create individual variables, and so on. There is a lot of duplicated effort for each object you add to a class.
A tree architecture solves all this by putting all items as nodes, so they can be stored and treated in a generic way. No more remembering to modify half the class when I add a new variable or remove it.
The down side is that accessing elements in a class from the outside is slower as a search of some sort, or even a direct access to the index of the element requires extra work, and therefore time.

Empirical experience

I worked with the Cocos libraries in a couple of projects and found it to be a delightful system, working fine in the limited environment that is a smartphone.

Conclusion

All in all, it’s a good system for games that don’t try to squeeze the processor dry, and like a clean easy to maintain system.

Thursday, August 4, 2011

Baddies 1.3–Project distribution

Reflecting the new architecture explained in the previous article (Baddies 1.2 – Architecture), the whole project was divided in 4 MVS projects, though within a single solution.


Microsoft Visual Studio is a superb tool for this kind of things and as long as you don’t put recursive references of a project within a project, it gets the job done very easily.


The project structure ends up looking like this:

  • Core
  • Game
  • Editor
  • Content


The Content project holds the content files (graphics, audio, and so on) used by any of the other 3 projects, as the amount of non-shared assets in the whole solution is relatively small compared to the total amount of assets.
The references between all the projects are the logical ones, with the game and editor using the core and content.

ProjDep

This setup of projects is interesting to remember as it’s common to a lot of game projects (tough instead of the editor there might be another secondary tool for the game).

Wednesday, August 3, 2011

Baddies 1.2 - Architecture

The initial project was to make a single complete game, and the architecture reflects this. It’s a tree based system where almost every element of the game is a node, and any node can be attached to another. The architecture is inspired on the one implemented very successfully by the Cocos2D libraries.
Here is a class diagram in a simplified UML notation, with each class linked to where it was going to be used later on, instead of normal UML composition, as any node can be linked to any node as need arises.

Architecture 2

After the start of the project, it became apparent however that an editor was needed for the game. The editor shared many of the classes of the original game, thus the need for a library of common classes that both projects (game and editor) needed to access. This evolved into 3 separate architectures, as follows.

Core architecture

The core architecture has all the classes of the core engine and their dependency to the Node class. Classes in green are XNA classes.

Architecture Core

Game architecture

The game architecture has the relationship of the core classes among each other to create the actual game. All the white classes are from the core library, while blue classes are specific to the actual game.

Architecture Game

Editor architecture

The editor architecture is mainly one editor form and one game editor closely coupled via a picture box form. Inside the game editor we build the actual game to be shown, and in the editor form we create the GUI via windows forms.

Architecture Editor

Sunday, July 17, 2011

Baddies – 1.1 Introduction

This is the first of a series of articles documenting the creation of the Baddies project.


The Baddies project is a game idea I have been musing for quite a long time, and as I have found that an initial all-encompassing game architecture to be well beyond my means, I shall attempt to do it in an incremental fashion (tough following an initial architecture diagram), documenting each design decision whilst coding. What better way to do this than by blogging about it?


The Baddies game is a tactic based game, with heavy focus on the minions the player can control and some base building. The story of the game also plays a very important role in the final version.

It’s a game aimed for Xbox, windows and Windows Phone 7. For simplicity I shall focus first on the windows version and leave the other 2 for later on. I build on the XNA framework for the code of the game. I work on Microsoft Visual Studio 2010 as my IDE, and with subversion as my backup version storage.


I will use this post as an index for the rest of articles in this series. The articles will only focus on the code side of this project tough. Any story or graphics news will have to wait till almost completion of the game.


Tuesday, January 19, 2010

Caged

Caged is a RPG game written by me and my team* in our first year (2007) at the university. The game development was difficult as hell, and fun as hell as well. I learnt to design the architecture and lead a team, while teaching the team to code. One of the most rewarding experiences in my life.

CagedMenu CagedGame

The game is written C++, using SDL and TinyXML as only support libraries. We worked on the Dev-C++ IDE and SVN. It has 20+ game levels.

Features

  • A scripting engine which feeds cut-scenes and dialogues from XML
  • A sound engine based of SDL_mixer
  • AI for the bots, with path finding, decision making and message system.
  • Core, with entity manager, event system, clocks and timers, log system, resource manager, FSM…
  • Physics with collision detection and some neat force driven steering behaviors.
  • Graphics. SDL isn't meant to be used as a Gfx engine, so the camera,  the GUI, and so on was also fun to make.
  • Integrated game editor, to make all the xml maps for the game.
  • Life-saver debug mode xD

CagedEditro CagedDebug

In the end, one year and 200k lines of code later, the game was completed. It won 2nd place in two different contests, “tu tambien puedes” and “CDV 2008”.

Just wanted to share my first game with the world :) Game SVN here and direct download here.

Team*

Programming
  • Jaime (Ying) Barrachina
  • Victor (CyanCrey) Villanueva
  • Maria (Chuel) Cabezuelo
  • Catalin (K_ta) Costin
  • David (Coper) Garcia
Art

(You know who you are ;) )

  • Jusep
  • Alberto
  • Kiwi
  • Yuna (Script writer)
Special thanks
  • Javier (NeoM) Belenguer (Our life saver, really)
  • Wynter (Zerotri) Woods

Monday, January 18, 2010

Meanies

What's this game about?

You control a evil mastermind that's bent on taking over the world! Or at least his city.

To accomplish that, he will find and recruit as many minions as he can, and send them or lead them on missions, for the good of mankind. And of course, himself.

Where is it set?

This game is set in a small city in our age and time. You will move all over it, it's almost completely visitable, and under it, as your base is in the sewers.

What do you control?

You control small, big headed minions, each with his unique personality and stats.


How many do you control?

At any given moment, you can control up to 8 minions, tough you will usually be controlling your avatar, the evil mastermind.

What's the main objective?

Conquer the world!

This is one of the games I’m currently developing. I’m not going to say anymore about the general game design, as it’s an idea I hope to use for personal stuff, and because this blog is about the technical side.

So, let’s get technical then. The game is written in C# and XNA. It might or might not be the definite language for the game, as right now I’m using the whole thing as a prototype. The game is for windows, I’ll worry about porting and the like when I’ve actually got something.

Hum, the architecture then.

Main

Ignore the green boxes. Right now I’ve got, starting from Game, the branches that end at: EntityManager, MapGrid and Modes done, including the Entities (as far as collision and animations are concerned), and all that hangs from MapGrid.

A quick overview of the stuff so far, and I’ll update as I code along.

SceneManager

A state machine that changes Scenes. It has only one scene active at any given time, and Scenes are discarded, not saved, when a new one is selected.

Scene

States the game can be in. Structural purpose.

PlayScene

The main scene of the game, it provides content, NOT logic. This might be a bit hard to understand, but basically, once playing, we need a second state machine to keep track of how we play. More often than not, from one play mode we don’t change the content  but instead the changes are more subtle, and while we don’t want to just cram all the possible options for every situation in the PlayScene, it doesn’t make sense to swap to a new Scene and reload all assets, logic or whatever.

For example, in the game I could have the fighting, normal and dialog modes. In all of them the same graphics are still loaded, the player still is on screen, etc… The changes here are more along the lines of player control, dialogs shown, Bot decision paths…

That’s why I introduce…

Mode

Mode is the thread of your process, so to speak. PlayScene is always in a Mode, and modes can be swapped in and out easily. Modes dictate the logic the resources of the PlayScene must follow. They hold all the logic of PlayScene, and are used as different “logic paths” for the game components to follow.

And logically, Modes don’t have any “content” themselves, apart of the needed to run their own logic. You could say they are the cartridges in your gameboy, and call the shots in all the components of PlayScene.

CityMap

It’s a collection of zones, as well as an actual map where to choose a location. Only basic functionality to support one scene is implemented right now.

Zone

It’s a place with a map, scenario items and entities, so the class has the necessary tools to handle them.

MapGrid

Holds the tiles, the scenario items and a tile-collision map generated from the load files of terrain and scenarios.

And… that’s all for now. Entity deserves his own post, and the rest isn’t really developed yet. I’m still deciding what to code next… maybe some input, or perhaps some basic path finding and random movement.

Wednesday, June 10, 2009

Game - Phagocitosis


Phagocitosis is a 1 week, simple, small puzzle game I created some months back.

It was developed in ActionScript with Adobe Flash CS4, using the KeyObject library as the only external help. A friend proposed the subject and I couldn't resist the challenge of coding a game and learning a new IDE and language at the same time, so here's how I went about it.


Design:
The Game Design was informal and written in miscellaneous pieces of paper, napkins, and the back of envelopes. It was mainly done by my buddy Undi. It took several months of sporadic work to get the general idea working.

Once the game design was over with, the Investigation and Technical Design phases began, in parallel. As it happens with new technologies, you can't design the technical aspect until you know how they work, and you can't know what you need to investigate until you know what you need.
The result of that phase was this Technical Design Document (TDD), (well, actually a draft, it was a quick development so it didn't need detail) specked with investigation notes, and this list of references:
Also, some interesting book titles:
  • Game Development With ActionScript
  • Essential ActionScript 3.0

Development:
The very first thing you come to realize when jumping into the Flash bandwagon is that there's ActionScript 2.0 and ActionScript 3.0 and that alone can shoot everything to hell.
I chose AS 3.0 on the grounds that, tough it might have a smaller support base, for learning purposes it's always a good idea to go for the next thing, as technologies outdate incredibly fast in this field.

After a few false starts, getting Adobe Flash working and setting up a SVN got me ready to start coding.

The game was built based on 3 things, the scenario, the player (a slimy Amoeba) and the enemy (a simple hole, if you fell in, you died).

The scenario was set up as a series of keyframes in the main timeline of Adobe Flash, with each keyframe having an associated Enter, Execute and Exit functions, creating a Finite State Machine to provide for all the screens of the scenario.
Scenes:
  • Menu
  • Scene Selection
  • Play
  • Pause
  • Game Over
  • Game Won
And you can guess what each one represents ;)

Each scene had it's own challenges, but the 2 biggest ones were:
Making buttons: 5 out of the 6 Scenes needed buttons, and those introduced me to the world of callbacks in AS, coupled with event handling and corresponding objects from the IDE to code entities.
The map: I wanted to have a easy way to create new levels and add them, and as I was using mappy to generate xml files of the levels, it stood to reason I had to have a in-game xml interpreter that also had access to the tilemaps and rendered the complete map. Now that was fun.

And everywhere, I had to take out my magical photoshop and produce crappy graphic after crappy graphic to fill my scene. I tried for a simple animation of the Amoeba and failed dramatically, after which I gave up and focused on static gfx.

The Amoeba and the Hole:
Each of these elements had to move around the map without charging trough walls. The pixel perfect collision detection was a real bugger, even tough the game only has 4 directions available.

The Amoeba was player controlled, so it needed a bit of input-handling magic, which had me fighting key input for more than a few hours.
The Hole on the other hand, was AI driven, and it uses a special pathfinding approximation algorithm based on it's relative position to the amoeba, instead of going for a full pathfinding with Dijkstra or A*. Not too surprisingly, this hack, apart from making the game run MUCH faster, made it more fun, as you could bait the hole to come out of certain areas instead of just waiting for it to chase you.

Game Play and Map-Making:
Final logic was added, specifically:
  • Collision between Hole and Amoeba results on player death
  • Collision between player and Objective results on loading next map
  • Map loading and changing
  • Game Over and Game Win
  • Select scene (start the game from a specific map)
Map after map was produced (special thanks to my brother there) each with different challenges, and tweaked to make them have a smooth difficulty curve (tough different players disagree on that one).

The End:
Final touches where made on the last wee hours of the morning in the last day of the development week, and a html file created for quick play without having to payload it to a server.

The game can be found at the SVN, along with all the code. Or if you prefer, a direct download.

Enjoy!