Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am working on a Flash Tower Defense game. I have a main game loop which is an eventListener for each frame. Whenever you gain money or lose a life, I want the GameUI to be updated to display this change. Right now, it checks every frame for a change. How can I create an event to only change this information whenever the lives or money changes?

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

While Valke answered your question regarding custom events perfectly, I usually try to avoid Events in Flash for game-development. Robert Penner lists some good points why Events are bad.

Custom events are especially bad, when you're dispatching them very frequently (a common scenario in games), because every time you dispatch the event a new Event object will be allocated and also has to be garbage-collected later on.

I found the signal/slot pattern to be a very good replacement for most event-related stuff. There's the excellent as3-signals library or the fast turbosignals library for flash.

With as3-signals, your game class could look something like this (I omitted any irrelevant stuff):

public class Game
{
    // the signal that will dispatch whenever the money changes
    public var moneyChanged:Signal = new Signal(int);

    // ENTER_FRAME listener
    private function handleEnterFrame(e:Event):void {
        // the player collected money.. we can dispatch an "event"
        if(player.hasCollectedMoney){
            // dispatch the collected money amount
            moneyChanged.dispatch(player.collectedMoneyAmount);
        }
    }
}

Your GameUI class would simply have a method to update the money:

public class GameUI
{
    public function updateMoney(amount:int):void {
        // .. update money...
    }
}

All that is left to do, is to connect the signal to the update method (slot). You usually do this somewhere at initialization time, but you can also add/remove listeners/slots during runtime. eg.

var game:Game = new Game();
var gui:GameUI = new GameUI();
game.moneyChanged.add(gui.updateMoney);

Done! Whenever the game dispatches "moneyChanged", the gui will be updated. This also works nicely with multiple listeners, so you could also have a ScoreManagerclass, that also listens to moneyChanged updates.

share|improve this answer
    
Is this still basically checking every frame if money has changed? Right now, I just update the UI every frame with the money amount, so I guess this just doesn't update the UI unless it has too, so that should help the game efficiency a bit. –  Sean May 12 '11 at 18:50
    
Also, I am using Flash CS5, how do I import the custom library for signals? I never done that before. –  Sean May 12 '11 at 19:15
    
@Sean: Well, somewhere you have to trigger the money-change event.. right? Maybe that's when the player collides with a coin or something. Code above was just an example. The idea is that the game will dispatch the signal only when necessary and all listeners will then (and only then) update. The easiest way to add the library to Flash is to download the .swc file and add it to the "Library path" tab which can be found in: File > Action Script Settings. Use "Browse to SWC File" there. –  bummzack May 12 '11 at 22:04
    
SWC download is here: github.com/downloads/robertpenner/as3-signals/… –  bummzack May 12 '11 at 22:05
    
It is good to see alternative solutions such as Signals -- thanks. I disagree with your reasoning behind using Signals however. If you are using an absurd amount of events in a real time game, there is a much larger problem in your architecture. So much so that you need a whole other library to get by? Bollocks. –  Nick Wiggill May 13 '11 at 17:29
show 3 more comments

you can create a custom event class this way:

1 / In a new .as file (say GUIEvent.as) create the following class

package {

    import flash.events.*;

    public class GUIEvent extends Event {

        public static const DEFAULT_NAME:String = "GUIEvent";
        public var _params:*;

        // your events types
        public static const GET_LIFE:String = "getLife";
        public static const GET_MONEY:String = "getMoney";
        public static const GET_GLOBAL:String = "getGlobal";
        public static const GET_ETCETERA:String = "getEtc";

        public function GUIEvent($type:String, $params=null , $bubbles:Boolean=false, $cancelable:Boolean = false){
            super($type, $bubbles, $cancelable);
            this._params = $params;
        }

        public override function clone():Event{
            return new GUIEvent(type, this._params, bubbles, cancelable);
        }

        public override function toString():String{
            return formatToString("GUIEvent", "_params", "type", "bubbles", "cancelable");
        }   
    }
}

2/ In the place you want to register for the events (probably your MainClass.as)

import GUIEvent;

YourGuiObjectWaitingForTheUpdates.addEventListener(GUIEvent.GET_LIFE, GUIupdateHandler);
YourGuiObjectWaitingForTheUpdates.addEventListener(GUIEvent.GET_MONEY, GUIupdateHandler);
YourGuiObjectWaitingForTheUpdates.addEventListener(GUIEvent.GET_GLOBAL, GUIupdateHandler);

3/ Place the function provided to the addEventListener where it should be (still probably in your MainClass.as)

private function GUIupdateHandler(evt:GUIEvent):void
{
    switch(evt.type) { 
        case GUIEvent.GET_LIFE:
            //modify lives on the GUI using evt._params.life
            break;
        case GUIEvent.GET_MONEY:
            //modify money value on the GUI using evt._params.money
            break;
        case GUIEvent.GET_GLOBAL:
            //modify lives AND money value on the GUI using evt._params.life and evt._params.money
            break;
        default:
            //nothing ?
}

4/ Finally, dispatch the events when you need to update you GUI...

this.dispatchEvent(new GUIEvent(GUIEvent.GET_LIFE, {life:3}, true));
//or
this.dispatchEvent(new GUIEvent(GUIEvent.GET_MONEY, {money:333}, true));
//or
this.dispatchEvent(new GUIEvent(GUIEvent.GET_GLOBAL, {life:3, money:333}, true));

I do not practice AS3 anymore, but I have played with it for years so it should be almost OK... but I could have forgotten something through.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.