How to switch between screens?


#1

I know this is a trodden thing to say, but I’m new to haxe and Openfl,and I was wondering if there is an easy way to switch screens.

Unfortunately I couldn’t find any tutorial for haxe, so, do you know a good tutorial or is there a build-in function in Openfl to switch between screens?.. or do I have to write my own screen manager?


#2

One possible way is to make a class for each screen:

class MenuScreen extends Sprite {
    super();
    
    addChild(new Bitmap(Assets.getBitmapData("Title.png")));
    
    //Add buttons and so on...
}

class GameScreen extends Sprite {
    var playerCharacter:Character;
    
    public function new() {
        super();
        
        playerCharacter = new Character();
        addChild(playerCharacter);
        
        //Etc.
    }
}

Then you could switch between them:

public static function toGame():Void {
    Lib.current.removeChild(currentScreen);
    
    currentScreen = new GameScreen();
    Lib.current.addChild(currentScreen);
}

public static function toMenu():Void {
    Lib.current.removeChild(currentScreen);
    
    currentScreen = new MenuScreen();
    Lib.current.addChild(currentScreen);
}

HaxeFlixel does something like this; look at their examples for more.


#3

Hello, you can check my very simple screen manager:
https://github.com/dmitryhryppa/dhFramework/tree/master/dhFramework/screens
It’s pretty simple and not optimized, but it is a good way to start.

How to use. In Main class you need to initialize manager:

ScreenManager.initialize( stage ); // stage or any DisplayObject, it will be a container for all screens

Then create the screen. Basic screen class lloks like:

class GameScreen extends Sprite implements IScreen
{
        public function new() {
            super();
 	}
	public function initialize():Void { 
            // here is your init code
        }

        public function update(deltaTime:Float):Void {
            // here is your enterframe function
        }

	public function unload():Void {
            // and this function will be called when you change the screen. 
        }
}

To load your any screen do:

ScreenManager.loadScreen(new GameScreen());

Sorry for my English :smile:


#4

Whatever you do, you might consider supporting a “hide” and “show” for scenes, which may take time. This is incredibly useful for animating a scene out, and the next one in, even if it is just a simple fade, rather than assuming it will be an instant transition.

I also tend to use a showScene () method, something like this:

function showScene (scene:Scene) {
    
    var delay;
    
    switch (currentScene) {
        
        case START:
            
            Actuate.tween (startScreen, 1, { alpha: 0 });
            delay = 0;            

        case GAME:
            
            Actuate.tween (gameScreen, 1, { alpha: 0 });
            delay = 0;            

    }
    
    switch (scene) {
        
        case START:
            
            Actuate.tween (startScreen, 1, { alpha: 1 }).delay (delay);
        
        case GAME:
            
            Actuate.tween (gameScreen, 1, { alpha: 1 }).delay (delay);
        
    }
    
    currentScene = scene;
    
}

and the enum:

enum Scene {
    
    START;
    GAME;
    
}

This was an over-simplified example, but it uses a currentScene value to know what scene you are coming from, depending, it can make the previous scene disappear properly. You could wrap this into a hide () method if you use a common base class. Similarly, it switches on the new requested scene, which could be put in a show () method, to show the next scene. Another optimization might be to return if (currentScene == scene) so that you can call showScene repeatedly without restarting the animation.


#5

If you want “third-party” solutions, HaxeFlixel does this out-of-the-box. You organize your code into a series of state classes, and switch between them (one line of code).


#6

Hi , i have a question i used something like this to change of scenes this work in flash, android and html5 but neko only the first time i call the function but i cant go to any scenes… can you help me?


#7

Do you have any example code that could point to the issue?


#8

Hi this is how i do it for now:
Scene is a sprite that it is added to the stage

static var _scene:Scene;
public static var scene(get, set):Scene;
static function get_scene():Scene 
{
	return _scene;
}

static function set_scene(value:Scene):Scene 
{
	
	if (_scene!=null) 
	{
		_stage.removeChild(_scene);
		trace("scene removed");
	}
	_scene = value;
	_stage.addChild(_scene);
	trace("scene added");
	
	#if nape
	try 
	{
		var debugDraw:Bool =  cast(_scene, NapeScene).debugDraw;
		if (debugDraw == true) 
		{
			var debugDisplay:DisplayObject = cast(_scene, NapeScene)._debug.display;
			_stage.addChild(debugDisplay);
		}
		
	}catch (e:Dynamic)
	{
		trace("this scene doesn't support nape");
	}
	#end
	
	var scaleX:Float = stage.stageWidth / STAGE_WIDTH;
	var scaleY:Float = stage.stageHeight /STAGE_HEIGHT;
	
	_scene.scaleX = scaleX;
	_scene.scaleY = scaleY;
	_scene.x = stage.stageWidth / 2 - (STAGE_WIDTH * scaleX) / 2;
	_scene.y = stage.stageHeight / 2 - (STAGE_HEIGHT * scaleY) / 2;
	return _scene;
}

#9

Do you get any trace output?


#10

Only the first one “scene added” after that does’nt show any trace


#11

Does commenting the Nape code make a difference?


#12

doesn’t do anything, i dont know what it can be happening


#13

I think it must be something outside of this code, unless I am missing something :slight_smile: