Singletons for AS3

Posted in Programming, Tips on June 21st, 2010 by Manuel
No Gravatar

Singletons the curse and blessing of many coding projects. ;) Among other pitfalls, you’ll basically introduce a global variable in your system, making UnitTests much harder.

Why Singletons?

Despite the possible problems they can present, they are just so darn handy sometimes. If there is some part of your code that needs to be accessed from almost anywhere in the system (like the sound system, or a global error text console and such) there is hardly a better way to achieve that.

Alternatives?
A global messages system to communicate between objects can achieve the same effect. We used to make heavy use of such a system system. However, according to our experience, maintaining that system is fairly time consuming for it gets more and more complicated over time. Besides, if a messaging system allows queing, you’ll never really now where and why a message was sent because you loose the stacktrace. So, right know we are reducing the work-load done by the message system, handing it over to direct singletons access. By this, we increased debugability and clearity of data transfer. Besides, using singleton access is much faster than routing it through our messaging system.

How to Do It?
The web already offers a bunch of solutions (1). Most of them boil down to implement the singleton code over and over again in each singleton. We didn’t like that and tried to come up with a better solution. When we define a singleton it looks like that:

/**
* Accesing this class somewhere in the code looks like this:
* cSomeController.GetInstance().DoSomething();
*/

public class cSomeController extends cSingleton
{
    public static function GetInstance():cSomeController
    {
        return cSingleton.GetInstance(cSomeController);
    }

    public function DoSomething()
    {
        trace("Yes, I can.")
    }
}

That is much simpler than copying&pasting the complete singleton code over and over. The corresponsing cSingleton-class looks like that:

package rsengine.patterns
{
    import flash.utils.Dictionary;
    /**
    * Singleton base class
    */

    public class cSingleton
    {
        private static var m_instances:Dictionary = new Dictionary();
        private static var m_unlockConstructor:Boolean = false;            

        public function cSingleton()
        {
          if (m_unlockConstructor == false)

          throw Error("You cannot create an instance of a singleton."
          + "Use GetInstance instead!");
        }

    /**
    * Returns an instance of the specified class
    * @param _class class
    * @return instance of specified class
    */

    public static function GetInstance(_class:Class) : *
    {
      if (m_instances[_class] == null)
      {
        m_unlockConstructor = true;
        m_instances[_class] = new _class();
        m_unlockConstructor = false;
      }
      return m_instances[_class] ;
    }
  }
}

Our singleton implementation significantly reduced the amount of code you have to copy&paste compared to the other singleton implementations out there on the net. We do know that our implementation of GetInstance() is a little slower (because of the Dictionary look up). Since you shouldn’t have too many calls to the GetInstance method this is probably nothing to worry about too much. Nevertheless, you could cache the result of GetInstance() if you do need to access the singleton more than once (e.g. in a loop).

Have fun and happy coding
Manuel

AS3: Singletons, ActionScript 3 Singleton Redux, google

Popularity: 19% [?]

  • Share/Bookmark
Tags: , , , , , ,

Numeric Enumerations (Enums) for AS3

Posted in Methodology, Programming, Tips on April 14th, 2010 by Manuel
No Gravatar

Something I really missed in Actionscript 3 were enums. If you need ascending unique numeric ids ( e.g. for naming array indexes ), enums are your friend.

For our current project we programmed a messaging system. The system uses unique numeric ids for message types and message channels. The list of messages and channels grew over time and right now each list contains more than a hundred entries. In the beginning we did the numbering ourselves like that:


    public static const MSG_OPEN_WINDOW:int = 0;
    public static const MSG_CLOSE_WINDOW:int = 1;
    public static const MSG_REGISTER_TIMER:int = 2;
    // .. and so on

For code beauty we were always trying to group related message ids, which often meant to re-index dozens of entries if we inserted an id somewhere in between. This was a pain!

