Dispatching Signals with HaxeFlixel

ShaunHaxeLeave a Comment

Haxe C++ target

When the play button is pressed, I don’t want it to switch state in the context of the button like seen below, but in a function contained in the Main Menu state, this gives me more control of other components, such as a bringing up a loading screen while the state switches.

/**
 * @author Shaun Stone (SMKS)
 */
class MainMenuScreen extends FlxState

...
/**
 * @author Shaun Stone (SMKS)
 */
class PlayButton extends BaseButtonGroup
{
	var iconAssetName:String = "play";

	public function new(textureAtlas:SparrowData) 
	{
		this.icon = getIconByName(this.iconAssetName);
		
		super(textureAtlas, BaseButtonGroup.LARGE_BUTTON);
	}
	
	override public function positionIcon() 
	{
		super.positionIcon();
		
		iconSprite.x += GameSize.getPositionByPlatform(20);
	}

        override function onMouseUp(object:FlxObject) 
        {
               super.onMouseUp(object);
 
               FlxG.switchState(new NormalGameModeScreen());
        }

}

I found on an Android device, switching state there is a 2-3 second pause as it prepares the next screen. I wanted to pull up a loading icon so it doesn’t look like the game has crashed.

First off, I pass in a new argument when creating a new instance of the button called: callback with the option to pass a string value.

/**
 * @author Shaun Stone (SMKS)
 */
class BaseButtonGroup extends FlxSpriteGroup
{

...

    public function new(textureAtlas:SparrowData, BaseButtonGroup.NORMAL_BUTTON,
	?callback:String->Void
    )
    {
	super(
		BaseButtonGroup.X_POS, 
		BaseButtonGroup.Y_POS, 
		BaseButtonGroup.MAX_BUTTON_SPRITES
	);

        ....

        this.addSubscriber(callback);

...
}

In my state screen I pass an anonymous function.

btn = new PlayButton(textureAtlas, function(str:String):Void
	{
		trace(str + ' button has been pressed');
	}
);
add(btn);

I then register the signal by calling addSubscriber. This will create the signal if it doesn’t exist.

public function addSubscriber(listener:String->Void):Void
{
     if (signal == null) {
         signal = new FlxTypedSignal<String->Void>();
     }
 
     signal.add(listener);
}

Now in the play button I dispatch the signal on mouse up. This is then caught in the state screen, and from there I can do what I need to do.

PlayButton.hx

 override function onMouseUp(object:FlxObject) 
 {
     super.onMouseUp(object);
 
     this.dispatchSignal('play');
 } 

function dispatchSignal(?string:String):Void
{
	if (signal == null) {
		throw "Signal instance undefined";
	}
	
	signal.dispatch(string);
}

MainMenuScreen.hx

btn = new PlayButton(textureAtlas, function(str:String):Void
	{
		trace(str + ' button has been pressed');
		
		// show loader
		
		// switch state
	}
);
add(btn);

Leave a Reply

Your email address will not be published. Required fields are marked *