Thursday, September 9, 2010

Message Oriented Architecture (Code 2/2)

Second and final part of the code.
private function _addEventListener(idChannel:String, type:String, listener:iEventListener):void {
   if(!(idChannel in hashChannel)) { // first add channel check
      // there is no hashType for that sender so we create one
      hashChannel[idChannel] = new Object();
   }
   if (!(type in hashChannel[idChannel])) { // first add type check
      // there is no such event listener registred
      hashChannel[idChannel][type] = new Array();
   }
   var array:Array = hashChannel[idChannel][type] as Array;
   if(array.indexOf(listener) != -1) { // second add listener check
      // the array does contain "listener", so we don't add twice
      return;
   } else {
      // the only really useful code
      array.push(listener);
   }
}
 
Be careful with all those checks, without them, you could have problems. By example if you put the EventCenter as an external project like me, you don't have to change for each project the type of channels, types etc. So keep in mind that you need to check each time if the channel exist, if the type exist etc. The code itself is not complex but the number of case could me it hard to understand. Now you know of to add a listener. Let's see of to remove on, that is the last part.
private function _removeEventListener(idChannel:String, type:String, listener:iEventListener):void {
   if(!(idChannel in hashChannel)) {
      // there is no hashType for that sender so we return
      return;
   }
   var hashType:Object = hashChannel[idChannel];
   if (!(type in hashType)) {
      // You try to remove a listener that has not the good type
   } else {
      var array:Array = hashType[type] as Array;
      var index:int = array.indexOf(listener);
      if(index != -1) {
         // remove the listener from the array
         array.splice(index, 1);
         if (array.length == 0) {
            // the array is empty, so we delete it
            delete hashType[type];
         } else {
            hashType[type] = array;
         }
      } else {
         // the listener is not in the array
      }
   }
}
 
The splice method of Array, permit the deletion when we specify the index of the item and 1 as the number of item we want to remove. When we need Array.remove(item), we need to use Array.splice(Array.indexOf(item), 1), but be careful, if you forget to write the "1" all the array from the index will be removed, quite hard to find in debug.
I think we are done with the subject of EventCenter, good luck using this new way of messaging.

Message Oriented Architecture (Code 1/2)

Here I present you the code of the EventCenter. I show your parts of code incrementally, to be able to add some comments at each step.
public class EventCenter {
   private static var instance:EventCenter = new EventCenter();
   private var hashChannel:Object;
   
   public function EventCenter():void {
      this.hashChannel = new Object();
   }
 
You have here the initial code of the class. We use the singleton pattern without any protection, you can improve that if you want but it's not the goal of this tutorial. The only one variable of this class is the hashChannel that is the HashMap that contains the different channels. In ActionScript 3, we don't have native HashMap like in Java, but we have the Object class that can contains dynamical property like an HashMap.
public static function reset():void {
      instance = new EventCenter();
   }

   public static function dispatchEvent(idChannel:String, type:String, args:Object = null):void {
      instance._dispatchEvent(idChannel, type, args);
   }

   public static function addEventListener(idChannel:String, listener:iEventListener, ...type):void {
      for each(var t:String in type) {
         instance._addEventListener(idChannel, t, listener);
      }
   }

   public static function removeEventListener(idChannel:String, listener:iEventListener, ...type):void {
      for each(var t:String in type) {
         instance._removeEventListener(idChannel, t, listener);
      }
   }
 
This part of the code is actually the interface we show to the world. All those methods are public static, we could also add final but it's out of the bounds of this tutorial. All the real code is hidden in the instance field. The reset method only serves if you want to reinitialize the EventCenter. The idChannel is the identifier of the channel on/from which we send/receive messages. The iEventListener listener is the object that will receives the message, we call its method onEvent with the correct arguments. Finally the ...type allows us to add as many type as we want thanks to the "..." syntax that will transform type into an Array.
public interface iEventListener {
   function onEvent(type:String, args:Object):void;
}
 
Here is the simple code for the interface. One iEventListener can listens to as many Channel as it wants. It is the time to show the concrete code:
private function _dispatchEvent(idChannel:String, type:String, args:Object):void {
   if(idChannel in hashChannel) {
      var hashType:Object = hashChannel[idChannel];
      if (type in hashType) {
         this._dispatch(hashType, type, args);
      } else {
         // No such listener
      }
   } else {
      // there is no listener for this sender
   }
}
 
We use the properties of objects to store elements in the pseudo HashMap. You can notice the "in" operator that is quite faster than the "hasProperty...". With this, we know if there is an entrance with key=idChannel, if so, we know there are some listener for that channel. Then, we search into the HashMap corresponding to the channel if there is the type we look for, in this case we can call the _dispatch sub-function.
private function _dispatch(hashType:Object, type:String, args:Object):void {
   var array:Array = hashType[arrayType] as Array;
   if (!array) { // first assert
      // The array is null
      delete hashType[type];
   } else {
      if (array.length == 0) { // second assert
         // Array is empty => property removed
         delete hashType[arrayType];
      } else {
         for each(var listener:iEventListener in array) {
            listener.onEvent(type, args);
         }
      }
   }
}
 
As you will see in other function, especially in "_removeEventListener" we never keep an Array of listeners empty or null, so I call the two conditions "assert". Normally we never came into their braces.
This function allow us to dispatch / trigger / fire an event to all the corresponding listeners. The args contains also an HashMap.
Here is some examples of use:
EventCenter.dispatchEvent("Score_Channel", "Reset_Score");
EventCenter.dispatchEvent("Score_Channel", "Add_Score", {incr:13});
EventCenter.dispatchEvent("Score_Channel", "Decrease_Score", {decr:11});
EventCenter.dispatchEvent("Score_Channel", "Change_Score", {old:12, new:39, forPlayer:'Bob'});
 
The args is optionnal and moreover could have as many item as you want, identified by the keys. I think this is the most flexible we can do. Remember how complex it is with the native system of event. You have to create a new type of Event for each... new type you want. But with my solution, you just have to change the name. For my use, I always make constants representing the events with in commentary the format of the keys, with that when I code a dispatch, I always see with the doc, what is the format. Next part of the code, in next message.

Tuesday, September 7, 2010

Message Oriented Architecture (Performance)

Second part of the tutorial about MOA. After a night of test, I can show you the results. They are convincing. I compared the native event system with my implementation. The three main performance indices are the time for sending an event without any listener, the cost to add a listener to an empty list of listener and finally the marginal cost for adding a listener to an existing list of listeners.

Type Native Custom Performance 
without listener 2674.2 ms 1545.4 ms ~175%
first listener 2342.6 ms 1264.5 ms ~185%
add a listener 883.6 ms 145.6 ms ~605%

All tests were done with 1'000'000 send actions. The second and third experiment result are only the additional cost. So we can observe that we gain a lot of time using our custom version. Additionally, the custom version gives you more flexibility for its purpose and throw away the useless things like bubbling, etc. We can set a channel in which we speak, give the number of arguments we want and select a event type. All actions are done in a static manner, so we don't have to bother with EventDispatcher, we only use "iEventListener". As you will see.

Example of structure for the EventCenter
As you can see on the example schema, we use different level of classification. The first level contains the channels. When an event is dispatch, we first select the correct channel. Then the second level is the type of event, each channel has different type of event. You can notice the "Kill_Channel" has no type in the schema, it's because it has no listener. When a listener comes, we will add the types it wants to wait for. With this technique we don't waste neither memory space for each unused event types nor computation time when we dispatch an event that nobody are interested by.
The third level is a list of all current listeners. For the moment, we use a simple ArrayList, but we could also implement a LinkedList to store the listeners and allow us to have constant time insert/delete. But to do that, we need to add some code in each listener. Because we use only an interface to have the biggest flexibility. Using a class like EventListener that contains the next/prev links needed by the linked list, we must use composition instead of simple inheritance.
All the code you need will come with the next tutorial...

Monday, September 6, 2010

Message Oriented Architecture (Intro)

After this article, I hope, you will make some nice architecture for your future games. Using a message oriented architecture, inspired by message oriented middleware (MOM), permit the complete separation of the modules. Without a static module managing the message, all your modules needed to be connected to allow any kind of communication. Without wire, we can't communicate. But this article will show you how to reinvent the WiFi in your architecture, i.e. wireless communication. Actually the wires still exist but are hidden behind the communication module.
Let's call our communication module "EventCenter". First reason is because I use it instead of the natives events of ActionScript 3. Secondly because all the principles are based on events, that encapsulate the messages in some sense.
Some notions are needed before starting. First notion is the synchronization: a synchronous message is blocking, i.e., when we call "send", the receiver sees his method "receive" called and only when this method finishes, the sender has the hand back; an asynchronous message is sent and after a given time, the receiver really receives the message, i.e. it's not blocking. Too theoretical ? Let's have two examples.
Synchronous Messages:
We can use synchronous messages when we want to simulate direct function call like "enemy.kill()" by sending the message "EnemyKillMessage". In this case, just after the send of the message, the enemy is dead.
Asynchronous Messages:
The example for asynchronous message is quite more complex. Imagine you have a loop, during a pass you could send 0,1, or n message(s). The only relevant information is "do I have received a message during the pass or not ?" Imagine the number of messages is irrelevant and we want to make a treatment only once, imagine a long compuation. If we had synchronous message, we should use a boolean to keep the information "alreadyComputed" and a message will be send after each pass to indicate we need to reset the boolean. We can also use asynchronous messages and store them into an array like a buffer. Cleaning the buffer in one time when making the computation can speedup the execution. (If you find a better example, not too complex, don't hesitate).

Next message will be about the structure of our communication center, here was just an introduction. (Will be published tomorrow)

Sunday, September 5, 2010

Polygon: basic manipulations

In this post we will show how to manipulate polygons. First things, the best way to manipulate them is to store them in a linked list way, i.e. we define a polygon by the start point and each point is linked with its two neighbors, respecting the clockwise rule.
Left: clockwise polygon definition, right: counter-clockwise polygon definition
The area of the polygon is defined to the right of the vector formed by two consecutive points. You can see in the example, with two same set of points simply defined in the reverse order, we have one time the desired polygon and the second time the inversed area.

Now we want to have some operations on those polygons. First one is the membership of a point to the polygon. This is a known problem in computational geometry, called PIP for Point In Polygon: on Wikipedia. I choose to use the winding algorithm to solve this problem to avoid potential round error.

public function isPointInside(px:Number, py:Number):Boolean {
   var counter:int = 0;
   var xinters:Number;
   var p1:WPoint;
   var p2:WPoint;
   p1 = start;
   p2 = p1;
   do {
      p2 = p1.next;
      if (py > Math.min(p1.y, p2.y)) {
         if (py <= Math.max(p1.y, p2.y)) {
            if (px <= Math.max(p1.x, p2.x)) {
               if (p1.y != p2.y) {
                  xinters = (py - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
                  if (p1.x == p2.x || px <= xinters) { counter++; }
               }
            }
         }
      }
   }while((p1 = p1.next) != start);
   if (counter % 2 == 0) {
      return(false);
   } else {
      return(true);
   }
}
 
Now we can call this function to know if a given point is inside or outside a polygon. Note the method to use to iterate over the points of a polygon, like with Linked List. The complexity is O(n) where n is the number of points in the polygon. To have complete code, you also need the code of the classes.

public class WPolygon {
   public var start:WPoint;
}
public class WPoint {
   public var prev, next:WPoint;
   public var x:Number, y:Number;
   public var parent:*;
}
 
Next useful function is how to compute the area of the polygon. Without entering into details, there is a very simple algorithm to compute the area by adding partial projection for each couple of points.

public function area():Number {
   if(start.prev == start.next) {
      throw new Error("Area of polygon needs at least three points");
   }
   var result:Number = 0;
   var curr:WPoint = start;
   do {
      result += curr.x * curr.next.y - curr.next.x * curr.y;
   }while((curr = curr.next) != start) ;
   result /= 2;
   return result;
}
 
The algorithm comes from Polygon Area where you can find a little illustrated example to understand the method. The complexity is O(n) where n is the number of points in the polygon.
To finish this initial post, we show you the basic functions of adding/removing points. Note that we suppose that when we remove the point, we already know which point in the polygon we want to remove, i.e. we already have the pointer to it (and especially to its neighbors).

public function addPoint(x:Number, y:Number):WPoint {
   var nPoint:WPoint = new WPoint(x, y);
   
   start.prev.next = nPoint;
   nPoint.prev = start.prev;
   start.prev = nPoint;
   nPoint.next = start;
   
   nPoint.parent = this;
   
   return nPoint;
}

public function removePoint(point:WPoint):void {
   if(point.parent != this) {
      throw new Error("Removal fails, the point isnt in the polygon");
   }
   point.prev.next = point.next;
   point.next.prev = point.prev;
   point.parent = null;
}
 
You notice we returned the new point in the add function. If you want to use the point you need to use this pointer because it has the links to the neighbor points and the parent pointer set. Like in Linked List, the insertion and deletion is done in O(1) by simply setting the neighbors' pointers.


Twelve steps to make games (2/2)

The second part of the tutorial about work flow for game design. This is a possibility, not the only one, don't follow each step strictly, create your own work flow using this example.
  1. Assemble the parts together
    Mixing all the previous things together is quite hard if you do that directly. The main problem is the spaghetti effect. You have multiple class and each could have some links with other, so the solution for lots of developer is to put a reference on each class to each other class. Conceptually speaking, it's just horrible. Try to join similar class, to make some "helper", to use composition with precaution and not as the unique solution. You can also implement a system of message communication (I will put an article about that later).
  2. Test the gameplay
    Don't think it's the funniest part, it's the hardest actually. Why ? Simply because you have created the gameplay and you must be objective to see some default ! The gameplay must be quasi perfect, it's the thing that allow the user to "play" literally. If your hero moves too fast, the player has not the experience that you wanted. This must be the extension of your concept, not a tool to communicate with the game. Try different games and observe attentively how the objects move, the events appears, the character jumps etc. The gameplay needs to serve the game !
  3. Improve the graphics
    Yes, until now, I never speak about the graphical part of the game. It's not without reason. Before this point, your character must be a circle/square and all other things too. If you spend too much time drawing/designing things, you could have some problems when debugging especially. Imagine your character has a sword but when you are near a wall, the sword is "on" the wall, you could think it's a problem of collision but actually it's just that the sprite you use is bigger than what you had planned. One of the problem when you develop alone it's to manage a certain balance between working hard on graphics and trying to find perfect gameplay. My opinion is that we need to endure the graphics to have fun with gameplay, for little flash game of course. If you want to make the next best-seller you need to have some artist in your team.
  4. Making little beta
    To have objective feedback, you need to find objective people. Of course, friends are never really objective, either they want to be cool with you or you bother, but having a real objective opinion is quite rare and if so, you need to filter all other. So, the easiest way is to publish on a website like Flash Game License (
    FGL). Initially it's a site to sell / search sponsor but you can enable the view by other develops and preview players, they will let feedbacks to improve your game. You can also try on little forum to have a dozen of constructive feedbacks. When you have improve the more relevant issues, you can go further.
  5. Publish the game
    To publish a game, you have some different possibilities. First is to publish manually to big portals and hope your game is nice and people likes it, in this case, little portals will take the games and you can let the viral distribution working. To have such portals, try the two following lists that I found: 45+ on Mochi
    35+ by Emanuele. The second main possibility is to use Flash Game Distribution (FGD), this site will send your game plus some informations to a very large network of portals. The disadvantage of the second method is that your don't control directly the submission, perhaps you want to submit only one portal per week to spread the success during three months. If your game doesn't have a lot of success, try to find where is the problem. Is it the gameplay ? The idea is not as good as you thought ? Perhaps the execution, graphics are not enough good to support the ideas ?
  6. Learn from the experience
    When you have finished a game or any other part of your life actually, take a moment to sum up. Weighs the good and the bad things you did during the period and try to extract some useful informations. Perhaps you loose too much time debugging ? In this case search a new way to test your code, it could increase your efficiency. The goal after an experience is to learn something, even the experience was very bad, you can derive an advantage. 
Don't forget, if you have some games, send them to me, I could publish them and ask reader to make objective feedback, like a little beta.
Last tips: Take pleasure in making games !

Friday, September 3, 2010

Twelve steps to make games (1/2)

Like in all other scientific field, we need to have a certain methodology. If you start coding directly your game, I can bet your game will be either very small or unplayable/unfinished/etc. To make great games, you need to follow some steps.

  1. Searching ideas
  2. If you don't have the idea of the millennium, it doesn't matter. You have different possibility. Either you have an original idea that was never seen before (the first FPS, STR, RPG, or even the first game using skills, upgradeable weapons, achievements, etc), or you played original games and you have idea how to improve the gameplay or in general the user experience. A new concept is relatively hard to find, sometimes it comes during the night (dreams are a powerful idea engine), or by looking at the nature / people / common actions. Look around yourself and analyze each thing in the piece. You have a lamp ? Ho a shadows based game with infiltration... You have a mosaic parquet ? Ho you invented Tetris... etc. Each object in the life could be the main subject of a game. Imagine your computer speakers, you could take them as weapon and shoot wave on poor enemies... The imagination doesn't have any limit !
  3. Putting ideas on paper
    When you have a nice idea, you need to test it. If the idea doesn't pass the test, it is useless to continue with it. You need either to modify it or to change. Testing is quite simple, you need to draw some little shapes that represents your concept and try to play them. If it's boring, not fun, annoying etc, the test is not successful. One of the problem of this technique is that it's your idea, and a personal idea is always good for the person itself (in general). My advise is to test with your friends / family / cat. Ask them to be honest, it's some days of work that could be useless if they simply tell you the idea is nice to avoid to hurt you. I prefer a friend tells me my idea is bad than working a week on a stillborn game.
  4. Drawing some diagrams
  5. Imagine the interface you would like to have in your final game. Draw some boxes, put names and functions on them like. Using Inkscape this task becomes really easy.
    Lo-fi prototype
    You must using only simple colors, simples shapes. We call it a Lo-fi prototype for Low Fidelity. The goal is to have a general look for the game interface. When you have all elements you want, go to the next step.
  6. Thinking about software architecture
    At this point you shouldn't have written anything. You can look at your interface and distinguish some class of object. For our previous example, you have circle, some purple and one red, three panels, one for game, one for score and one for the life. Try to extract some object concept from your idea. When you have a certain amount of concepts (it's better to have all at once but we are human and we can't think directly in the perfect way), you can draw some links between them. Like the score panels observes the game logic, the enemies circles are linked to the hero circle, etc. You should have a nice starting diagram at this moment. Ideally, no concept is alone, if an object has no link with the other, there is probably an error.
  7. Start coding
    Now you have a class diagram, some design concepts and lots of impatience to code all those things no ? Make an ActionScript 3 class for each things, try to show the hierarchy previously found.
  8. Very simple hierarchy
    When you have the skeleton of each class, you can finally start coding. The coding part is not as important as we can think initially and must not be an important part. The design (graphical and gameplay), the architecture, etc, must be more important. The code is simply a tool we use to expose our ideas. Keep that in mind. Do no confound code and algorithm. A nice algorithm could "create" gameplay, code doesn't. The importance of the algorithm is out of the goal of this tutorial.
  9. Testing each little part incrementally
    You need to understand something that is really important in any development, that is right for game making, computer science in general but also in any other scientific field. We can't advance if you don't have solid basis. Imagine your architect builds your house on a unstable ground... The tests are the things that make your work easier when you have something that grow. If you have a coordinate mapper, test it, because when you use it, you assume it has no bug. Imagine you use it in an other class, but there is a bug with 0 (typically) and when you run a little example, the new class appears to have lots of bugs. But actually it was the coordinate mapper, but before thinking it is that you have perhaps rewrite three times your last class for nothing. Considering the tests with high priority. It's the protection you take against the evil bugs ! When you have tested a class under all angles, you can use it in other projects without problem. You can think about a stable system that hasn't side effect and I can affirm that is a real pleasure to have well-done bricks to build a game.

        Tools ?

        What are the tools we can use to draw/code a game in ActionScript3 ?

        The best tool to design some flash is the classic Flash CS5. The problem with Flash CS5 is that you can draw, design, animate all your things but not really code. Actually you can, but it's horrible, like coding with a pen and paper : no good auto completion, no incremental compilation, lots of error message that are not very useful etc. Get Flash CS5

        The best new things with CS5 is the integration of Flash Builder (previously Flex Builder) with Flash IDE. With Flash Builder you can write your code very easily. The bridge between both program is relatively easy to use. It is a plugin for Eclipse. There is a lot of functionalities that make your coding "effort" as low as possible. Get Flash Builder

        Because I like incremental things, the third tool I present you now is (for me) better than the two other. It is FDT. Also a plugin for Eclipse (that is really nice for Java coding), FDT is for me, the most intuitive tool for ActionScript 3. It has approximatively the same advantage as Flash Builder but the team behind is more reactive. Get FDT

        Now, not necessarily the best, but the most profitable because it is free, FlashDevelop. Very nice to code with, it is based on Visual Studio Layout, you have a lot of options, you can link projects directly with your IDE etc. You can notice that FlashDevelop has the best auto completion I never seen before: when you type a word like "add" the IDE also propose you "onAdded" function. It's very useful when you code function with some prefix modifiers like get, set, link, add, etc. Get FlashDevelop, it's free, try it !


        Now, I hope, you are ready to start coding ActionScript 3 and making good games.

        Thursday, September 2, 2010

        First message

        Welcome on my new blog. The main topic will be Game Design (yah yah) but also other topics related to computer science, psychology etc.
        If you have a suggestion, please don't hesitate, send me an email (wadeck [dot] follonier [at] gmail [dot] com) and I will perhaps publish it the days after.

        Enjoy your reading.