Tags – open source.

Moderatrix: Fast User Interface Widgets Without Flex.

In this series of articles I’d like to invite you to meet the library I’ve been working on during last few years: Moderatrix (with a small help from other support libraries).

It started long before I joined Falanxia, but Moderatrix made a good leap lately: it was heavily used in our recently launched Bzoonk Bar game.

So what’s going on here? Basically all you need to see is in the video screencast below – all the effects, animation and so on (it was used in other projects as well, but let’s stick with Bzoonk Bar). There’s a lot more under the hood I’d like to talk about.

You may ask why I didn’t use Flex (or any other user interface library). But first you need to know the requirements I needed to meet.

Everything started when I was in Cyprus for my one year trip to Sideshow. I just moved from AS2 to AS3 and I really needed a strong library to allow me fast prototyping, while not using Flash (you may know Flash IDE is nearly unusable on OSX).

I got to create a feature-packed video player for Involver, and there was a huge list of requirements I had to satisfy:

  • fast and easy GUI skinning and rendering,
  • skins should be built and used without rebuilding of the player core SWF file,
  • so the premium clients could build their own skins – without Flash, just using regular graphics app and a text editor,
  • color theming of the existing skins for regular users and not-so-premium clients,
  • advanced 3D animation.

The list was somewhat longer, you can check it out on my Involver portfolio page, but I think it’s now clear the requirements were pretty tough.

Actually it was even a bit worse: there were some other challenges I also needed to solve: data and processor consumption should be minimal.

So now you know why Flex was not an option for me:

  • Flex apps are usually pretty large (and the Involver player had to be compact; it has to load fast, start fast and act fast),
  • they are usually a bit sluggish, honestly,
  • it’s not really easy to deploy pixel-perfect graphics in Flex (I got a feeling this could be a reason for a flame war),
  • it’s not really easy to add animation, Flex components are too slow to animate smoothly,
  • in 2007 it was difficult to skin a Flex component, and if you needed a runtime skin, you needed Flash or Flex to build one,
  • no 3D possible – we needed to animate UI containers in 3D and it’s really not possible in Flex even now, few years later – Flex simply doesn’t think you’d ever need to put a subcontainer in a parent container (which may be rotated), but puts it on the stage again

I tried a few user interface libraries available at the time, but nothing was really useful for my scenario. So I decided to build my very own system. It started as a part of my vancura-as3-libs package, but when I started to work at Falanxia, I refactored the libraries into Falanxia suitable ones. And now the libraries are open again – so you can use it right now.

This series will show you how to use them. If you’re interested, please be sure to follow me on Twitter, so you know when a new article is out.

WebExpo 2010: Preparing Data for Performance-Critical Apps in Flash.

In case you’re going to attend WebExpo 2010, I’d love to invite you to my talk.

Some people don’t like Flash because they experienced it in the form of annoying Flash banners and intro animations. But this format is groundbreaking and it’s possible to create almost anything with it; from simpliest animations to very complicated and sohpisticated applications.

Flash has given me absolute creative freedom for 13 years now. I learned how to use it effectively and created my own process which I will introduce to you…

I’m illustrator, graphic designer and also a programmer of Flash games. Most of our games are designed for Facebook. They have to be fast, small and very attractive. I will share my experience with development of these games.

I will show you my workflow from application design to execution. I use self-made framework that is available as opensource. I will also talk about more general process of preparing and optimizing data.

Pokud jdete na WebExpo 2010, rád bych Vás pozval na svou přednášku.

Flash může být někým vnímán negativně po zkušenostech s otravnými bannery a intro animacemi, kde bývá tato technologie použita. Přitom je tento formát naprosto přelomový a je v něm možno vytvořit takřka cokoliv, od nejjednodušších animací, po velmi komplikované a propracované aplikace.

Mě Flash dává už 13 let naprostou tvůrčí svobodu. Naučil jsem se ho efektivně využívat a vytvořil si řadu vlastních postupů, které Vám představím.

Jsem kreslíř, grafik a v poslední době také programátor flashových her. Navrhujeme hry hlavně pro Facebook, které musejí být rychlé, malé a velmi atraktivní. I o zkušenosti z vývoje těchto her se s Vámi chci podělit.

