Phaser III
Game Prototype Library


Integrated Index.html with Game.js

Unorthodox Method: combining index.html with game initialization logic is typical deployment for mobile apps. Refer to this example

<!doctype html>  
<html>  
<head>  
	<meta charset="utf-8">  
	<title>Phaser 3 Game Prototyping - unorthodox</title>  
	<meta name="description" content="Phaser 3 Game Prototyping Template" />  
	<link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />  
	<style>  
		body{margin:0;padding:0}  
		canvas {margin: 0 auto;}  
	</style>  
	<!--  
		NOTE: Phaser library must be loaded prior to any game logic.  
		We load script files here to avoid windows.onload call.  
		Window.onload is rarely used for many reasons, and because  
		phaser doesn't wait until all resources are loaded.  
		The DOMContentLoaded event triggers when the page is ready.  
		Phaser waits for the full HTML and scripts, and then starts.  
		This is explained in greater detail in ["Phaser.JS Design Guide workbook".](https://leanpub.com/phaserjsgamedesignworkbook)
	-->  
	<script src="https://cdn.jsdelivr.net/npm/phaser@3.24.1/dist/phaser.js"> </script>  
	<script src="js/states/Boot.js"></script>  
	<script src="js/states/Preloader.js"></script>  
	<script src="js/states/Languages.js"></script>  
	<script src="js/states/MainMenu.js"></script>  
</head>  
<body>
<h1>Unorthodox Method: combining index.html with game initialization logic </h1>
  <div id="orientation"></div>
  <div id="gContent"></div>
<!-- 
NOTE: Phaser library must be loaded prior to any game logic. 
We load script files here to avoid windows.onload call. 
Window.onload is rarely used for many reasons, and because 
	phaser doesn't wait until all resources are loaded.
The DOMContentLoaded event triggers when the page is ready. 
Phaser waits for the full HTML and scripts, and then starts.
This is explained in greater detail in 
	["Phaser III Design Guide workbook".](https://leanpub.com/phaser3gamedesignworkbook)
-->
<script src="https://cdn.jsdelivr.net/npm/phaser@3.24.1/dist/phaser.js"> </script>
<script src="js/states/Boot.js"></script>
<script src="js/states/Preloader.js"></script>
<script src="js/states/MainMenu.js"></script>
<script src="js/states/Game.js"></script>
<!-- 
NOTE: per the Phaser 3 Design Guide workbook, you may place the following
script externally or as the last head script using defer. 
-->


<!-- Creating Client WebSocket -->
<script >
	function WebSocketTest() {
		if ("WebSocket" in window) {
			alert("WebSocket is supported by your Browser!");
			// Let us open a web socket on local development site;

			//TODO: Change the URL to point to your live production server.
			//Classic OOP style creates object/function:
			var ws = new WebSocket("ws://localhost:9998/echo");

			//OLOO style; note that false warning
			//var ws = Object.create(WebSocket("ws://localhost:9998/echo"));

			//
			//============================
			// 4 WebSocket Protocol Msg
			//============================
			ws.onopen = function onopen(event)
			{
				// Web Socket is connected, send data using send()
				ws.send("Test Message sent");
				alert("Test Message away, away ... Captain!");
			};
			ws.onmessage = function onmessage(event) 
			{ 
				var received_msg = event.data;
				alert("Incoming Messages ... brace for impact, Captain!");
			};
			ws.onclose = function onclose()
			{ 
				// websocket is closed.
				alert("Connection is closed..."); 
			};
			//============================
			// End of WebSocket Protocol
			//============================
		} else {
			// The browser doesn't support WebSocket
			alert("WebSocket NOT supported by your Browser!");
		}
	}
</script>

<!-- Facebook Instant Game deployment??? -->
<!-- <script src="https://connect.facebook.net/en_US/fbinstant.6.0.js"></script>  -->

<script id="unorthodox">
/**  
 * File Name: combines index.html & initial boot.js  
 * Bonus File Content URL: https://leanpub.com/LoRD  
 * Description: monolithic File for controlling and displaying game scenes;  
 *  managing global variables throughout game state.  
 * Author: Stephen Gose  
 * Version: 0.0.0.15  
 * Author URL: https://www.stephen-gose.com/  
 * Support: support@pbmcube.com  
 *  
 * Copyright © 1974-2017 Stephen Gose LLC. All rights reserved.  
 *  
 * Do not sell! Do not distribute!  
 * This is a licensed permission file. Please refer to Terms of Use  
 *   and End Users License Agreement (EULA).  
 * Redistribution of part or whole of this file and  
 * the accompanying files is strictly prohibited.  
 *  
 */  

	;//Closes any previous scripts
	// creates a global variable called game
	// =========================================================
	var game = {};
	var gWidth, gHeight;
	var isMobile=navigator.userAgent.indexOf("Mobile");
	var config = {};
	
	//load any major scene change initially; defer everything else  
	var states = {  
		//'AboutUs':	GAMEAPP.AboutUs, 	//Deferred to MainMenu  
		'Boot':		GAMEAPP.Boot,  
		//'Credits':	GAMEAPP.Credits, 	//Deferred to MainMenu  
		//'Donations':	GAMEAPP.Donations, 	//Deferred to MainMenu  
		//'GameOver':	GAMEAPP.GameOver, 	//Deferred to MainMenu  
		//'Help':     	GAMEAPP.Help, 		//Deferred to MainMenu  
		'Languages':	GAMEAPP.Languages,  
		'ManinMenu':	GAMEAPP.MainMenu,  
		//'Options':	GAMEAPP.Options, 	//Deferred to MainMenu  
		'Preloader':	GAMEAPP.Preloader,  
		//'Scores':   	GAMEAPP.Scores, 	//Deferred to MainMenu  
		//'Share':    	GAMEAPP.Share, 		//Deferred to MainMenu  
		//'WebMasters':	GAMEAPP.WebMasters 	//Deferred to MainMenu  
	};  
	  
	for(var state in states){  
		game.scene.add(state, states[state]);  
	}
	console.table(states);  
	//daisy-chained; Equal to Phaser v3 'manual start'  
	game.scene.start('Boot'); 
	
	//preferred game launch method.
document.addEventListener('DOMContentLoaded', function(){
	// ============
	// Example: 2.2 Launching a name-space "Game".
	// ============
	// window.GAMEAPP.main(); //name space activation
	// console.log("Game obj: === Ext? "+Object.isExtensible( GAMEAPP ));
	// console.log(Object.values(GAMEAPP));
	// console.log(Object.getPrototypeOf(GAMEAPP));
	// console.log(Object.getOwnPropertyDescriptors(GAMEAPP));
	
	// OR: global variable launched; similar to Phaser v2.6.2
	// ============
	// Example: 2.2 Launching a Global variable "Game".
	// ============
	// var gWidth  = 800;	//Using Golden Ration is important.
	// var gHeight = 500;	//Using Golden Ration is important.
	// Lessons learned from colleagues
	// initial size determined
	if (isMobile != -1) {
		//-1 is desktop/anything other than mobile device
		console.log("isMobile="+isMobile);
		gWidth = window.innerWidth * window.devicePixelRatio;
		gHeight = window.innerHeight * window.devicePixelRatio;
	}
	
	config = {
		//use : window.GAMEAPP.viewportWidth,
		width:	gWidth || 800,	//Using Golden Ration is important. 
		//use : window.GAMEAPP.viewportHeight,
		height:	gHeight || 500,	//Using Golden Ration is important.
		type:	Phaser.AUTO,
		title: 'Phaser3 Game Prototyping Starter Kit',		//Game Title
		url: 'https://makingbrowsergames.com/p3gp-book/',	//Game URL 
		version: '0.0.1.0 semver ',	//https://semver.org/spec/v1.0.0.html
		input: {
			keyboard: true,
			mouse: true,
			touch: true,
			gamepad: false
		},
		physics: {
			default: 'arcade',
			arcade: {  
				// Debug active (turned on) for arcade physics  
				debug: true  
			}
		},
		//scene:  window.GAMEAPP.state,
		parent:   document.body
	};
	
	//standard Phaser III launch method
	//Separate name space used  
	//Similar to Phaser v2.x.x   
	game = new Phaser.Game(config);
	/**	
		//Strangely, old v2.6.2 also works in Phaser III!!!
		// try it out and learn what happens!
		game = new Phaser.Game(  
			gWidth, gHeight,    //width and height of canvas  
			Phaser.AUTO,        // how to render canvas  
			"gContent");        // place canvas inside div  
	*/				
	console.log("Game obj: === Ext? "+Object.isExtensible( game ));
	//console.log(Object.values(game));
	//console.log(Object.getPrototypeOf(game));
	console.log(Object.getOwnPropertyDescriptors(game));
	
	console.log("Game prototype (Phaser.Game): === Ext? "+Object.isExtensible( Phaser ));
	//console.log(Object.values(Phaser));
	//console.log(Object.getPrototypeOf(Phaser));
	console.log(Object.getOwnPropertyDescriptors(Phaser));

	// Example: 2.2 ends
	// ============
}, false);
//
// =================================================
</script>

</body>
</html>

See Examples here


External Boot.js Module

Standard Method: using index.html to load and initilize game boot information from external module js file.

/**
Copyright © 1997-2016, Stephen Gose LLC. All rights reserved.
Visit our game show case:	https://www.renown-games.com 
License information:		https://makingbrowsergames.com/starterkits/quiz/
Affiliate Information:		https://www.sgose.com/products/affiliates-program/

 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN  
 * THE SOFTWARE.
 * 
 *
	 * File Name: boot.js
	 * Live Demo: https://makingbrowsergames.com/starterkits/
	 * Source Code: https://makingbrowsergames.com/starterkits/
	 * Description: File for controlling initial game shell launch; managing global variables throughout game state.
	 * Author: Stephen Gose
	 * Version: 0.0.0.xxxx semver launch date
	 * Author URL: https://www.stephen-gose.com/
	 * Support: support@pbmcube.com
	 *
	 * \u00A9 Copyright ©  1974-2017 Stephen Gose LLC. All rights reserved. 
	 * 
	 * Do not sell! Do not distribute!
	 * This is a licensed permission file. Please refer to Terms of Use
	 *   and End Users License Agreement (EULA).
	 * Search for [ //**TODO** ] to tailor this file for your own use 
	 *   and will void any support agreement.
	 *
	 * Redistribution of part or whole of this file and
	 * the accompanying files is strictly prohibited.
	 *
	 */

	"use strict";
	
var boot = new Phaser.Class({

    Extends: Phaser.Scene,
    initialize: function boot () {
        Phaser.Scene.call(this, { key: 'boot' });
    },

		preload: function(){
			console.log("> %c  Game Prototype boot configure browser settings  ", "color:white; background:red");
			
			//Debug Plugin - for tutorials, development and books
			//this.game.add.plugin(Phaser.Plugin.Debug);
// -------------------------------------------
// TODO: Last chance to start WebSocket automatically!!
// -------------------------------------------			
//
// =================================================			
// CORS:
// - https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
// - https://enable-cors.org/
// Avoid this anti-pattern of omitting the protocols schemes in script "src";
// Cross origin requests are only supported for protocol schemes: 
//		http, data, chrome, chrome-extension, https.
//			this.load.crossOrigin = 'anonymous';
//
// =================================================
		this.load.image('twitter', 'assets/twitter.png');
			// required assets for following states here	
			// ARBP mainMenu & Story collapse into one scene
			this.load.path = "assets/images/staticScenes/";			
			this.load.image('background', 'titleScene.jpg');	
			this.load.image('creditScene', 'creditsScene.jpg');	
			this.load.image('langScene', 'languageScene.jpg');
			this.load.image('mainMenu', 'mainMenu.jpg');
			//this.load.image('menus', 'MenuPanelHUD2.jpg');
			this.load.image('storyScene', 'storyScene.jpg');
			this.load.image('titleScene', 'titleScene.jpg');
	/**
			//Language Scene uses StoryPanelHud
			this.load.path = "assets/images/flags/";
			this.load.spritesheet('chinaBtn', 'china.png', 50, 50);
			this.load.spritesheet('dmarkBtn', 'denmark.png', 50, 50);
			this.load.spritesheet('englishBtn', 'english.png', 50, 50);
			this.load.spritesheet('frenchBtn', 'france.png', 50, 50);
			this.load.spritesheet('germanBtn', 'germany.png', 50, 50);
			this.load.spritesheet('italyBtn', 'italy.png', 50, 50);
			this.load.spritesheet('japanBtn', 'japan.png', 50, 50);
			this.load.spritesheet('nlandBtn', 'netherlands.png', 50, 50);
			this.load.spritesheet('portugalBtn', 'portugal.png', 50, 50);
			this.load.spritesheet('spainBtn', 'spain.png', 50, 50);
			this.load.spritesheet('swedenBtn', 'sweden.png', 50, 50);
			
			//UI Buttons
			this.load.path = "";
			//this.load.spritesheet('button', 'assets/spriteSheets/mmog-sprites-silver.png', 129, 30);
			//this.load.atlas('button-continue','assets/spriteSheets/RightArrow-Phaser.png','assets/spriteSheets/arrowR-sprites.json');
			//this.load.atlas('button','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
			//this.load.atlas('langButton','assets/spriteSheets/language.png','assets/spriteSheets/language.json');
			
			//Load button for twitter
			this.load.image('twitter','assets/images/twitter.png');
	*/		
			// set world size
			
			// set the boundaries of our game world
			//this.physics.bounds.width = window.GAMEAPP.worldWidth;
			//this.physics.bounds.height = window.GAMEAPP.worldHeight;
			//this.game.setCollideWorldBounds(true);
			//this.enableScaling();
					
		},

    create: function () {
        this.add.image(0, 0, 'titleScene').setOrigin(0);
        this.input.once('pointerdown', function () {
            console.log('From boot to load');
            this.scene.start('load');
        }, this);
			
			//this.background = this.add.image(0, 0, 'background');

			//ACTIVATE FOR ITCH.IO BUILDS
			//local storage capacity = 5MB per
			//The localStorage object stores the data with no expiration date. 
			//The data will not be deleted when the browser is closed,
			//   and will be available whenever.
			if(localStorage.firstRunDate !== "undefined"){
				localStorage.clear();
				sessionStorage.clear();
			}else{
				console.log(" %c  Resorting to Cookie storage.","color:white; background:red");
			}
			
			//
			if(localStorage.firstRun != "DONE"){
				console.log(" %c  Setting up for first-time run  ","color:white; background:red");
				//firstRun();
			}
				
			// goto load state
			this.scene.start("load");
		},
    }

});
  
      

See Examples here


Prelaod.js

Standard Method: to load game assets from external module js file.

/**
Copyright © 1997-2016, Stephen Gose LLC. All rights reserved.
Visit our game show case:	https://www.renown-games.com 
License information:		https://makingbrowsergames.com/starterkits/quiz/
Affiliate Information:		https://www.sgose.com/products/affiliates-program/

 * The above copyright notice and this permission notice shall be included in 
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN  
 * THE SOFTWARE.
 * 
 *
 * File Name: load.js
 * Live Demo: <> 
 * Source Code: https://makingbrowsergames.com/book/
 * Description: File for controlling assets downloads; 
 *		some delegations to browser.
 * Author: Stephen Gose
 * Version: 0.0.0.xx
 * Phaser Version: 3.15.x+
 * Author URL: https://www.stephen-gose.com/
 * Support: support@pbmcube.com
 *
 * \u00A9 Copyright ©  1974-2017 Stephen Gose LLC. All rights reserved. 
 * 
 * Do not sell! Do not distribute!
 * This is a licensed file with EULA permission.
 * Please refer to the Terms of Use
 *   and End Users License Agreement (EULA).
 *  
 * Search for [ //TODO ] to tailor this file for your own use; 
 *	 doing so will void any support agreement.
 *
 * Redistribution of part or whole of this file and
 * the accompanying files is strictly prohibited.
 *
 * Reference:
 * https://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html
 *
 */
// 
// =========================================================
"use strict";
/**	game load assets **/
var load = new Phaser.Class({

    Extends: Phaser.Scene,

    initialize: function load (){
        Phaser.Scene.call(this, { key: 'load' });
    },

    preload: function (){
		console.log("Entering load -> preload");	//debug
		this.load.image('loadScene', 'assets/images/loadScene.jpg');
		// we have preloaded assets required for Loading group objects
		//	from the Boot state.
    },

	create: function(){
		// loading has finished - proceed to where? demo state? languages?
        this.add.image(0, 0, 'loadScene').setOrigin(0);
        //this.input.once('pointerdown', function () {
            console.log('From load to language');
            this.scene.start('language');

        //}, this);
    }

});

      

See Examples here


Splash.js &/or Languages.js (10kB)

Standard Method: to load splash scene or language scene from external module js file.

9.4.1 Scrum 2:

Initial Language JSON load - This file populates all the language button's label and sets the dynamic file names. Once a gamer selects their native language by clicking on their national flag, a second JSON language lexicon is downloaded. This second JSON file then dynamically populates all text components with the gamer’s native language.

/**  
 * File Name: language.js  
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html  
 * Description: File for controlling initial entry into game shell  
 * and scenes; managing global variables throughout game state.  
 * Author: Stephen Gose  
 * Version: 0.0.0.15  
 * Author URL: https://www.stephen-gose.com/  
 * Support: support@pbmcube.com  
 *  
 * Copyright © \u00A9 1974-2017 Stephen Gose LLC. All rights reserved.  
 *  
 * Do not sell! Do not distribute!  
 * This is a licensed permission file. Please refer to Terms of Use  
 *   and End Users License Agreement (EULA).  
 * Search for [ //**TODO** ] to tailor this file for your own use  
 * and will void any support agreement.  
 *  
 * Redistribution of part or whole of this file and  
 * the accompanying files is strictly prohibited.  
 *  
 * This file is automatically loaded from state/load.js  
 * to change default state - change state/load.js at line: 34  
 */  
"use strict";  
window.GAMEAPP.state.language = {  
	preload: function(){  
	
	//using atlas for graphics; loading graphics for the main menu state now;  
	//	they should be in the cache when needed.  
	//	game theme music file should be deferred to splash/language phase.  
	//navigation and menu buttons;  
	//two methods to load spriteSheets: 1) classic or 2) texture atlas  
	//load navigation buttons using classic method  
	//using programmatic method  
		this._preloadResources();  
	},  
	

	create: function(){
		console.log("starting language selection state");
		this.add.image(400, 250, 'menus');
		this.cameras.main.setViewport(0, 0, 800, 518);
		
		//v3 buttons
		var chinaBtn = this.add.sprite(400-140, 200, 'chinaBtn').setInteractive();
		chinaBtn.name = "china";
		chinaBtn.on('pointerover', function (pointer){
			console.info(chinaBtn.name + " over. ");
			this._toolTip.setText("Chinese | 中文 "); 
			chinaBtn.setFrame(1);
		}, this);
		chinaBtn.on('pointerout', function (pointer){
		console.info(chinaBtn.name + " out. ");
		this._toolTip.setText("");
		chinaBtn.setFrame(0);
		}, this);
		chinaBtn.on('pointerdown',  function (pointer){
		console.info(chinaBtn.name + " clicked down. ");
		chinaBtn.setFrame(2);
		}, this);
		chinaBtn.on('pointerup',  function (pointer){
		console.log(chinaBtn.name + " click released.");
		GAMEAPP.gameLanguage = 1;
		chinaBtn.setFrame(0);
		}, this);	},  
	// . . . . etc  . . . .
	},
	
	update: function(){  
		
	},
	
	btnOver: function(butn){  
		switch(butn.name){  
			case "china":  
				console.log("Chinese selected");
				this._toolTip.setText("Chinese | 中文 ");  
				break;
			
			case "denmark":
				console.log("Danish selected");
				this._toolTip.setText("Danish | Dansk sprog ");  
				break;  
			
			case "english":  
				console.log("English selected");
				this._toolTip.setText("Default Language: English\n  
					Select language then click arrow to enter.");  
				break;  
			
			case "french":  
				console.log("French selected");  
				this._toolTip.setText("French | langue française ");  
				break;  

			case "german":  
				console.log("German selected");  
				this._toolTip.setText("German | deutsche Sprache ");  
				break;  
				
			case "italy":  
				console.log("Italian selected");  
				this._toolTip.setText("Italian | lingua italiana ");  
				break;  
			
			case "japan":  
				console.log("Japanese selected");  
				this._toolTip.setText("Japanese | 日本語 ");  
				break;  
			
			case "netherlands":  
				console.log("Dutch selected");  
				this._toolTip.setText("Dutch | Nederlandse taal ");  
				break;  
			
			case "portugal":  
				console.log("Portuguese selected");  
				this._toolTip.setText("Portuguese | idioma portugues ");  
				break;  
			
			case "spain":  
				console.log("Spanish selected");  
				this._toolTip.setText("Spanish | língua espanhola ");  
				break;  
			
			case "sweden":  
				console.log("Swedish selected");  
				this._toolTip.setText("Swedish | Svenska språket ");  
				break;  
			
			default:  
				console.log("English selected");  
				this._toolTip.setText("Default Language: English\n  
					Select language then click arrow to enter.");  
				break;  
		}
	},
	
	function clickContinue(){
		// https://phaser.io/phaser3/devlog/121
		// https://phaser.io/phaser3/devlog/119

		GAMEAPP.game.scene.stop("language").sendToBack();
		GAMEAPP.game.scene.start("story").bringToTop();
	}
	
};
//Sample JSON lexicon of 36 languages:  
{  "language"[  
	{btn: "us_btn", tooltip:"English / US", file:"en_US"},  
	{btn: "de_btn", tooltip:"German / Deutsch", file:"de"},  
	{btn: "swed_btn", tooltip"Swedish / svenska", file:"swed"},  
	{btn: "fr_btn", tooltip:"French / français", file:"fr"},  
	{btn: "fili_btn", tooltip:"Filipino / Filipino", file:"fili"},  
	{btn: "hun_btn", tooltip"Hungarian / magyar" file:"hun"},  
	{btn: "bulg_btn", tooltip:"Bulgarian / български", file:"bulg"},  
	{btn: "japan_btn", tooltip:"Japanese / 日本人", file:"japan"},  
	{btn: "china_btn", tooltip:"Chinese / 中國", file:"chin-simp"},  
	{btn: "hindi_btn", tooltip:"Hindi / हिन्दी", file:"hindi"},  
	{btn: "grk_btn", tooltip:"Greek / ελληνικά", file:"grk"},  
	{btn: "italy_btn", tooltip: "Italian / italiano", file:"italy"},  
	{btn: "israel_btn", tooltip:"Hebrew / עברית", file:"israel"},  
	{btn: "mala_btn", tooltip:"Malaysian / Malaysia", file:"mala"},  
	{btn: "mex_btn", tooltip:"Mexican / mexicano", file:"mex"},  
	{btn: "mont_btn", tooltip:"Montenegrin / црногорски", file:"mont"},  
	{btn: "serb_btn", tooltip:"Serbian / српски", file:"serb"},  
	{btn: "dutch_btn", tooltip:"Dutch / Nederlands", file:"dutch"},  
	{btn: "be_btn", tooltip:"Belgium / België", file:"be"},  
	{btn: "spain_btn", tooltip:"Spanish / español", file:"spain"},  
	{btn: "sa_btn", tooltip:"Saudi / سعودي", file:"sa"},  
	{btn: "rom_btn", tooltip:"Romanian  / român", file:"rom"},  
	{btn: "port_btn", tooltip:"Portuguese / português", file:"port"},  
	{btn: "ru_btn", tooltip:"Russian / русский", file:"ru"},  
	{btn: "sing_btn", tooltip:"Singapore / சிங்கப்பூர்", file:"sing"},  
	{btn: "hk_btn", tooltip:"HongKong / 香港", file:"hongK"},  
	{btn: "thai_btn", tooltip:"Thailand / ไทย", file:"thai_US"},  
	{btn: "tur_btn", tooltip:"Turkish / Türk", file:"turk"},  
	{btn: "viet_btn", tooltip:"Vietnamese / tiếng Việt", file:"viet"},  
	{btn: "kor_btn", tooltip:"Korean / 한국의", file:"kor"},  
	{btn: "braz_btn", tooltip:"Brazilian / brasileiro", file:"braz"},  
	{btn: "czech_btn", tooltip:"Czech / čeština", file:"czech"},  
	{btn: "pol_btn", tooltip:"Polish / polski", file:"pol"},  
	{btn: "finn_btn", tooltip:= "Finnish / suomalainen", file:"finn"},  
	{btn: "norw_btn", tooltip:"Norwegian / norsk", file:"norw"},  
	{btn: "denm_btn", tooltip:"Danish / dansk", file:"denm"}  
	]  
} 
//ARRA v15 as2 original; you will need to research your own content.

function assignLanguage(lang) {

	trace(“ switch - lang: “ + lang);

	switch (lang)

	{

		case 0 :
			//US English

			sales = “https://www.pbmcube.com/arra/index-enus.php”;
			wikiinfo = “”;
			pbm3info = “”;
			instruct = “”;
			playtxt = “Play”;
			playown = “”;
			playThis = “Play this month’s NEW RPG!”;
			playLast = “Play previous month’s Featured Game!”;
			playBonus = “NEW Featured Bonus Game!”;
			opttxt = “Game Options”;
			sharetxt = “Share with a Friend”;
			helptxt = “How to play”;
			moretxt = “More Adventures”;
			credittxt = “Credits”;
			introPara = “After a two-day journey, you arrive
				at the dreaded ruins of the Wyvern.
				Just ahead you can see the main gate.”;
			break;

		case 1 :

			//german = 1
			sales = “https://www.pbmcube.com/arra/index-ende.php”;
			wikiinfo = “”;
			pbm3info = “”;
			instruct = “Anleitung: \n Verwenden Sie Pfeiltasten zu bewegen.
			\n\n Überqueren Sie die Straße. \n Überqueren den Fluss.\n\n
			Geben Sie eine geheime Höhle für mehr Spaß.\n Achtung
			Gefahr!!”;

			playtxt = “Spiel”;
			playown = “”;
			playThis = “Spielen dieses Monats Neues Spiel!”;
			playLast = “Spielen Vormonat Spiel!”;
			playBonus = “NEU Bonusspiel!”;
			opttxt = “Spieloptionen”;
			sharetxt = “Aktien dieser”;
			helptxt = “Anweisungen”;
			moretxt = “mehr”;
			credittxt = “Abspann”;
			introPara = “Sie gelangen auf das gefürchtete Ruinen
				nach einer zweitägigen Reise. Sie sehen
				das Haupttor kurz vor.”;
			break;

		case 2 :
			//swedish = 2
			sales = “https://www.pbmcube.com/arra/index-ense.php”;
			wikiinfo = “”;
			pbm3info = “”;
			instruct = “”;
			playtxt = “Spela”;
			playown = “”;
			playThis = “Spela denna månads nya spel!”;
			playLast = “Spela föregående månads Dagens spel!”;
			playBonus = “NY Dagens bonusspelet!”;
			opttxt = “Spelalternativ”;
			sharetxt = “VARA DELAKTIG I”;
			helptxt = “instruktioner”;
			moretxt = “mer”;
			credittxt = “eftertexterna”;
			introPara = “Du kommer fram till den fruktade ruinerna
				efter två dagars resa. Du ser huvudingången
				precis framför oss.”;
			break;

// . . . etc. . . . . . 

}      

See Examples here


Game Main Menu

Standard Method: load game main menu options from external module js file.

/**  
 * File Name: mainMenu.js  
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html  
 * Description: File for controlling initial entry into game shell  
 * and scenes; managing global variables throughout game state.  
 * Author: Stephen Gose  
 * Version: 0.0.0.15  
 * Author URL: https://www.stephen-gose.com/  
 * Support: support@pbmcube.com  
 *  
 * Copyright © \u00A9 1974-2017 Stephen Gose LLC. All rights reserved.  
 *   
 * Do not sell! Do not distribute!  
 * This is a licensed permission file. Please refer to Terms of Use  
 *   and End Users License Agreement (EULA).  
 * Search for [ //**TODO** ] to tailor this file for your own use  
 * and will void any support agreement.  
 *  
 * Redistribution of part or whole of this file and  
 * the accompanying files is strictly prohibited.  
 *  
 * This file is automatically loaded from state/load.js  
 * to change default state - change state/load.js at line: 34  
 */  
"use strict";  
window.GAMEAPP.state.story = {  
	preload: function(){  
		console.log(" %c ARRA rv_15 Story & Main Menu Game Prototype", "color:white; background:red");  
		GAMEAPP.InfoText = "Main Menu Selections";  
		//ARRA mainMenu & Story collapse into one scene  
		this.game.load.image('story', 'assets/images/staticRooms/story.jpg');  
		this.load.spritesheet('button',  
			'assets/spriteSheets/mmog-sprites-silver.png', 129, 30);  
		GAMEAPP._assignLanguage(GAMEAPP.gameLanguage);  
		//using altas for graphics; loading graphics for the  
		//	main menu state now;  
		//	they should be in the cache when needed.  
		//	game theme music file should be deferred to splash/language phase.  
		//navigation and menu buttons;  
		//two methods to load spriteSheets: 1) classic or 2) texture atlas  
		//load navigation buttons using classic method  
		//using programmatic method  
		this._preloadResources();  
	},  
	  
	create: function(){  
		console.log("starting story line & Main Menu state");
		this.input.setGlobalTopOnly(true); 
		var style = {};
		//Static english language assignment here; use global variable to attach selected language
		//var playtxt = this.add.text(670, 280, "Play" , GAMEAPP.styleBTN);	// "Play";
		//var opttxt = this.add.text(0, 0, "Options", GAMEAPP.styleBTN); 		//"Game Options";
		//var sharetxt =  this.add.text(0, 0, "Share", GAMEAPP.styleBTN); 	//"Share with a Friend";
		
		//var moretxt = this.add.text(0, 0, "More", GAMEAPP.styleBTN); 		//"More Games";
		//var credittxt = this.add.text(0, 0, "Credits", GAMEAPP.styleBTN);	//"Credits";
		//var webtxt = this.add.text(0, 0, "License", GAMEAPP.styleBTN);	//"WebMasters" && customer license;
		//var donationtxt = this.add.text(0, 0, "Donations", GAMEAPP.styleBTN);
		console.log("Language Selected: #"+GAMEAPP.gameLanguage);
		if (GAMEAPP.gameLanguage == 0) {
			this.add.image(400, 250, 'storyHUDeng');
			//style = { font: "12px Arial", fill: "#F90", align: "center", boundsAlignH: "left", boundsAlignV: "top", wordWrap: true, wordWrapWidth: 245 };
			//this.introParatxt = this.add.text(1000,0, GAMEAPP.introPara, style);
			//this.introParatxt.setShadow(3, 3, 'rgba(0,0,0,0.5)', 5);
			//this.introParatxt.setTextBounds(555, 70, 780, 400);
			//this.introParatxt.fontWeight = 'bold';
		}else{
			this.add.image(400, 250, 'story');
			// the alignment of the text is independent of the bounds, try changing to 'center' or 'right'
			style = { font: "14px Arial", fill: "#FFF", align: "center", boundsAlignH: "left", boundsAlignV: "top", wordWrap: true, wordWrapWidth: 230 };
			this.introParatxt = this.add.text(0,0, GAMEAPP.introPara, style);
			this.introParatxt.setShadow(3, 3, 'rgba(0,0,0,0.5)', 5);
			//this.introParatxt.setTextBounds(550, 138, 780, 400);
			this.introParatxt.fontWeight = 'bold';
		}
		
		//Main Menu creation
		//this.soundButton = this.add.button(10, 10, 'soundButton', this.toggleThemeMusic, this);
		
		// Play 
		this.playButton = this.add.sprite(670, 280, 'button').setInteractive();//, this.startGame, this, 2, 1, 0, 1);  button frames: over, off, down
		this.playButton.setFrame(1);
		this.playButton.setOrigin(0.5,0);
		this.playButton.setScale(0.7,0.7);
		this.playButton.name = "play";
		//this.playButton.onInputOver.add(this.btnOver, this);
		//this.playButton.add.text(playtxt).setOrigin(0.5,0);

		this.playButton.on('pointerover', function (pointer){
			console.info(this.playButton.name + " over. ");
			this._toolTip.setText(GAMEAPP.playtxt);
			this.playButton.setFrame(2);
		}, this);
		this.playButton.on('pointerout', function (pointer){
			console.info(this.playButton.name + " out. ");
			this._toolTip.setText(""); 
			this.playButton.setFrame(1);
		}, this);
		this.playButton.on('pointerdown',  function (pointer){
			console.info(this.playButton.name + " clicked down. ");
			this.playButton.setFrame(0);
		}, this);
		this.playButton.on('pointerup',  function (pointer){
			console.log(this.playButton.name + " click released.");
			console.log("Play selected");
			startGame();
			this.playButton.setFrame(1);
		}, this);
		var playtxt = this.add.text(653, 280, "Play" , { font: "18px Arial", fill: "#000000", align: "center" });	// "Play";
		
				// Credit button (comparison to Phaser v2.x.x syntax)
		this.creditButton = this.add.sprite(610, 320, 'button').setInteractive();//, this.GameCredits, this, 2, 1, 0, 1); // button frames: over, off, down
		this.creditButton.setFrame(1);
		this.creditButton.setOrigin(0.5,0);
		this.creditButton.setScale(0.7,0.7);
		this.creditButton.name = "credit";
		//this.creditButton.onInputOver.add(this.btnOver, this);
		//this.creditButton.addChild(credittxt).setOrigin(0.5,0);
		this.creditButton.on('pointerover', function (pointer){
		console.info(this.creditButton.name + " over. ");
		this._toolTip.setText(GAMEAPP.credittxt); 
		this.creditButton.setFrame(2);
		}, this);
		this.creditButton.on('pointerout', function (pointer){
		console.info(this.creditButton.name + " out. ");
		this._toolTip.setText(""); 
		this.creditButton.setFrame(1);
		}, this);
		this.creditButton.on('pointerdown',  function (pointer){
		console.info(this.creditButton.name + " clicked down. ");
		this.creditButton.setFrame(0);
		}, this);
		this.creditButton.on('pointerup',  function (pointer){
		console.log(this.creditButton.name + " click released.");
		GameCredits();
		this.creditButton.setFrame(1);
		}, this);
		var credittxt = this.add.text(585, 320, "Credits", { font: "18px Arial", fill: "#000000", align: "center" });	
		
		// . . .  etc. . . . . .

	},
	
	update: function(){
		
	}
}
	
function startGame (pointer) {
		//	Ok, the Play Button has been clicked or touched, so let's stop the music (otherwise it'll carry on playing)
		//  this.music.stop();
		//	And start the actual game
		// https://phaser.io/phaser3/devlog/121
		// https://phaser.io/phaser3/devlog/119
		console.log("Game Play launched.");
		GAMEAPP.game.scene.stop("story").sendToBack();
		GAMEAPP.game.scene.start('game').bringToTop();

	}
function GameCredits (pointer) {

		//	And start the actual game
		console.log("Game Credits launched.");
		GAMEAPP.game.scene.stop("story").sendToBack();
		GAMEAPP.game.scene.start('credits').bringToTop();

	}
function GameOptions (pointer) {

		//	Ok, the Play Button has been clicked or touched, so let's stop the music (otherwise it'll carry on playing)
		//this.music.stop();
		//	And start the actual game
		console.log("Game Options launched.");
		GAMEAPP.game.scene.stop("story").sendToBack();
		GAMEAPP.game.scene.start('language').bringToTop();

	}
	
	//uses right-side plugin
function GameShare (pointer) {
		//	Ok, the Play Button has been clicked or touched, so let's stop the music (otherwise it'll carry on playing)
		//this.music.stop();
		//originally moved to separate internal scene; now off-site
		window.open("https://www.pbmcube.net/", "_blank");

	}
	
function MoreGame(pointer) {

		//	Ok, the Play Button has been clicked or touched, so let's stop the music (otherwise it'll carry on playing)
		//this.music.stop();
		//	And start the actual game
		//originally moved to separate internal scene; now off-site
		window.open("https://www.renown-games.com./index.html", "_blank");

	}
function WebMaster(pointer) {

		//	Ok, the Play Button has been clicked or touched, so let's stop the music (otherwise it'll carry on playing)
		//this.music.stop();
		//	And start the actual game
		//originally moved to separate internal scene; now off-site
		window.open("https://renown-games.com/shop/index.php?id=prod-ssc5", "_blank");

	}
	
function GameDonations (pointer) {

		//	Ok, the Play Button has been clicked or touched, so let's stop the music (otherwise it'll carry on playing)
		//this.music.stop();
		//	And start the actual game
		//originally moved to separate internal scene; now off-site
		window.open("https://www.paypal.me/pbmcube", "_blank");

	}

};

};   

See Examples here


CMS Main Menu

Standard Method: to load Game Main Menu from content management system.

See Examples here


Game Over

Standard Method: transition game to final administration from external module js file.

<?php
	
	/**
	 * File Name: HighScores.php (back-end server)  
	 * File URL: https://www.renown-games.com/MozartMusicMatch/
	 * Description: File for controlling and displaying game  
	 * scenes; managing global variables throughout game state.  
	 * Author: Stephen Gose  
	 * Version: 0.0.0.15  
	 * Author URL: https://www.stephen-gose.com/  
	 * Support: support@pbmcube.com  
	 *
	 * Copyright © 2008-2016 Stephen Gose LLC. All rights reserved.  
	 * 
	 * Do not sell! Do not distribute!  
	 * This is a licensed permission file. Please refer to  
	 * Terms of Use and End Users License Agreement (EULA).  
	 * Search for [ //**TODO** ] to tailor this file for your own use and will void any support agreement.  
	 *
	 * Redistribution of part or whole of this file and  
	 * the accompanying files is strictly prohibited.  
	 *
	 */
	
	class HighScores
	{
		
	public function __construct() {
		$username = "<USER NAME HERE>";
		$password = "<PASSWORD HERE>";
		$db = "<DATABSASE NAME HERE>";
		mysql_connect("localhost",$username,$password);
		mysql_select_db($db);
	}
	
	
	public function saveScore($gameID, $score, $initials, $dateStamp, $hash)
	{
		$sql = "SELECT `secretkey` FROM `GameIDs` WHERE `id` = \"".$gameID."\"";
		$res = mysql_query($sql);
		if (mysql_numrows($res) == false) //GAME ID DOES NOT EXIST
		{
			return "ERROR - GAME ID DOES NOT EXIST";
		}
		//GAME ID EXISTS - VERIFY HASH
		$secretKey = mysql_fetch_object($res)->secretkey;
		$compareHash = $secretKey.$score.$initials.$dateStamp;
		$compareHash = md5(md5($compareHash));
		if ($compareHash != $hash)
		{
			return "ERROR - HASH DOES NOT MATCH";
		}
		//CHECK TO SEE IF IDENTICAL SCORE RECORD EXISTS
		$sql = "SELECT * FROM `Scores_".$gameID."` WHERE `score`=".$score." AND `datestamp`=".$dateStamp." AND `initials`=\"".\
$initials."\"";
		$res = mysql_query($sql);
		if (mysql_numrows($res) > 0) //RECORD ALREADY EXISTS
		{
			return "ERROR - SCORE ALREADY EXISTS";
		}
		//VALID REQUEST - SAVE SCORE TO SELECTED GAME TABLE
		$sql = "INSERT INTO `Scores_".$gameID."` (`score`,`initials`,`datestamp`) VALUES (".$score.", \"".$initials."\", \"".$\
dateStamp."\")";
		$res = mysql_query($sql);
		return $res;
	}
	
	public function getScores($gameID, $number)
	{
		$sql = "SELECT * FROM `GameIDs` WHERE `id` = \"".$gameID."\"";
		$res = mysql_query($sql);
		if (mysql_numrows($res) == false) //GAME ID DOES NOT EXIST
		{
			return false;
		}
		//RETRIEVE REQUESTED NUMBER OF SCORES, OR HOWEVER MANY ARE THERE
		$sql = "SELECT * FROM `Scores_".$gameID."` ORDER BY `score` DESC LIMIT ".$number;
		$res = mysql_query($sql);
		$scores = array();
		for ($i = 0; $i < mysql_num_rows($res); $i++)
		{
			array_push($scores, mysql_fetch_assoc($res));
		}
		return $scores;
	}
	
	}

	?>

Copyright © 2017, Stephen Gose LLC.
All rights reserved.