Game State Demo in Projects
Shri

Waders,

 

I put a little demo of how to implement game states in Wade

It is up in the projects section titled - Game State Demo

 

What are game states you ask - The various modes your game goes through as it is played.

For example - initially you show an introduction screen with the title and you have a message to click to start.

Then you want to load a level or show a menu.

After that, the player is actually playing your game.

Then maybe a level completes and eventually the game is over.

 

These are all defined as different states I have coded up a game state object which has three methods.

  • getName() - returns the states name
  • enter() - what to do on state entry
  • exit() - what to do on state exit

 

In your main app then, you just need this little snippet of code to transition between the various game states

this.changeGameState = function(newState) {		if (currentState) {			currentState.exit();			currentState = null;		}		currentState = new window.self[newState]();		currentState.enter();	};	// end changeGameState

If you look at the various .js files, it should be pretty easy to understand.

 

Using this method should make game state management easier than impementing a bunch of conditional statements in your code

 

The bird animations and background images are courtesy of Bevoulin at opengameart.org under the CC-0 license.

 

Gio - Game state management is something that everyone has to deal with and is constantly being reinvented. Looking at some other

engines / frameworks (ex: Kiwi,  Phaser) I noticed that some of them have a built in "state" object you could use to transition you game through it's

various modes. Is this something you could consider adding to wade in future releases ?  I think it would make wade more attractive to developers.

It seems like that is the direction you were headed with loading and preloading scenes ?

 

cheers,

Shri

All 9 Comments
Gio

Hi Shri

 

That's nice, it's a neat way of managing game states and a perfectly valid way of doing things.

 

WADE, however, has a scene system, which is a superset of a state system. That is, using scenes you can do what a state system does, but scenes are a more general concept that allows you to do more.

 

I'll take this opportunity to say something about scenes and how they work. It's a nice flexible system, although I understand it may take time to get used to it.

 

In WADE there is always a current active scene. This includes everything that is on the screen, plus some other things (objects can be in the currently active scene but set to invisible for example). The states of the objects that are in the scene, including their properties and member functions, are also part of the scene. The assets used by the objects that are in the scene (images, sounds, fonts, JSON data files) are also part of the scene, which means that they can be loaded automatically when a scene is loaded. Additionally, a scene can also reference a set of "global" scripts that aren't members of any of the objects.

 

An important point is that scenes are data objects so they can be saved to and loaded from JSON files. This also includes scripts and functions, that get converted to strings before being exported as part of the scene.

 

There are few functions to interact with scenes, the key ones being:

 

wade.exportScene() that saves everything that is in the current scene to a data object

wade.importScene() that processes a scene data object to create and add objects to the scene, load their assets, load and execute global scripts, etc

wade.loadScene() that reads a JSON file, converts it to an object and passes it to wade.importScene()

wade.preloadScene() that does the same thing but asynchronously, without stopping the execution of the game

 

There are some arguments that you can pass into these functions to control exactly what they do - for example, should the current scene be cleared before adding objects from the next scene? Do you want to use the browser cache or force reloading everything? When exporting, do you want a string, or an object as the result? And so on.

 

So with this system it should be pretty easy to manage states. If you want a function o be executed when a scene is loaded, add a script that executes this function to the scene. Or if you prefer, add an onAddToScene function to the background object, for example. And add an onRemoveToScene function to it, with the code that you want to execute when the background is removed.

 

Let's make an example. Say that you are in the middle of the game and want to open a menu.

wade.app.lastScene = wade.exportScene();wade.loadScene('menu.wsc');

menu.wsc is just a JSON file. We use .wsc as the default extension for wade scenes in the editor, but it's just JSON

menu.wsc contains all the objects for the menu, their properties and, just to make an example, a "Close" button that has an onClick function (also defined inside menu.wsc) that does this:

wade.importScene(wade.app.lastScene, 0, 0, 1, 1);

So that's all the code that you need (3 lines) to effectively implement a state system and manage states using scenes.

 

There are caveats and it can get a bit more complicated when objects have cyclical references and cannot be easily serialized, but you get the idea :)

 

There are also similar (but better performing) ways of doing this if performance is an issue. The above code is simple and will take a fraction of a second to execute (WADE has its own internal cache that speeds the process up, so it's quite fast), but if you want to be faster there are other ways, such as getting a list of scene objects in the scene before loading the menu, and when exiting the menu remove any object that isn't in the list. Again, it's probably around 5 lines of code to do it that way and should be pretty straightforward.

Shri

Gio,

 

Thanks for the info.

I was pretty sure you guys already had something to handle game states based on zirma.

But c'mon, the scene functionality is in no way intuitive from the documentation in the snippets or the api.

 

Could you please provide an example of:

"If you want a function to be executed when a scene is loaded, add a script that executes this function to the scene."

and/or (but I suspect it will be the same ?)

"a "Close" button that has an onClick function (also defined inside menu.wsc) that does this:"

 

I think it would be the following, but does it have to be a self executing function ?

Also, this line from the documentation

"scripts: An array of script (.js) file names. Note that these scripts will be loaded and executed after the rest of the scene has been loaded, but before any scene objects are created and added to the scene"

means that you can't reference any scene objects in the script ?

--------- load.js-------------------(function() {    console.log('myScene loaded');})();---------end load.js----------------var data = { json: [myScene.json],             scripts: [load.js]            };wade.importScene(data,0,0,0,1);

avere un weekend excellente, ciao!

Shri

 

Shri

Gio,

 

I was fooling around with the scene stuff

 

Here is my intro.wsc file:

{ "sceneObjects": [	{		"type": "SceneObject",		"behaviors": ["IntroScene"],		"sprites": [			{				"type": "Sprite",				"image": "./images/introScreen.jpg",				"visible": true,				"autoResize": true,				"layer": 2			}		],		"name": "Intro",		"addToScene": {			"params": null		}	}]}

Here is my behavior file:

IntroScene = function() {	var self = this;		this.onAddToScene = function(eventData) {		console.log(name + ' added to scene');	};	// end onAddToScene		this.onClick = function(eventData) {		console.log('intro scene clicked');		return true;	};	// end onClick		this.onRemoveFromScene = function() {		console.log(name + ' removed from scene');	};	// end onRemoveFromScene	};	// end IntroScene

The intro image shows, bu I am not getting anything from the behavior ?

It works as expected if I use wade.addSceneObject(object, IntroScene);

 

Also, how do you set it up to autoListen ?

"autoListen": true, -- with a line like this in the addToScene in the .wsc file

 

thanks,

shri

Gio

It looks all correct, it should work if you just set it to autolisten. In fact, the second argument of addSceneObject is a bool that says whether to autoListen, and your wade.addSceneObject(object, IntroScene) is equivalent to wade.addSceneObject(object, true);

 

You should only need to do this:

"addToScene": {"autoListen": true}

Everything else is fine. A few other notes anyway, they may be helpful:

 

  • The "type" fields are optional. They are mainly there because it's sometimes useful, given a data object, to know what it represents. But you don't need to specify the types when describing a scene, as WADE can deduce them from the scene structure.
  • "visible" is also an optional one as it is true by default anyway, you want to use it only when setting it to false
  • "name" is also optional, but I think it's good practice to have it, so you can do things like wade.getSceneObject('Intro') in your code
  • you'd use "params" inside "addToScene" to specify some parameters to be passed to the object's onAddToScene function. If you don't want to pass any parameters, you can omit the "params" field
Shri

Gio,

 

Still can't get the click to work

 

my intro.wsc file

{ "sceneObjects": [	{		"behaviors": ["IntroScene"],		"sprites": [			{				"image": "./images/introScreen.jpg",				"autoResize": true,				"layer": 2			}		],		"name": "Intro",		"addToScene": { "autoListen": true }	}]}

my intro scene behavior file

IntroScene = function() {	var self = this;		this.onAddToScene = function(eventData) {		console.log('intro scene added to scene');	};	// end onAddToScene		this.onClick = function(eventData) {		console.log('intro scene clicked');		return true;	};	// end onClick		this.onRemoveFromScene = function() {		console.log('intro scene removed from scene');	};	// end onRemoveFromScene	};	// end IntroScene

the main

this.sceneCallback = function() { console.log('scene load callback'); }		this.loadIntro = function() {		console.log('load intro scene');		wade.loadScene('./intro.wsc',0,self.sceneCallback,1);		/*var sp = new Sprite('./images/introScreen.jpg',2);		var o = new SceneObject(sp,IntroScene);		wade.addSceneObject(o,true);*/	};	// end loadIntro

I get the callback, but it seems as if the behavior is not being attached to the scene object as I am not getting anything from the behavior - added to scene, click.

 

If I run the loadIntro with the commented out code, everything works as expected.

I must be attaching the behavior incorrectly but I'm not sure what I am doing wrong ?

 

cheers,

Shri

Gio

Could it be that the script where IntroScene is defined is not loaded? If it's supposed to be loaded as part of the scene, you'll want to add a "scripts" field to the root of the scene structure:

"scripts" : ["introScene.js"]

I may be able to help more if I can look at the whole thing. Do you want to upload it to a new Share and Fork project, or maybe attach a zip?

Shri

Gio,

 

Here it is.

When I check for scene objects on return from the load scene, I get that there are no (zero) scene objects ?

 

cheers,

Shri

Gio

Hey Shri

 

Sorry, my bad for not spotting it earlier - also I recognize that the documentation is unclear and I've updated it for the next release. The "behaviors" field is an array of objects like this:

"behaviors": [{"name": "IntroScene", "properties": {...}}]

Where "properties" is optional, and is an object that contains the values that you want to assign to your behavior's public variables. In your case it can safely be omitted, so just:

"behaviors": [{"name" : "IntroScene"}]
Shri

Gio,

 

Made the change, it seems to work as advertised - thanks.

I will try to get around to adding a project that does game state management with the scene system.

 

As an aside, it would be nice if you guys did some tutorials for the "system" level stuff.

The basic tutorials (code snippets and api) are good and the high level (example games on the site) are good, but

there are "system" wide things that wade does but which are pooly documented or even unknown,  to the casual developer.

Some examples - an aggregate list of event handling, the scene system for game state management, saving/retrieving game state/data, the draw functions and how you would use them in your games (flashlight effect, bloody screen, etc).

It looks like you are beefing up the video tutorials so maybe it is already in the works, anyway just my two cents.

 

"come sempre, grazie per l'aiuto".

 

cheers,

Shri

Post a reply
Add Attachment
Submit Reply
Login to Reply