The net already has assembled quiet some wisdom about “fake enums ins as3″¹, which do fit different needs (like some have type safety) but unfortunately not ours. Most of them are String based, which is what we did not want. So after putting in some thought we came up with a solution that worked for us. Now we can define our enums like this:


    public static const MSG_OPEN_WINDOW:int = cEnum.Enum(0);
    public static const MSG_CLOSE_WINDOW:int = cEnum.inc;
    public static const MSG_REGISTER_TIMER:int = cEnum.inc;
    // .. and so on

Now, by using static methods and a static counter we can create an arbitrary amount of coherent numeric values, which comes in very handy from time to time! Re-indexing is in the past now!

We want to share our little enum class with the web, so here it comes:


public class cEnum
{
	private static var m_currentIncrement:int = 0;

	/**
	 * Adds an enum value to the collection
	 */

	public static function Enum(_v:int) : int
	{
		m_currentIncrement = _v;
		return m_currentIncrement;
	}

	/**
	 * returns the next increment
	 */

	public static function get inc():int
	{
		return ++m_currentIncrement;
	}
}

Bottom line, if you need a neat way to maintain a list of static coherent numeric entries while type safety is not a big issue … this is an fairly easy way to do it. May this help you out there as much as it helped us.

Have fun and happy coding
Manuel

¹ Further readings on AS3 enums can be found here: e.g. http://www.herrodius.com/blog/87,
http://scottbilas.com/blog/faking-enums-in-as3/
or http://blog.petermolgaard.com/2008/11/02/actionscript-3-enums/

Popularity: 31% [?]

  • Share/Bookmark
Tags: , , , , ,

Random Map Generation

Posted in Art, Programming, Tips on August 24th, 2009 by Manuel
No Gravatar

Designing an appealing and huge game world from scratch will take even really fast designers a looooong time: valuable time that can be spent in better ways. This is where generated content comes in handy. With the push of a button a designer can create a whole world (oceans, land, forests, deserts, mountains, cities, … ) in an instant. So this is what we decided to do for our game … and here is how we got to the finish line:

On the bumpy road to an actual working map generator we decided to split all map generation tasks into small modules: heightmap generator, water generator, forest generator, desert generator, and so on. In the map-generator GUI the designer can put these modules into a task list and define the order in which they are executed. Each module also has parameters that affect the characteristics of the generated map. Even though it is supposed to be a random map generator it is especially important to have deterministic behavior. Consequently, each module that actually generates content has at least a “seed” parameter for the random number generator. With the same seed the generator will create the same results every time. Changing the seeds will create a different map.

map generation steps
In the little animation above you can see the output of some of the modules.

Heightmap Generator
At first we create a heightmap. We use Perlin noise since it is built into the AS3 BitmapData class and it is amazingly fast. In the beginning we experimented with our own implementation of the diamond-square algorithm, but it was way too slow.

Water Fill
In the next step we apply water to the world. We simply declare everything below a certain height level as being under water.

Mountains
By looking for local peaks we detect mountains and flag the areas accordingly.

Humidity Map
By defining a water contingent that grows over water and decreases over land we can flag dry and wet zones on the continents. To make things easier we define our whole world as a west-wind zone. The centers of most bigger continents will be dry (yellow), coast regions will be mostly humid (green) and continental areas lying east of a big stretch of water will be very humid (dark green).

Climate Zones
Next we define climate zones in the world: tropical areas, temperate zones and polar regions. With this information we can easily place polar caps in the world.

Forest Generator
Using the information from the climate zones and the humidity map makes it possible to place different types of forests into the world. Jungle (purple) will be found in the hot and wet regions around the equator, while coniferous forests will be found close to the polar caps.

Desert Generator
The desert generator also uses the information from the humidity map to detect dry regions and place desert areas into them.

Well, now you had a look at some of the modules in our map generator. They are not only capable of creating earth-like maps (like the small sample map above) but also completely different maps by changing the parameters: a lake landscape, a waste land, a desert or whatever our games may need. With this we are able to quickly create new game content of any size for the players to explore.

Cheers,
Manuel

Popularity: 100% [?]

  • Share/Bookmark
Tags: , , , , , , , , , ,

Asserting the Basics – Part I

Posted in Methodology, Programming, Tips on November 3rd, 2008 by Manuel
No Gravatar

Although it’s not the hardest language to learn, Actionscript3 does provide a couple of traps that may lead an inexperienced Padawan astray. In a series of blog entries I would like to describe my own first steps on these new grounds, hoping that I can provide some aid for other programmers who also want to join the scripted side of the action.

Usually, the first thing I do in a new language is to ensure to have at least the following things at hand:

  • a possibility to print out text
  • an assert mechanism
  • and unit tests

These ingredients provide at least a minimum of safety while progressing through the uncharted territories of a new language and this is what I want to talk about. Let’s start on the first topic:

The beauty of text output

My very first project as a professional programmer was a racing game in C++ for Symbian OS 6 (an operating system on Nokia cellphones). Back then, the Symbian SDK consisted pretty much only of compilers and packagers, … and one funny little emulator. This bad boy did not have a text console to print to, and, even worse, there was no support for a real-time debugger. I pretty much felt like being blindfolded. It was then, when I realized how important a simple text console can be! Traumatized by this experience, I started our game engine by writing a Debug class with its first method being an output function for text messages.

Some may say: “Heck, why didn’t he just use trace() everywhere”. This has several reasons: For one, trace() simply does not work with non-debug Flash players and secondly I wanted to have one interface for all the debug messages. This way, implementing the possibility to switch off printing of messages is a piece of cake, and later adding a logger for all messages would be just the piece of cake next to the one I have just mentioned.

Now, this is what our very first method(s) looks like:

    private static var m_sendDebugInfo:Boolean = true;

    public static function EnableDebugInfo(_debugInfo: Boolean) : void
    {
        m_sendDebugInfo = _debugInfo;
    }

    /**
     * Sends a message to the console of flash develop
     * @param    _msg message to send
     */
    public static function Out(_msg:String): void
    {
        if (m_sendDebugInfo == true)
        {
            fscommand("trace", _msg); // for normal player
            trace(_msg); // for debug player
        }
    }

Alright, this is pretty basic stuff, I know. Anyway, I did have to fiddle around with the text console to get it working in all players, especially with the non-debug player. So I thought, why not starting simple? I can always get more complicated later … and maybe this info can save some of somebody else’s time.

So, we just reached the end of the first entry of my series. Next time, I’m going to discuss the topic of assertions. So stay tuned for another episode of “Asserting the Basics”.

Happy coding,  Manuel

Popularity: 4% [?]

  • Share/Bookmark
Tags: , ,

Doing server-communication the foxy way

Posted in Programming, Tips on October 26th, 2008 by Joerg
No Gravatar

Hi guys,

I am currently checking out some stuff for the server-side of our browser game. Right now, I am having a look at the so called SmartfoxServer (SFS in short), a “socket server for flash multi player games and applications”. Sounds interesting, so we decided to give it a try.
A good portion of the samples are written in ActionScript2 and only a few are in AS3 which makes it a bit difficult for me since we are using AS3, but fortunately I found these tutorials that deal with SFS and AS3. I already started reading them and I am going to continue this within the next few days.

I am still a bit in a struggle with some Flash and Flex SDK stuff, but here is what I can already say about the SFS:
- simple and clear server configuration using a config.xml file
- foolproof API: you can get started within minutes and there are event functions for every kind of stuff
- detailed documentation
- extending the protocol is very easy by writing your own socalled “server-extensions”
- zones and rooms are already implemented. These are necessary if you want to run multiple instances of your game on one server (zones) or if you want to split your gameworld into different locations (rooms)
- FREE trial version of the SFS pro! The only limitation is that only 20 users may connect. Enough to test it though.

As soon as I am done with the tutorials, I will try to encapsule one part of our demo and feed the game with content from the server instead of pre-generated local content.

I am not aware about the performance at the moment. You may have a look at the benchmark whitepaper or wait until we run performance tests on our own.

I will keep you up to date and tell you my opinion regarding the SFS while getting more into detail the next days.

Popularity: 12% [?]

  • Share/Bookmark
Tags: , ,