Help with game states with classes

hello folks,

so after my other questions about text, button and other such things. the one thing i am trying to get into is using game states properly.
i have done them before in other languages, but seems to be slightly different. especially when buttons are involved. keyboard stuff is fine, thats pretty easy. but getting a button class to talk to the main class to change scenes is confusing me somewhat. maybe im not looking at things right. well, actually i think thats obvious since im asking for help :wink:

but when i have set up is a simple menu class, this holds buttons, the header for the menu, and really thats it. then its called into the Main.hx for it to be used. and to some effect it does. i had set up a trace, just so i can see if it being pressed. but cant work out the change it scene to what i need.
its thing like classes talking to other classes that has confused me comparred to other laguages i have used in the past

now this is what i have with my main, or at least some of the code

enum GameState {
	Menu;
	Playing;
	Retry;
}

class Main extends Sprite {
	var player:PlayerClass;
	var enemy:EnemyClass;
	var currentGameState:GameState;
	var menuClass:MenuClass;
	var startSelect:Bool;
	
	public function new () {
		
		super ();
		
		player = new PlayerClass();
		enemy = new EnemyClass();
		menuClass = new MenuClass();

		setGameState(Menu);
	}

	private function setGameState(state:GameState):Void {
		currentGameState = state;
		if (state == Menu) {
			addChild(menuClass);
			
		} else if (state == Playing) {
			addChild(player);
			addChild(enemy);
		} else if (state == Retry) {
			
		}
	}
}

and im quite happy with that setup. though am sure it could be done better.
and now here is the menuclass.hx, which is using, not the simplebutton [because i still have not worked that out ;)] but something @yupswing had guided me towards :wink:

var optionsButtonFormat = new TextFormat(menuHeaderFont.fontName, 30, 0x000000, false);
		var optionsButtonField = new TextField();
		optionsButtonField.defaultTextFormat = optionsButtonFormat;
		optionsButtonField.selectable = false;
		optionsButtonField.x = 450;
		optionsButtonField.y = 600;
		optionsButtonField.scaleX = 1;
		optionsButtonField.scaleY = 1;
		optionsButtonField.width = 175;
		optionsButtonField.height = 28;
		optionsButtonField.text = "OPTIONS";
		addChild(optionsButtonField);

		startButtonField.addEventListener(MouseEvent.CLICK,onStartClick);
		optionsButtonField.addEventListener(MouseEvent.CLICK,onOptionsClick);
	}
	public function onOptionsClick(event:MouseEvent):Void {
		trace('clicked me OPTIONS');
	}

but its just getting the created buttons to change my enum GameState. just a bit o’ help needed really

many thanks :wink:

and to add. i have looked at HaxeFlixel, and that seems to have a game state type library. im not looking to move to HaxeFlixel by the way :wink: but is there something like that for OpenFL?

just a thought really. ill have a check. may answer my own question :wink:

EDIT
nope, didnt find anything that has an openfl type gamestate library. just directs me to flixel, which i would rather not install. just extra stuff really :wink:
would like to stick with just openFL :wink:

A few things:

  1. Class names should not end in “Class” unless your game is about school. “PlayerClass” could be reduced to “Player” without losing any information.
  2. By far the easiest way to switch states is with a static method call.
  3. Don’t make the setGameState() function determine the contents of each state. Instead, make a separate class for each one.
  4. Enums are cool and all, but this isn’t the place for them.

How about something more like this? (Getters and setters are optional but convenient.)

class GameState {
    public static var current(default, set):Sprite;
    private static function set_current(state:Sprite):Void {
        if(current != null) {
            Lib.current.removeChild(current);
        }
        
        current = state;
        Lib.current.addChild(current);
    }
    
    public static var menu:MenuState = new MenuState();
    public static var playing:PlayState = new PlayState();
    public static var retry:RetryState = new RetryState();
}

Now your Main class can be reduced to this:

class Main {
    public function new() {
        GameState.current = GameState.menu;
    }
}

Much cleaner!

And since it’s static, you can update GameState.current from anywhere in your code.

1 Like

awesome balls.

aye the whole ‘put class at the end’ has just been something that i did so if IF anything was called Player in the cosmos of whatever i was using it wouldnt conflict. :slight_smile: but think its a habit i can drop now.

but that is brilliant. ill have a good dig around. just these type of things are nice to try and weed out really. since everyone does use them :wink:

again, thanks a bunch

EDIT
also i was looking the replace enums. worked with them before, but as you said, this isnt the place for them :wink:

ANOTHER EDIT
but also, in my defence for using CLASS at the end. im still learning, so may use that as an excuse :wink:

well ive now actually started my project al over again :wink: seemed the best thing to do. i remember exactly what ive done, but with these changes and new things to learn, its best to start flesh :wink:

hmmm. ive tried this code a few times, but im sure im missing something completely.
my setup right now is using the folder storage method, so i have to import everything when needed. also by setting the ‘package’ to ‘state’ or whatever the actual file is in.

but on making a GameState.hx file, putting that exact game state code in and then using the main.hx code you posted im getting nothing but errors.

here is the project ive made usng the code on here, but im just a bit lost because i dont know the ‘why’ its not working.

many many thanks. this has been driving me slightly up the bend from not knowing or figuring it out

main.hx

package;

import openfl.display.Sprite;
import state.GameState;

class Main extends Sprite {
	public function new () {
		super ();
		GameState.current = GameState.menu;	
	}
}

state.GameState.hx

class GameState {
    public static var current(default, set):Sprite;
    private static function set_current(state:Sprite):Void {
        if(current != null) {
            Lib.current.removeChild(current);
        }
        
        current = state;
        Lib.current.addChild(current);
    }
    
    public static var menu:MenuState = new MenuState();
    public static var playing:PlayState = new PlayState();
    public static var retry:RetryState = new RetryState();
}