Představím vám svou workflow od návrhu aplikace po realizaci. Používám svůj vlastnoručně naprogramovaný framework, který jsem publikoval jako opensource a je tak k dispozici i vám. Kromě toho se budu také zabývat obecnými postupy přípravy a optimalizace dat.

TrazzlePublisher.

If you use as3logger to standardize your AS3 logging needs, I’ve got something for you.

At Falanxia we’ve been using SOS Max Logger by PowerFlasher, but recently I’ve found a great new supplement, which I think is a great leap forward: Trazzle. Let me copy paste few features we love here:

  • Bitmap logging
  • Performance monitoring
  • Multiple Log Levels
  • TextMate support

For us just the Bitmap logging feature was a reason to switch. In case we logged events just via SOS Max, there would be a need to rewrite all logger calls, and it would be a somewhat painful and completely useless experience. Since we use the as3logger approach, it was really easy to add a small Trazzle wrapper. And there was no need to rewrite anything in our sources.

Here’s the source:

/*
 * Falanxia Utilitaris.
 *
 * Copyright (c) 2010 Falanxia (http://falanxia.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.falanxia.utilitaris.logger {
    import com.falanxia.utilitaris.utils.*;
    import com.nesium.logging.*;

    import de.dev_lab.logging.*;
    import de.dev_lab.logging.publisher.*;

    import flash.display.*;



    /**
     * The {@code String} publisher outputs the Log to a Trazzle.
     * See more info about Trazzle here:
     * http://www.nesium.com/products/trazzle
     *
     * @author Vaclav Vancura @ Falanxia a.s. vaclav@falanxia.com
     * @author Falanxia (http://falanxia.com, @falanxia)
     * @since 1.0
     */
    public class TrazzlePublisher implements IPublisher {


        private static var _trazzle:TrazzleLogger;



        /**
         * Constructor.
         */
        public function TrazzlePublisher(stageReference:Stage, appName:String) {
            if(_trazzle == null) {
                _trazzle = new TrazzleLogger();
                _trazzle.setParams(stageReference, appName);
            }
        }



        /**
         * Outputs the message to the {@code String}.
         * @param logLevel Log level
         * @param object Message
         */
        public function publish(logLevel:int, object:*, ...additional):void {
            var prefix:String;

            switch(logLevel) {
                case Logger.DEBUG:
                    prefix = "d ";
                    break;

                case Logger.INFO:
                    prefix = "i ";
                    break;

                case Logger.WARN:
                    prefix = "w ";
                    break;

                case Logger.ERROR:
                    prefix = "e ";
                    break;

                case Logger.FATAL:
                    prefix = "f ";
                    break;

                default:
                    prefix = "";
            }

            if(object == null) object = "[null]";

            _trazzle.log(prefix + String(object), 4);
        }



        /**
         * Clear.
         * Trazzle has no clear method, so it's just a placeholder.
         */
        public function clear():void {
        }



        /**
         * Destructor.
         */
        public function destroy():void {
            clear();
        }



        /* ★ SETTERS & GETTERS ★ */


        /**
         * Get Trazzle reference.
         * @return Reference to Trazzle
         */
        public static function get trazzle():TrazzleLogger {
            return _trazzle;
        }
    }
}

Of course you need as3logger de.dev_lab.logging.Logger class.

All you need now is just an initialization of the logger:

Logger.addPublisher(new TrazzlePublisher(stage, "My application name"));

And you can log as you logged before:

Logger.debug("Debug message");
Logger.info("Info message");
Logger.warn("Warning message");
Logger.error("Error message");
Logger.fatal(Math.random() * 1000);

If you want to call Trazzle for any reason (e.g. to log a Bitmap), you can use:

var myBitmapData = new BitmapData(100, 100);
myBitmapData.noise(Math.random() * 1000);
TrazzlePublisher.trazzle.logBitmapData(myBitmapData);

Or to invoke a beep and show a performance window:

TrazzlePublisher.trazzle.beep();
TrazzlePublisher.trazzle.startPerformanceMonitoring();

You can fork or watch the Gist for this class here on Git.

Dummy Tween Plugin.

A somewhat different approach to periodical calling of a method. This time with TweenLite/TweenMax by Greensock

As I said before, last few months I’ve been working for Falanxia.com, where I help to develop social games in Flash (and more platforms coming). I was not very happy with the way how to periodically call a method:

var timer:Timer = new Timer(10, 100); // call a method 100 times with 10 ms delay)
timer.addEventListener(TimerEvent.TIMER, method);
timer.start();

Is there a shorter approach to do the same thing? While we already use TweenLite/TweenMax a lot, I thought there has to be a plugin which should handle this task (no, I don’t need TweenLite.delayedCall(). Well, nope, there’s not. But sure it can be handled this way:

var tweenObj:Object = {pass:0};
TweenLite.to(tweenObj, 1, {ease:Liner.easeNone, onUpdate:method}); // 100 * 10 ms = 1 second

IMHO this way is a bit cumbersome and you need to create an Object to be tweened. I came up with a simple TweenLite plugin to do the job:

/*
 * Falanxia Utilitaris.
 *
 * Copyright (c) 2010 Falanxia (http://falanxia.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.falanxia.utilitaris.plugins {
    import com.greensock.*;
    import com.greensock.plugins.*;



    /**
     * Dummy tween plugin.
     *
     * @author Vaclav Vancura @ Falanxia a.s. vaclav@falanxia.com
     * @author Falanxia (falanxia.com
     * @since 1.0
     */
    public class DummyTweenPlugin extends TweenPlugin {


        public static const API:Number = 1.0;

        protected var _target:Object;



        /**
         * Constructor.
         */
        public function DummyTweenPlugin() {
            super();
            this.propName = "dummy";
            this.overwriteProps = ["dummy"];
        }



        /**
         * Tween initialization.
         * Gets called when any tween of the special property begins. Store any
         * initial values and/or variables that will be used in the "changeFactor"
         * setter when this method runs.
         * @param target Target object of the TweenLite instance using this plugin
         * @param value The value that is passed in through the special property
         * @param tween The TweenLite or TweenMax instance using this plugin
         * @return If the initialization failed, it returns false. Otherwise true.
         * It may fail if, for example, the plugin requires that the target be a
         * DisplayObject or has some other unmet criteria in which case the plugin
         * is skipped and a normal property tween is used inside TweenLite
         */
        override public function onInitTween(target:Object, value:*,
            tween:TweenLite):Boolean {
            return true;
        }
    }
}

How to use it?

TweenPlugin.activate([DummyTweenPlugin]);
// first you need to activate the plugin, but only once in the whole app

TweenLite.to(this, 1.0, {dummy:{}, onUpdate:method});

This way there’s no need to create an Object variable. I think it’s a bit simpler. Actually this article took much more time to write than to code the DummyTweenPlugin.

mDocs.

As you saw in my last post, I use autogenerated NaturalDocs documentation.

I was not really happy with skins NaturalDocs provides by default and was not able to find anything usable, so I decided to create my own. If you like it, feel free to use it. Git repo is here.


Click the image to see the full resolution.

Vancura-AS3-Libs.

Finally I was able to take some free time
and open my AS3 libraries.

What does it do? Read the docs here: here and point your browser to the git repo.

Features

Currently these features are covered:

Core functions

Easy Far wrapper:

  • Far
  • FarHelperItem

More features coming soon: skinnable widgets, remoting and more. Watch this space for more information.

How to get the SWC

There are several ways to get the library for use in your project.

Binary distribution

In case you’re lazy or you don’t have all required components to compile it on your machine, you can grab the SWC here.

Compilation from source

You can compile the SWC very easily. In simple words you just need to launch ./compile.sh file. I wrote it on OSX, but it should work fine on a Linux machine as well. The only issue, actually, is the Windows machine. Since I don’t have access to any Windows installation around here, you have to figure out how to compile it. Just take a look at the compile.sh file and you’ll see what’s going on there.

The library uses several 3rd party components: * Greensock Tweening Platform (known as TweenNano, TweenLite and TweenMax) * Printf-AS3, an article here. * Vanrijkom Flashlibs * Uni fonts by miniml.com

All these files are downloaded from internet and not included in the source package. Hence you’ll get the most up-to-date SWC if you compile.

Of course you need Adobe Flex SDK. In my compile.sh script I use FlexSDK4 beta, which is not out yet, but works pretty well for me.