Ruins of Able-Wyvern™
(Phaser v2.x.x)

Historical releases and events:


Boot.js (2kB)

The "boot.js" loads the "Artwork Theme" (AT) Component. It holds the "... all the artwork used by the Game Framework Component for the visual elements ... " of the game. We could replace (i.e., overwrite!) the current artwork theme but retain the same file names in the "boot.js" and have a "new game with different artwork theme" using the same Game Mechanics (GM) and Game Framework Mechanisms (GFM).

/**
 * File Name: boot.js
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html
 * Description: File for controlling initial game shell launch; managing global variables throughout game state.
 * Author: Stephen Gose
 * Version: 0.0.0.8
 * 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.
 *
 */
"use strict";
window.GAMEAPP.state.boot = {
	
	preload: function(){
		console.log(" %c Game Prototype boot configure browser settings ", "color:white; background:red");
		//CORS: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
		//https://enable-cors.org/
		this.load.crossOrigin = 'anonymous';
		
		this.game.load.image('R6', 'assets/images/staticRooms/R6.jpg');
		this.game.load.image('background', 'assets/images/staticRooms/intro.jpg');
		this.game.load.image('story', 'assets/images/staticRooms/story.jpg');
		this.game.load.atlas('button-continue','assets/spriteSheets/RightArrow-Phaser.png','assets/spriteSheets/arrowR-sprites.json');
		// set world size
		this.game.world.setBounds(0, 0, window.GAMEAPP.worldWidth, window.GAMEAPP.worldHeight);
		
		this.enableScaling();
		
		//init mt helper
		mt.init(this.game);
		
		//set background color - true (set also to document.body)
		mt.setBackgroundColor(true);
		
		// load assets for the Loading group ( if exists )
		mt.loadGroup("Loading");
	},
	create: function(){
		this.background = this.add.image(0, 0, 'background');
		
		// add all game states
		for(var stateName in window.GAMEAPP.state){
			this.game.state.add(stateName, window.GAMEAPP.state[stateName]);
		}
		
		// goto load state
		this.game.state.start("load");
	},
	enableScaling: function(){
		var game = this.game;
		game.scale.parentIsWindow = (game.canvas.parentNode == document.body);
		game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
	}
};

See Examples here


Credits.js (4kB)

/**
 * File Name: Credit.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
 */
 
window.GAMEAPP.state.credits = {
	preload: function (){
		console.log(" %c ARRA rv_15 Credits Menu Game Prototype", "color:white; background:red");
		GAMEAPP.InfoText = "Game Credits and Information";
		//ARRA mainMenu & Story collapse into one scene
		this.game.add.image(0, 0, 'menus');
		this.load.spritesheet('button', 'assets/spriteSheets/mmog-sprites-silver.png', 129, 30);
		//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
		
	},

	create: function () {
		//return to main menu txt
		var mmtxt = this.add.text(0, 0, "Return", GAMEAPP.styleBTN);
		var tooltxt = this.game.add.text(this.world.centerX, this.world.centerY+30, "ARRA is a RPG fantasy game by Stephen Gose Game Studios.\nSteve Gose -- is a professional eLearning specialist and\n managed a multi-national eLearning program for the US & Japan\n regions of a global telecommunication corporation.\n\n		Currently is a Professor at UAT.edu and He owns and operates\n PBMCube - Play By Mail, eMail & Modem games,\n and TB-Cube - Training by Blackboard, Books & Browsers an online / eLearning provider).\n\nLearn more at https://www.stephen-gose.com or\n visit his linkedIn page\n https://www.linkedin.com/in/stephen-gose/", GAMEAPP.styleHUD);
		
		text = this.game.add.text(this.world.centerX, 145, "Credits & Help", {
        font: "20px Arial",
        fill: "#CCC",
        align: "center"
		});

		text.anchor.setTo(0.5, 0.5);
		text.setShadow(3, 3, 'rgba(0,0,0,0.5)', 5);
		text.fontWeight = 'bold';
		
		tooltxt.anchor.setTo(0.5, 0.5);
		tooltxt.setShadow(3, 3, 'rgba(0,0,0,0.5)', 5);
		tooltxt.fontWeight = 'bold';
			
		//Goto main menu
		var buttonContinue = this.game.add.button(this.world.width, this.world.centerY+50, 'button-continue', this.quitGame, this, 1, 0, 2,0);
		
		buttonContinue.anchor.set(1,1);
		buttonContinue.x = this.world.width+buttonContinue.width+20;
		
		this.add.tween(buttonContinue).to({x: this.world.width-20}, 500, Phaser.Easing.Exponential.Out, true);
		
	},


	update: function () {

		

	},

	quitGame: function (pointer) {

		//	Then let's go back to the main menu.
		this.state.start('story');

	}

};
      

See Examples here


Combat.js (25kB)

/**
 * File Name: combat.js
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html
 * Description: File for controlling and displaying combat scenes; managing global variables throughout game state.
 * Author: Stephen Gose
 * Version: 0.0.0.8
 * 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.
 *
 */
//design notes: switch seems to be faster than the if statement combat.
//This is original "switched" version rv_8
"use strict";
window.GAMEAPP.state.Combat = {
	init: function(){
		// Data structures
		//====================================================
		GAMEAPP.CmbtTurn = 0;
		console.log('Intialize Combat Turns: '+GAMEAPP.CmbtTurn)
		
	},
	preload: function(){
		console.log("loading combat state");
		this.game.load.image('combat', 'assets/images/staticRooms/combat.jpg');
		this.game.load.atlas('avatar','assets/icons/arraIcons.png','assets/icons/arraIcons.json');
		this.load.atlas('fireButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.atlas('attackButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.atlas('searchButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.atlas('exchangeButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.atlas('exitButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.atlas('cookButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.spritesheet('Death','assets/spriteSheets/ARRADeath/ARRADeath.png',160,100);
		this.load.spritesheet('button', 'assets/spriteSheets/mmog-sprites-silver.png', 129, 30);
		//GAMEAPP.LastRoom = GAMEAPP.CrntRoom;
		
	},
		
	create: function(){
		console.log("starting combat  state");
		var MonsterNdx = MT[GAMEAPP.CrntRoom].Mnstr;
		var mGold = Number(M[MT[GAMEAPP.CrntRoom].Mnstr].HGold);
		var mGem = Number(M[MT[GAMEAPP.CrntRoom].Mnstr].HGem);
		var mFood = Number(M[MT[GAMEAPP.CrntRoom].Mnstr].Food);
	console.log("Monster #: "+ MonsterNdx);
	console.log("Silver found: "+mGold);
	console.log("Gems found: "+mGem);
	console.log("Food found: "+mFood);
		this.game.add.image(0, 0, 'combat');
		var rect = new Phaser.Rectangle(90, 110, 196, 155);
		this.game.physics.arcade.setBounds(90, 110, 196, 155);
		//Set a neutral background color
		this.game.stage.backgroundColor = "#000";
		//Set game to ARCADE physics systemLanguage
		this.game.physics.startSystem(Phaser.Physics.ARCADE);
		this.game.renderer.renderSession.roundPixels = true;
		this.game.world.enableBody = true;
		
		//Create Room
		this.Room = this.game.add.group();  
		this.Room.enableBody = true; 
		this.game.physics.enable(this.Room, Phaser.Physics.ARCADE);
		
		this.NorthWall = this.game.add.sprite(90,110,box({length:190,width:16,color:'#999'}));	
		this.NorthWall.enableBody = true;
		this.NorthWall.body.immovable = true;
		this.NorthWall.visible = false;
		this.Room.add(this.NorthWall);
		this.NorthWall.alignTo(rect, Phaser.TOP_CENTER);
		
		this.SouthWall = this.game.add.sprite(0,200,box({length:190,width:16,color:'#999'}));
		this.SouthWall.body.immovable = true;
		this.SouthWall.visible = false;
		this.Room.add(this.SouthWall);
		this.SouthWall.alignTo(rect, Phaser.BOTTOM_CENTER);
		
		this.WestWall = this.game.add.sprite(200,16,box({length:16,width:190,color:'#999'}));
		this.WestWall.body.immovable = true;
		this.WestWall.visible = false;
		this.Room.add(this.WestWall);
		this.WestWall.alignTo(rect, Phaser.RIGHT_CENTER);
		
		this.EastWall = this.game.add.sprite(90,16,box({length:16,width:190,color:'#999'}));
		this.EastWall.body.immovable = true;
		this.EastWall.visible = false;
		this.Room.add(this.EastWall);
		this.EastWall.alignTo(rect, Phaser.LEFT_CENTER);
		
		//toolTip (tt) and RoomAlert (ra) text
		this._toolTip = this.game.add.text(this.game.world.width-100, this.game.world.height-90, GAMEAPP.InfoText, GAMEAPP.styleTT);
		this._toolTip.anchor.set(0.5);
		GAMEAPP.RoomAlert = "";
		
		//toolTip (tt) and RoomAlert (ra) text
		GAMEAPP.RoomAlert = "Beware, a " + M[MT[GAMEAPP.LastRoom].Mnstr].Race + " is here!"
		this._raTxt = this.game.add.text(this.game.world.width-268, 65, GAMEAPP.RoomAlert, GAMEAPP.styleRA);
		this._raTxt.anchor.set(0,0);
		var attacktxt = this.game.add.text(0, 0, "Attack" , GAMEAPP.styleBTN);	// "Attack" button text;
		var firetxt = this.game.add.text(0, 0, "Fire" , GAMEAPP.styleBTN);		// "Fire" button text;
		var exchangetxt = this.game.add.text(0, 0, "Exchange" , GAMEAPP.styleBTN);
		var exittxt = this.game.add.text(0, 0, "Return" , GAMEAPP.styleBTN);
		var searchtxt = this.game.add.text(0, 0, "Search" , GAMEAPP.styleBTN);
		var dodgetxt = this.game.add.text(0, 0, "Dodge" , GAMEAPP.styleBTN);	
		var defendtxt = this.game.add.text(0, 0, "Defend" , GAMEAPP.styleBTN);	
		
		//Combat narrative HUD
		var CmbtTurn = 1;
		this.CTurnNum = this.game.add.text(15, 93, "Combat Turn: #"+String(CmbtTurn) , GAMEAPP.styleTT);
		//combat narrative for player
		this.Narr1txt = this.game.add.text(35, 265, "xx" , GAMEAPP.styleNarrH);	
		//combat narrative for monster		
		this.Narr2txt = this.game.add.text(this.game.world.width-350, 265, "xx" , GAMEAPP.styleNarrM);
		
		//Character HUD Display
		this.cStmnatxt = this.game.add.text(this.game.world.width-125, 120, String(Person[1].ModStmn) , GAMEAPP.styleCmbtH);
		var cWS = ((CCP.WSRaw * 5) + (CCP.Stmn * 2)) + "%";
		this.csWStxt = this.game.add.text(this.game.world.width-125, 136, String(cWS) , GAMEAPP.styleCmbtH);
		var cPS = ((CCP.BSRaw * 5) + (CCP.Coor * 2)) + "%";
		this.csPStxt = this.game.add.text(this.game.world.width-125, 152, String(cPS) , GAMEAPP.styleCmbtH);
		this.csWpntxt = this.game.add.text(this.game.world.width-125, 168, String(CCP.WName) , GAMEAPP.styleCmbtH);
		this.csArmtxt = this.game.add.text(this.game.world.width-125, 185, String(CCP.AName) , GAMEAPP.styleCmbtH);
		
		this.cExptxt  = this.game.add.text(this.game.world.width-45, 103, String(Person[1].TempScore) , GAMEAPP.styleCmbtH);
		this.cRenowntxt = this.game.add.text(this.game.world.width-45, 120, String(Person[1].Renown) , GAMEAPP.styleCmbtH);
		this.cGoldtxt = this.game.add.text(this.game.world.width-45, 136, String(CCP.HGold) , GAMEAPP.styleCmbtH);
		this.cFoodtxt = this.game.add.text(this.game.world.width-45, 152, String(CCP.Food) , GAMEAPP.styleCmbtH);
		
		//Monster HUD Display
		this.mStmnatxt = this.game.add.text(this.game.world.width-125, 231, String(Person[6].ModStmn) , GAMEAPP.styleCmbtM);
		this.msWStxt = this.game.add.text(this.game.world.width-125, 248, String(Person[6].WS)+"%" , GAMEAPP.styleCmbtM);
		this.msPStxt = this.game.add.text(this.game.world.width-125, 265, String(Person[6].PS)+"%" , GAMEAPP.styleCmbtM);
		this.msWpntxt = this.game.add.text(this.game.world.width-125, 281, String(M[MT[GAMEAPP.CrntRoom].Mnstr].Weapn) , GAMEAPP.styleCmbtM);
		this.msArmtxt = this.game.add.text(this.game.world.width-125, 298, String(M[MT[GAMEAPP.CrntRoom].Mnstr].Armor) , GAMEAPP.styleCmbtM);
		
		this.mRenowntxt = this.game.add.text(this.game.world.width-44, 231, String(Person[6].Renown) , GAMEAPP.styleCmbtM);
		this.mGoldtxt = this.game.add.text(this.game.world.width-44, 248, String(M[MT[GAMEAPP.CrntRoom].Mnstr].HGold) , GAMEAPP.styleCmbtM);
		this.mFoodtxt = this.game.add.text(this.game.world.width-44, 264, String(M[MT[GAMEAPP.CrntRoom].Mnstr].Food) , GAMEAPP.styleCmbtM);
		
		//ARRA Character Death animation
		this.ARRADeath = this.game.add.sprite(1600, 212, 'Death');

		//  Here we add a new animation called 'show Death'
		//  Because we didn't give any other parameters it's going to make an animation from all available frames in the ARRA Death sprite sheet
		var showDeath = this.ARRADeath.animations.add('showDeath');

		//  And this starts the animation playing by using its key ("showDeath")
		//  30 is the frame rate (30fps)
		//  true means it will loop when it finishes
		this.ARRADeath.animations.play('showDeath', 8, true);
		
		// Attack button deployed off screen
		this.attackButton = this.game.add.button(this.world.centerX-800, 338, 'button', this._combatRound, this, 2, 1, 0,1);
		this.attackButton.anchor.set(0.5,0.5);
		this.attackButton.scale.setTo(0.5,0.5);
		this.attackButton.addChild(attacktxt).anchor.set(0.5,0.5);
		
		// Fire button deployed visible only if armed with Missile weapon.
		this.fireButton = this.add.button(152, 338, 'button', this._combatRound, this, 2, 1, 0,1); 
		this.fireButton.anchor.set(0.5,0.5);
		this.fireButton.scale.setTo(0.5,0.5);
		this.fireButton.addChild(firetxt).anchor.set(0.5,0.5);
		
		// Exchange weapons button 
		this.exchangeButton = this.game.add.button(this.world.centerX-800, 361, 'button', this._Exchange, this, 2, 1, 0,1);
		this.exchangeButton.anchor.set(0.5,0.5);
		this.exchangeButton.scale.setTo(0.5,0.5);
		this.exchangeButton.addChild(exchangetxt).anchor.set(0.5,0.5);
		
		// Exit button 
		this.exitButton = this.game.add.button(65, 338, 'button', this._GameReturn, this, 2, 1, 0,1);
		this.exitButton.anchor.set(0.5,0.5);
		this.exitButton.scale.setTo(0.5,0.5);
		this.exitButton.addChild(exittxt).anchor.set(0.5,0.5);
		
		// Search button 
		this.searchButton = this.game.add.button(this.world.centerX-800, 338, 'button', this._Search, this, 2, 1, 0,1);
		this.searchButton.anchor.set(0.5,0.5);
		this.searchButton.scale.setTo(0.5,0.5);
		this.searchButton.addChild(searchtxt).anchor.set(0.5,0.5);
		
		// Dodge button - available during missile combat only
		this.dodgeButton = this.game.add.button(this.world.centerX-800, 338, 'button', this._Cook, this, 2, 1, 0,1);
		this.dodgeButton.anchor.set(0.5,0.5);
		this.dodgeButton.scale.setTo(0.5,0.5);
		this.dodgeButton.addChild(dodgetxt).anchor.set(0.5,0.5);
		
		// Defend button  - available during melee & hand-to-hand combat only
		this.defendButton = this.game.add.button(this.world.centerX-800, 338, 'button', this._Cook, this, 2, 1, 0,1);
		this.defendButton.anchor.set(0.5,0.5);
		this.defendButton.scale.setTo(0.5,0.5);
		this.defendButton.addChild(defendtxt).anchor.set(0.5,0.5);
		
		//enemy character
		this.enemy = this.game.add.sprite(MT[GAMEAPP.LastRoom].mxPos,MT[GAMEAPP.LastRoom].myPos,'avatar');
		this.enemy.frameName = String(M[MT[GAMEAPP.LastRoom].Mnstr].icon+'.bmp');
		this.enemy.body.collideWorldBounds = true;
		this.game.physics.enable(this.enemy, Phaser.Physics.ARCADE);
		
		this.enemy.alignIn(rect, Phaser.BOTTOM_RIGHT);
		
		GAMEAPP._PUpdate();
			
		//place character
		this.player = this.game.add.sprite(90,230,'avatar');
		this.player.frameName = 'avatar.bmp';
		this.player.body.collideWorldBounds = true;	
		this.cursor = this.game.input.keyboard.createCursorKeys();
		
		this.player.alignIn(rect, Phaser.TOP_LEFT);
		
	},
	
	update: function(){
		this.game.physics.arcade.collide(this.player, this.Room);
		this.game.physics.arcade.collide(this.enemy, this.Room);
		
		//Not engaged in melee; if player is dead; show it, and stop the combat
		if(Person[1].ModStmn <= 0){
			this.player.tint = 0xFF0000;
			GAMEAPP.RoomAlert = "Defeated ?!";
			CCP.ModStmn = Person[1].ModStmn;
			this._raTxt.setText(String(GAMEAPP.RoomAlert));
			this.attackButton.x = this.world.centerX+800;
			this.fireButton.x = this.world.centerX+800;
			
			//Show ARRA Death animation at this.game.world.width-178, 100
			this.ARRADeath.x = this.game.world.width-178;
			this.ARRADeath.y = 100;
			this.ARRADeath.animations.play('showDeath', 8, true);
			
		}else{
			this.attackButton.x = this.world.centerX-800;
			this.defendButton.x = this.world.centerX-800;
			this.fireButton.x = 240;
			this.dodgeButton.x = 152;
			GAMEAPP._MoveChar(this.cursor,this.player);
		}
		//if monster dead; show it and stop the combat
		if(Person[6].ModStmn <= 0){
			this.enemy.tint = 0xFF0000;
			//GAMEAPP.RoomAlert = "Victory over the " + M[MT[GAMEAPP.LastRoom].Mnstr].Race + "!";
			this._raTxt.setText("Victory !");
			MT[GAMEAPP.CrntRoom].Mnstr = 0;
			this.attackButton.x = this.world.centerX+800;
			this.fireButton.x = this.world.centerX+800;
			
			this.ARRADeath.x = this.game.world.width-178;
			this.ARRADeath.y = 212;
			this.ARRADeath.animations.play('showDeath', 8, true);
			
			//'Killing Blow delivered
			GAMEAPP.InfoText = "Monster was slain\n... looking in its backpack.\nYou savage all food, gold & gems ... ";
			CCP.ModStmn = Number(Person[1].ModStmn);
			CCP.Score +=  Number(Person[1].TempScore) + Number(Person[6].Coor);
			Person[1].TempScore = 0;
			Person[6].Coor = 0;
			CCP.HGold += Person[6].Gold;
			Person[6].Gold = 0;
			CCP.HGem += Person[6].Gem;
			Person[6].Gem = 0;
			CCP.Food += Person[6].Food;
			Person[6].Food = 0;
			CCP.Renown = Math.ceil((Number(Person[1].Renown)) + Number(Number(Person[6].Renown)/2));
			
		}else{
			GAMEAPP._MoveMonster(this.cursor,this.enemy);
		}
		this.Narr1txt.setText(String(GAMEAPP.Narr1));
		this.Narr2txt.setText(String(GAMEAPP.Narr2));
		this.cStmnatxt.setText(String(Person[1].ModStmn));
		this.cExptxt.setText(String(Person[1].TempScore));
		this.mStmnatxt.setText(String(Person[6].ModStmn));
		this._toolTip.setText(String(GAMEAPP.InfoText));
		this.game.physics.arcade.overlap(this.player,this.enemy,meleeCombat,null,this);
		
	},
	//
	// =========================================================
	// Subroutines & Functions - ARRA Combat Module.
	// =========================================================
	// Combat Finite State machine - see AI chapter in the book.
	// Hardcoded percentages according to ARRA game rules. 
	// Refer to FREE Rule book in file downloadeds.
	_CombatSkill: function(EventRoll, TestValue){
		var results = 20;
		var Critical  = 0;
		Critical = Math.ceil(TestValue/10)

		if (EventRoll <= Critical){				//Player did a critical
			results = 10;
			return results;						//Return a 10
		}else if (EventRoll <= TestValue){		//This is a normal hit
			results = 1;
			return results;
		}else if (EventRoll > 94){			
			//Then Player's Fumbled, This is a new
			//circumstance to include - RQ fubbling. BUT For now,
			results = 0;
			return results;
		}else if(EventRoll > TestValue){		//Player's Missed
			results = 0;
			return results;
		}

	},
//
//====================================================
	_CombatNarrative: function(Who,T){
		
	var ModTtlAP = Person[T].TotalAP;
	var AtkWord = "";
	var PryWord = "";
	var Narrative = "";
	var Trash = 1;
	var Ndx = 0;

	console.log("Who: "+Who+"; Target: "+T)

	//Random Adjectives
	var AtkWord = "";
	var PryWord = "";
	var Ndx = 0;
	var Atk = 0;
	var Pry = 0;
	var Hit = 0;
	var DamRoll = 0;
	var ModTtlAP = 2;
	var TxtTkn = "";
	var TxtTkn2 = "";
	var AtkRoll = 101;
	var PryRoll = 101;
	var DamRoll = 0;

	var ThisAdjWord = ["","",""];

	var AdjWord = ["poor ","desperate ","smooth ","skilled ","clever ","quick ","strong ","wicked ","savage ","firm ","ragged ","heavy ","poor ","desperate ",];

	//Random Critical Adjectives
	var CAdj = ["BRUTAL ","BRUTAL ","MORTAL ","GAPING ","SEVERE ","CRITICAL ","GRAVE ","CRITICAL "];

	//Random Attack Verbs
	var RAtkVrb = ["slash ","slash ","chop ","slice ","thrust ","cut ","hack ","chop "];

	//Random Parry Words
	var RPryVrb = ["block ","block ","parry ","block ","redirect ","parry ","counter ","redirect "];

	//Initialize Variables

	Trash = Math.floor((Math.random() * 6 + 1));
	AtkWord = RAtkVrb[Trash];


	Trash = Math.floor((Math.random() * 6 + 1));
	PryWord = RPryVrb[Trash];

	for (var i=1 ; i < 2 ; i++){

	  Ndx = Math.floor((Math.random() * 12 + 1));
	  ThisAdjWord[i] = AdjWord[Ndx];
	}

	//Start on this person
	//Get Atk & Parry rolls
	AtkRoll = Math.floor((Math.random() * 99 + 1));

	//CombatSkill Function return 0,1 or 10 given person AtkRoll and Weapon proficiency.
	Atk = this._CombatSkill(AtkRoll,Person[Who].WS)
	console.log("WHo: "+Who);
	console.log("AtkRoll: "+AtkRoll);
		if(Atk > 0){
			//then discover amount of damage
			//Function WeaponDamage returns final resulting damage given person's #.
			//fixed at 2D6
			//DamRoll = this._GetWpnDamage(2);
			for(var i=1; i<=2 ;i++){
				DamRoll += Math.floor((Math.random() * 6 + 1));
				if (DamRoll<1) {
					DamRoll = 1;
				}
			}
			
			console.log("Damage Done: "+DamRoll);
			if(Atk == 10){
			  Ndx = Math.floor((Math.random() * 6 + 1));
			  ThisAdjWord[1] = CAdj[Ndx];
			}
		}else{
			console.log("Damage Done: NONE");
		}
	//This is the Opponent's Roll
	PryRoll = Math.floor((Math.random() * 99 + 1));

	//Perform parry for target person 
	Pry = this._CombatSkill(PryRoll,Person[T].PS)
	console.log("Defender's PS: "+Person[T].PS);
	console.log("PryRoll: "+PryRoll);
	if(Pry == 10){
	  Ndx = Math.floor((Math.random() * 6 + 1));
	  ThisAdjWord[2] = CAdj[Ndx];
	  ModTtlAP = (Person[T].TotalAP * 4);
	}

	//Now Combat Calculations for this Person
	Trash = 0;
	Hit = Atk - Pry;
	console.log("Atk: "+ Atk);
	console.log("Pry: "+ Pry);
	console.log("Hit: "+ Hit);
	console.log("================");

	//Genereate Combat narrative
	if (Who == 1){
	  TxtTkn  = "    You: ";		//Player
	  TxtTkn2 = "Monster: "; 		//Monster
	}else{
	  TxtTkn  = "Monster: "; 		//Monster's Text Color
	  TxtTkn2 = "    You: ";		//Player's Text Color
	}


	//NEW Switch statement for Combat
	switch(Hit){
		case 0:
		//attack & parry cancell each other
		Narrative = TxtTkn + ' a ' + ThisAdjWord[1] + AtkWord + '\n';
		Narrative += TxtTkn2 + ' a ' + ThisAdjWord[2] + PryWord + '\n';
		Narrative += TxtTkn2 + ' not injurded!';
		break;

		case 1:
		Trash = DamRoll - ModTtlAP;
		if (Trash < 0) {
		  Trash = 0;
		}
		Narrative = TxtTkn + ' a ' + ThisAdjWord[1] + AtkWord + '\n';
		Narrative += TxtTkn2 + ' a failed ' + PryWord + '\n';
		Narrative += TxtTkn2 + ' wounded! [' + Trash + ' pts]';
		Person[T].ModStmn -= Number(Trash)
		console.log("Target: "+T+" stmn = "+Person[T].ModStmn);
		//this.mStmnatxt.setText(String(Person[6].ModStmn));
		//this.cStmnatxt.setText(String(Person[1].ModStmn));

		if (Who == 1){
			Person[1].TempScore += Number(Trash)
		   // this.cStmnatxt.setText(String(Person[1].TempScore));
		}
		break;

		case -1:
		Narrative = TxtTkn + ' a failed ' + AtkWord + '\n';
		Narrative += TxtTkn2+" a "+AdjWord[2]+PryWord+" awaits.";
		break;

		case 9:
		Trash = ((DamRoll * 2) - ModTtlAP);
		if (Trash < 0){
			Trash = 0;
		}

		Narrative =  TxtTkn+" a "+ThisAdjWord[1]+AtkWord+"\n";
		Narrative += TxtTkn2+" a "+PryWord+" was too late!\n";
		Narrative += TxtTkn2+" wounded! ["+String(Trash)+" pts]";

		Person[T].ModStmn -= Number(Trash);
		console.log("Target "+T+" stmn = "+Person[T].ModStmn);
		   // this.mStmnatxt.setText(String(Person[6].ModStmn));
		//this.cStmnatxt.setText(String(Person[1].ModStmn));

		if (Who == 1){
			Person[1].TempScore += Number(Trash);
			//this.cStmnatxt.setText(String(Person[1].TempScore));
		}
		break;

		case -9:
		Trash = (DamRoll - (ModTtlAP * 2));
		if (Trash < 0){
			Trash = 0;
		}

		Narrative =  TxtTkn+" a "+ThisAdjWord[1]+AtkWord+"\n";
		Narrative += TxtTkn2+" but a "+ThisAdjWord[2]+PryWord+" over-powered!\n";
		Narrative += TxtTkn2+" wounded? ["+String(Trash)+" pts]";

		Person[T].ModStmn -= Number(Trash);
		console.log("Target "+T+" stmn = "+Person[T].ModStmn);
		   // this.mStmnatxt.setText(String(Person[6].ModStmn));
		//this.cStmnatxt.setText(String(Person[1].ModStmn));

		if (Who == 1){
			Person[1].TempScore += Number(Trash)
			//this.cStmnatxt.setText(String(Person[1].TempScore));
		}

		break;

		case 10:
		Trash = ((DamRoll * 2) - ModTtlAP);
		if (Trash < 0){
			Trash = 0;
		}

		Narrative =  TxtTkn+" a "+ThisAdjWord[1]+" "+AtkWord+"\n";
		Narrative += TxtTkn2+" block entirely missed!\n";
		Narrative += TxtTkn2+" wounded ["+String(Trash)+" pts]";

		Person[T].ModStmn -= Number(Trash);
		console.log("Target "+T+" stmn = "+Person[T].ModStmn);
		//this.mStmnatxt.setText(String(Person[6].ModStmn));
		//this.cStmnatxt.setText(String(Person[1].ModStmn));

		if (Who == 1){
			Person[1].TempScore += Number(Trash)
			//this.cStmnatxt.setText(String(Person[1].TempScore));
		}
		break;

		case -10:
		Narrative = TxtTkn + ' a missed ' + AtkWord + '\n';
		Narrative += TxtTkn2+" a "+AdjWord[2]+PryWord+" awaits.";
		break;

	}
			
		//	return Narrative;
	
		if(Who == 1){
			GAMEAPP.Narr1 = String(Narrative);
			
		}
		if(Who == 6){
			GAMEAPP.Narr2 = String(Narrative);
			
		}
		
	},
//
//====================================================
	_combatRound: function(game){
				 
		GAMEAPP.CmbtTurn += 1;
		console.log('combatRound '+GAMEAPP.CmbtTurn);
		this.CTurnNum.setText( "Combat Turn: #"+String(GAMEAPP.CmbtTurn));
		//Determine combat round initiative
		var CmbtInit = Math.floor((Math.random() * 6 + 1));
		
		//Reset each combat variables
		var CombatTurnToggle = 0;
		
		//Who goes first?
		if (CmbtInit <= 3){
			GAMEAPP.InfoText = "You've gained the initiative.";
			this._toolTip.setText(GAMEAPP.InfoText);
			this._CombatNarrative(1,6);
			this.Narr1txt.setText(String(GAMEAPP.Narr1));
			this._CombatNarrative(6,1);	
			this.Narr2txt.setText(String(GAMEAPP.Narr2));			
			
		} else {
			GAMEAPP.InfoText = "Monster has the combat \n initiative this turn.";
			this._toolTip.setText(GAMEAPP.InfoText);
			this._CombatNarrative(6,1);	
			this.Narr2txt.setText(String(GAMEAPP.Narr2));			
			this._CombatNarrative(1,6);
			this.Narr1txt.setText(String(GAMEAPP.Narr1));
			
		}
		
	},
	
	//
	// =========================================================
	_Defend: function(){
		if (Person[6].ModStmn > 0) {
			GAMEAPP.InfoText = " You focus on defense!\n ... no attack possible ... ";
		} 
		if (Person[1].ModStmn < 1) {	
			this._GameReturn;
		} 
	},
	
	//
	// =========================================================
	_Exchange: function(){
		if (Person[6].ModStmn > 0) {	
			GAMEAPP.InfoText = "Changing Weapons ...\n You miss your attack and defense?";
		} 
		if (Person[1].ModStmn < 1) {	
			this._GameReturn;
		} 
	},
	//
	// =========================================================
	// Return from Combat session
	_GameReturn: function(){
		//debug
		if(Person[6].ModStmn <= 0){
			console.log("Room #: "+GAMEAPP.CrntRoom+"; Exit combat as victor. ");
		}else{
			console.log("Room #: "+GAMEAPP.CrntRoom+"; Exit combat as coward. ");
			// Ran away while monster was still in the room.
			CCP.Renown = Person[1].Renown-2;
			Person[1].Renown = CCP.Renown;
			GAMEAPP.InfoText = "Running from Combat? \n Renown is "+String(CCP.Renown);
		}
		if(Person[1].ModStmn > 0){
			this.camera.fade(0x000000, 200, false);
			this.time.events.add(200, function() {
				//Return to Room Scene rv_3 through rv_8
				this.game.state.start(MT[GAMEAPP.CrntRoom].RmID);		
			}, this);
		}else{
			this.camera.fade(0x000000, 200, false);
			this.time.events.add(200, function() {
				//exitGame defeated Room Scene rv_3 through rv_8
				this.game.state.start('exitGame');		
			}, this);
		}
	},
	
	//
	// =========================================================
	// Prep Frame 3
	_GetWpnDamage: function (Dice) {
		var TempT = 0;
		//Rolls Multiple 6-sided dice
		for(var i=1; i 0) {	
			GAMEAPP.InfoText = "WHAT?! NOW ...\n in the middle of Combat?";
		}
		
		if(Person[6].ModStmn < 1){
			GAMEAPP.InfoText = " ... looking in its backpack.\nYou savage all food, gold & gems ... ";
			CCP.HGold += Person[6].Gold;
			CCP.HGem += Person[6].Gem;
			CCP.Food += Person[6].Food;
			this._GameReturn;
		}
		
		if (Person[1].ModStmn < 1) {	
			this._GameReturn;
		} 
	}
	//
	// =========================================================
};
//
// =========================================================
//create a box Image (pseudo graphics) for the HTML5 canvas. 
var box = function(options) {  
	var bxImg = GAMEAPP.game.add.bitmapData(options.length,options.width);  
	bxImg.ctx.beginPath();  
	bxImg.ctx.rect(0,0,options.length,options.width);  
	bxImg.ctx.fillStyle = options.color;  
	bxImg.ctx.fill();  
	return bxImg;  
};
//
// =========================================================
//melee combat: Dynamic Menu; engaged in melee
var meleeCombat = function(player,enemy){  
	this.attackButton.x = 152;
	this.defendButton.x = 240;
	this.fireButton.x = this.world.centerX+800;
	this.dodgeButton.x = this.world.centerX+800;
	if(Person[6].ModStmn <= 0){
			this.enemy.tint = 0xFF0000;
			//GAMEAPP.RoomAlert = "Victory over the " + M[MT[GAMEAPP.LastRoom].Mnstr].Race + "!"
			this.attackButton.x = this.world.centerX+800;
			this.fireButton.x = this.world.centerX+800;
			this.defendButton.x = this.world.centerX+800;
			this.dodgeButton.x = this.world.centerX+800;
			//this.cookButton.x = 65;
			//this.inventoryButton.x = 152;
			this.searchButton.x = 240;
			
	}
	
	if(Person[1].ModStmn <= 0){
		this._GameReturn;
		
	}
};
//
// =========================================================      

See Examples here


Exit Game

/**
 * File Name: exit.js
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html
 * Description: File for controlling game exit and gargabe collection.
 * Author: Stephen Gose
 * Version: 0.0.0.8
 * 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.
 *
 */
	"use strict";
	window.GAMEAPP.state.exitGame = {
		preload: function(){
			console.log("loading Exit Game state");
			GAMEAPP.CrntRoom = GAMEAPP.Logout;
			this.game.load.image('exitGame', 'assets/images/staticRooms/exitGame.jpg');
			this.load.spritesheet('button', 'assets/spriteSheets/mmog-sprites-silver.png', 129, 30);
			this.load.spritesheet('Death','assets/spriteSheets/ARRADeath/ARRADeath.png',160,100);
			this.load.atlas('inventoryButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
			this.load.atlas('exitButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
			this.load.atlas('saveButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
			this.load.atlas('shareButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
			this.load.atlas('submitButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		},
		
		create: function(){
			console.log("starting Exit Game state");
			this.game.add.image(0, 0, 'exitGame');
			//Set a neutral background color
			this.game.stage.backgroundColor = "#000";
			
			//ARRA Character Death animation
			this.ARRADeath = this.game.add.sprite(372, 212, 'Death');
	
			//  Here we add a new animation called 'show Death'
			//  Because we didn't give any other parameters it's going to make an animation from all available frames in the ARRA Death sprite sheet
			var showDeath = this.ARRADeath.animations.add('showDeath');
	
			//  And this starts the animation playing by using its key ("showDeath")
			//  30 is the frame rate (30fps)
			//  true means it will loop when it finishes
			this.ARRADeath.animations.play('showDeath', 8, true);
			
			this.inventorytxt = this.game.add.text(0, 0, "Inventory" , GAMEAPP.styleBTN);
			this.exittxt = this.game.add.text(0, 0, "Exit" , GAMEAPP.styleBTN);	
			this.submitScore = this.game.add.text(0, 0, "Submit" , GAMEAPP.styleBTN);
			this.save = this.game.add.text(0, 0, "Save" , GAMEAPP.styleBTN);
			this.newGame = this.game.add.text(0, 0, "New Game?" , GAMEAPP.styleBTN);
			this.newGame.events.onInputDown.add(this._NewGame, this);
			this.share = this.game.add.text(0, 0, "Share" , GAMEAPP.styleBTN);
			
			// Inventory button 
			this.inventoryButton = this.game.add.button(65, 338, 'button', this._Inventory, this, 2, 1, 0,1);
			this.inventoryButton.anchor.set(0.5,0.5);
			this.inventoryButton.scale.setTo(0.5,0.5);
			this.inventoryButton.addChild(this.inventorytxt).anchor.set(0.5,0.5);
			
			// Exit button 
			this.exitButton = this.game.add.button(65, 361, 'button', GAMEAPP._ExitGame, this, 2, 1, 0,1);
			this.exitButton.anchor.set(0.5,0.5);
			this.exitButton.scale.setTo(0.5,0.5);
			this.exitButton.addChild(this.exittxt).anchor.set(0.5,0.5);
			
			// New Game button 
			this.newButton = this.game.add.button(240, 338, 'button', GAMEAPP._newGame, this, 2, 1, 0,1);
			this.newButton.anchor.set(0.5,0.5);
			this.newButton.scale.setTo(0.5,0.5);
			this.newButton.addChild(this.newGame).anchor.set(0.5,0.5);
			
			// Submit button 
			this.submitButton = this.game.add.button(152, 338, 'button', this._SubmitRoom, this, 2, 1, 0,1);
			this.submitButton.anchor.set(0.5,0.5);
			this.submitButton.scale.setTo(0.5,0.5);
			this.submitButton.addChild(this.submitScore).anchor.set(0.5,0.5);
			
			// Save button 
			this.saveButton = this.game.add.button(152, 361, 'button', this._SaveRoom, this, 2, 1, 0,1);
			this.saveButton.anchor.set(0.5,0.5);
			this.saveButton.scale.setTo(0.5,0.5);
			this.saveButton.addChild(this.save).anchor.set(0.5,0.5);
			
			// Share button 
			this.shareButton = this.game.add.button(240, 361, 'button', this._ShareRoom, this, 2, 1, 0,1);
			this.shareButton.anchor.set(0.5,0.5);
			this.shareButton.scale.setTo(0.5,0.5);
			this.shareButton.addChild(this.share).anchor.set(0.5,0.5);
			
			this._toolTip = this.game.add.text(this.game.world.width-100, this.game.world.height-90, GAMEAPP.InfoText, GAMEAPP.styleTT);
			this._toolTip.anchor.set(0.5);
			GAMEAPP.InfoText = "Experience & Score: "+String(CCP.Score)+"\n Renown Earned: "+String(CCP.Renown);
			GAMEAPP.RoomAlert = "Quest failed!";
			//rv_5
			//Send update to server as a "heart beat / keep alive"
			//TXBuffer();
			//Heart.send("update.asp",POST);
			
			//rv_8
			//IBPrpArcade game scores enabled
			var gname="ARRA-PBMCube";
			var pname = CCP.Name;
			var gscore = CCP.Renown;
			//getURL("index.php?act=Arcade&do=newscore", "_blank", "POST");
			
		},
		
		update: function(){
			this._toolTip.setText(GAMEAPP.InfoText);
			
			//this.ARRADeath.x = this.game.world.width-178;
			//this.ARRADeath.y = 212;
			this.ARRADeath.animations.play('showDeath', 8, true);
		},
		
		//
		// =========================================================
		_InventoryRoom: function(){
			
			//debug
			console.log("Room #: Exit defeated; Inventory Clicked: ");
			
			this.camera.fade(0x000000, 200, false);
			this.time.events.add(200, function() {
				this.game.state.start('Inventory');		//Inventory Scene rv_3 through rv_8
			}, this);
			
		},
		//
		// =========================================================
		_NewGame: function(){
			//Refer to book Bonus Content server-side middleware
			//debug
			console.log("Room #: Exit defeated; New Game Clicked: ");
			console.log(' - Equip ALL Monsters in Database once per game.');
		GAMEAPP._MonsterPrep();
		GAMEAPP._AllotMonster();
		
		console.log(' - Creating internal static Monster Database:');
		console.table(M);
		
		console.log(' - Creating internal static Movement Table:\n See book for dynamically generated Movement Tables and Mazes.');
		console.log('Distributing 6 Treasures and 7 Monsters once per game.');
		GAMEAPP._AllotTreasure();
		console.table(MT);
			
			this.camera.fade(0x000000, 200, false);
			this.time.events.add(200, function() {
				this.game.state.start('boot');		//Boot/Preload Scene rv_3 through rv_8
			}, this);
		},
		//
		// =========================================================
		_SaveRoom: function(){
			//Refer to book Bonus Content server-side middleware
			//debug
			console.log("Room #: Exit defeated; Save Clicked: ");
		},
		//
		// =========================================================
		_ShareRoom: function(){
			//Refer to book Bonus Content server-side middleware
			//debug
			console.log("Room #: Exit defeated; Share Clicked: ");
		},
		//
		// =========================================================
		_SubmitRoom: function(){
			//Refer to book Bonus Content server-side middleware
			//debug
			console.log("Room #: Exit defeated; Submit Clicked: ");
		}
	};
      

See Examples here


Inventory.js (5kB)

/**
 * File Name: inventory.js
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html
 * Description: File for controlling and displaying avatar inventory; managing global variables throughout game state.
 * Author: Stephen Gose
 * Version: 0.0.0.8
 * 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.
 *
 */
	"use strict";
	window.GAMEAPP.state.Inventory = {
		preload: function(){
			console.log("loading inventory state");
			this.game.load.image('Inventory', 'assets/images/staticRooms/inventory.jpg');
			this.load.spritesheet('button', 'assets/spriteSheets/mmog-sprites-silver.png', 129, 30);
			this.load.atlas('cookButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
			this.load.atlas('returnButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
	
		},
		
		create: function(){
			
			console.log("entering Invetory state:");
			this.game.add.image(0, 0, 'Inventory');
			
			var cooktxt = this.game.add.text(0, 0, "Cook" , GAMEAPP.styleBTN);		// "Cook" button text;
			var returntxt = this.game.add.text(0, 0, "Return" , GAMEAPP.styleBTN);	// "Return" button text;
			
			this.cGoldtxt = this.game.add.text(80, 110, String(CCP.HGold)+"\n" , GAMEAPP.styleHUD);
			this.cGemstxt = this.game.add.text(80, 136, String(CCP.HGem)+"\n" , GAMEAPP.styleHUD);
			this.cFoodtxt = this.game.add.text(80, 159, String(CCP.Food)+"\n" , GAMEAPP.styleHUD);
			this.cArrowstxt = this.game.add.text(80, 183, String(CCP.Arrows)+"\n" , GAMEAPP.styleHUD);
			this.cStmnatxt = this.game.add.text(this.game.world.width-75, 125, String(CCP.ModStmn)+"\n" , GAMEAPP.styleHUD);
			var cWS = ((CCP.WSRaw * 5) + (CCP.Stmn * 2)) + "%";
			this.csWStxt = this.game.add.text(this.game.world.width-75, 150, String(cWS)+"\n" , GAMEAPP.styleHUD);
			var cBS = ((CCP.BSRaw * 5) + (CCP.Coor * 2)) + "%";
			this.csBStxt = this.game.add.text(this.game.world.width-75, 173, String(cBS)+"\n" , GAMEAPP.styleHUD);
			var cPS = ((CCP.BSRaw * 5) + (CCP.Coor * 2)) + "%";
			this.csPStxt = this.game.add.text(this.game.world.width-75, 195, String(cPS)+"\n" , GAMEAPP.styleHUD);
			this.cRenowntxt = this.game.add.text(this.game.world.width-75, 218, String(CCP.Renown)+"\n" , GAMEAPP.styleHUD);
			this.cExptxt  = this.game.add.text(this.game.world.width-75, 243, String(CCP.Score)+"\n" , GAMEAPP.styleHUD);
			
			this._toolTip = this.game.add.text(this.game.world.width-100, this.game.world.height-90, GAMEAPP.InfoText, GAMEAPP.styleTT);
			this._toolTip.anchor.set(0.5);
			
			// Cook button 
			this.cookButton = this.game.add.button(65, 338, 'button', this._CookFood, this, 2, 1, 0, 1);
			this.cookButton.anchor.set(0.5,0.5);
			this.cookButton.scale.setTo(0.5,0.5);
			this.cookButton.addChild(cooktxt).anchor.set(0.5,0.5);
			
			// Exit button 
			this.returnButton = this.game.add.button(152, 338, 'button', this._GameReturn, this, 2, 1, 0, 1);
			this.returnButton.anchor.set(0.5,0.5);
			this.returnButton.scale.setTo(0.5,0.5);
			this.returnButton.addChild(returntxt).anchor.set(0.5,0.5);
			
		},
		
		update: function(){
			
		},
		// 
		// =========================================================
		_CookFood: function(){
			CCP.Food -= 1;
			if(CCP.Food < 0){
				CCP.Food = 0;
				this.cFoodtxt.setText(CCP.Food);
				this.cStmnatxt.setText(CCP.ModStmn);
				GAMEAPP.InfoText = " ... You have nothing to eat. ";
				this._toolTip.setText(GAMEAPP.InfoText);
			}else{
				GAMEAPP.InfoText = " ... mmmm! ...\n You grow in stamina!";
				this.cFoodtxt.setText(CCP.Food);
				CCP.ModStmn += 2;
				//if current health is greater than it should be?!
				if(CCP.ModStmn > CCP.Stmn){
					CCP.ModStmn = CCP.Stmn;
				}
				this.cStmnatxt.setText(CCP.ModStmn);
			}
		},
		// 
		// =========================================================
		_GameReturn: function(){
			//debug
			console.log("Inventory State exited to Room #: "+GAMEAPP.CrntRoom+"; ");
			
			this.camera.fade(0x000000, 200, false);
			this.time.events.add(200, function() {
				this.game.state.start(MT[GAMEAPP.CrntRoom].RmID);		//Inventory Scene rv_3 through rv_8
			}, this);
		}
	};

See Examples here


Language.js (11kB)

Version 8 pre-dates languages scenes; refer to ARRA v15 in Chapter 3 Keeping your SCRUM D.R.Y. Example 3.2


See Examples here


Load.js (3kB)

The "load.js" performs the same tasks as the "boot.js"; they load the current "Artwork Theme" (AT) Component. It holds the "... all the artwork used by the Game Framework Component for the visual elements ... " of the game. We could replace (i.e., overwrite!) the current artwork theme but retain the same file names in the "boot.js" and have a "new game with different artwork theme" using the same Game Mechanics (GM) and Game Framework Mechanisms (GFM).
/**
 * File Name: load.js
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html
 * Description: File for controlling assets downloads; some delegations to browser.
 * Author: Stephen Gose
 * Version: 0.0.0.8
 * 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.
 *
 */
	"use strict";
	window.GAMEAPP.state.load = {
		preload: function(){
			console.log(" %c Game Prototype load game assets ", "color:white; background:red");
			// we have preloaded assets required for Loading group objects in the Boot state
			var loadingGroup = mt.create("Loading");
			
			// loading has been deleted?
			// continue to load rest of the textures
			if(!loadingGroup){
				mt.preload();
				return;
			}
			
			// get preload sprite
			var preload = loadingGroup.mt.children.preload;
			
			// preload has been deleted?
			// continue to load rest of the textures
			if(!preload){
				mt.preload();
				return;
			}
			
			// set it as preload sprite
			// buid loading bar
			this.load.setPreloadSprite(preload);
	
			// update group transform - so we can get correct bounds
			loadingGroup.updateTransform();
	
			// get bounds
			var bounds = loadingGroup.getBounds();
	
			// move it to the center of the screen
			loadingGroup.x = this.game.camera.width*0.5 - (bounds.width) * 0.5  - bounds.x;
			loadingGroup.y = this.game.camera.height*0.5 - (bounds.height) - bounds.y;
			// load all assets
			mt.preload();
		},
		
		create: function(){
			// loading has finished - proceed to demo state
			this.game.add.image(0, 0, 'background');
			//ARRA skips languages and main menu; it goes directly to Story scene.
			this.game.state.start("story");
		}
	};

See Examples here


Main.js (35kB)

The "main.js" (aka game.js) is the "Game Mechanics" (GM) Component. It holds the "... rules, logic, and data structures ... " of the game.

/**
 * File Name: Main.js
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html
 * Description: File for controlling and displaying game scenes; managing global variables throughout game state.
 * Author: Stephen Gose
 * Version: 0.0.0.8
 * 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; doing so will void any support agreement.
 *
 * Redistribution of part or whole of this file and
 * the accompanying files is strictly prohibited.
 *
 */
"use strict";
/**	game set-up	**/
//Beginning of Static databases
//**TODO** 
// NOTE: the following data structures are for development only.
//	The optimum usage is a local or remote database using PouchDB or SQLite.
//	Stay away from IndexDB since it is deprecated.

console.log("%c      Starting my awesome MMoG game Prototype!     \n Adventurers of Renown: Ruins of Able-Wyvern rv_8  \n        Copyright \u00A9 1974-2017,  Stephen Gose.      \n  | https://renown-games.com/shop |                      \n  | \u2665\u2665\u2665\u2665\u2665 -> $120 License included in book!        \n  | Book available at: https://leanpub.com/LoRD |   ",
	"color:white; background:blue");
console.log('Initial Avatar Character for FREE Game play;\n   Members can customize characters.');
// 
// =========================================================
function ArmorClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {
	this.AID = a1;
	this.Name = a2;
	this.Protect = a3;
	this.Stack = a4;
	this.Cost = a5;
	this.Worth = a6;
	// New property. Current armor value to sell
	this.Weight = a7;
	this.CoorMod = a8;
	this.MoveMod = a9;
	this.StmnReq = a10;
	// New property for ARRA v3.3
	this.BodyLoc = a11;
	// 0=Shield;1=Head;2=Body;3=Arms;4=Legs
	this.DefenseType = a12;
	// Chop=C;Slash=S;Smash=S;Thrust=T: "CSST"
	this.Magic = a13;
	this.Renown = a14;
	// Class Inherited Methods:
}
//  End Armor Class
// =========================================================
// Prep Frame 2
function PersonClass(p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24,p25,p26,p27,p28) {
	this.PID = p1;	//default - 0
	this.CID = p2;	//default - 1
	this.Name = p3;	//default - Common Adventurer
	this.Score = p4;	//0
	this.TempScore = 0;
	this.Category = p5; //Warrior
	this.Health = p6; //Healthy
	this.Race = p7; //Folks
	this.Stmn = Number(p8); //12
	this.ModStmn = Number(p9);
	this.Fatigue = Number(p10);
	//p11? - future use
	this.Coor = Number(p12);  //12
	this.Psych = Number(p13); //8
	this.ModIQ = Number(p14); //8
	this.Renown = Number(p15); //1
	this.HGold = Number(p16); //0
	this.HGem = Number(p17); //0
	this.Movemnt = p18; //10
	this.MegaSQ = 1;
	this.Room = 6;
	this.Food = Number(p19); //1
	this.WSRaw = Number(p20); //2
	this.WSCmbt = p21; //NO
	this.BSRaw = Number(p22); //2
	this.BSCmbt = p23; //NO
	this.AtkFlag = 0;
	this.MisFlag = 0;
	this.PryFlag = 0;
	this.HitFlag = 0;
	this.EngFlag = 0;
	this.MovFlag = 0;
	this.Target = 6;
	this.TLoc = 2;
	this.TotalAP = Number(p24); //2
	this.Shield = p25; //Shield Name?
	this.Arrows = Number(p26); //0
	this.AName = p27;	//Body Armor Name
	this.WName = p28;	//Primary Weapon Name

	this.W = new Array();
	// Weapons Array for this person
	this.W[0] = {WID:0,Name:"Short Sword",Damage:2,DamMod:0,DamType:"CSST",Mode:"MMT",Cost:0,Worth:0,Weight:0,ReqStmn:0,ReqCoor:0,Use:0,Magic:0,Renown:0};
	// The Weapon in USE!!
	this.W[1] = {WID:0,Name:"None",Damage:0,DamMod:0,DamType:"CSST",Mode:"MMT",Cost:0,Worth:0,Weight:0,ReqStmn:0,ReqCoor:0,Use:0,Magic:0,Renown:0};
	// Primary Weapon = [1];Secondary = [2]
	this.W[2] = {WID:0,Name:"None",Damage:0,DamMod:0,DamType:"CSST",Mode:"MMT",Cost:0,Worth:0,Weight:0,ReqStmn:0,ReqCoor:0,Use:0,Magic:0,Renown:0};
	// Secondary Weapon = [2]
	this.W[3] = {WID:0,Name:"None",Damage:0,DamMod:0,DamType:"CSST",Mode:"MMT",Cost:0,Worth:0,Weight:0,ReqStmn:0,ReqCoor:0,Use:0,Magic:0,Renown:0};
	// Backup Weapon = [3]
	// Armor Array for this person
	this.A = new Array();
	// Shield position
	this.A[0] = {AID:0,Name:"Small Shield",Protect:1,Stack:"Y",DefType:"CSST",BodyLoc:"Shield",Cost:0,Worth:0,Weight:0,CoorMod:0,MoveMod:0,ReqStmn:0,Magic:0,Renown:0};
	// Helm position
	this.A[1] = {AID:0,Name:"None",Protect:0,Stack:0,DefType:"CSST",BodyLoc:"Head",Cost:0,Worth:0,Weight:0,CoorMod:0,MoveMod:0,ReqStmn:0,Magic:0,Renown:0};	
	// Body Armor is Leather Jerkin
	this.A[2] = {AID:0,Name:"Leather Jerkin",Protect:2,Stack:"Y",DefType:"CS--",BodyLoc:"Body",Cost:0,Worth:0,Weight:0,CoorMod:2,MoveMod:0,ReqStmn:0,Magic:0,Renown:0};
	// Arm's Armor position	
	this.A[3] = {AID:0,Name:"None",Protect:0,Stack:0,DefType:"CSST",BodyLoc:"Arms",Cost:0,Worth:0,Weight:0,CoorMod:0,MoveMod:0,ReqStmn:0,Magic:0,Renown:0};
	// Leg's Armor position
	this.A[4] = {AID:0,Name:"None",Protect:0,Stack:0,DefType:"CSST",BodyLoc:"Legs",Cost:0,Worth:0,Weight:0,CoorMod:0,MoveMod:0,ReqStmn:0,Magic:0,Renown:0};

	// PersonClass Inherited Methods:
	this.ModMove = function () { return this.Movemnt-(this.A[0].MoveMod+this.A[2].MoveMod);};
	this.ModCoor = function () { return this.Coor-(this.A[0].CoorMod+this.A[2].CoorMod);};
	this.Level = function () { return (((this.Stmn+this.Coor+this.Psych)-26)/6);};
	this.WS = function () { return ((this.Stmn*2)+(this.WSRaw*5));};
	this.BS = function () { return ((PersonClass.prototype.ModCoor*2)+(this.BSRaw*5));};
	this.PS = function () { return ((PersonClass.prototype.ModCoor*2)+(this.WSRaw*5));};
}
// End PersonClass
// =========================================================
//Prep Scene Frame 1
function WeaponClass(w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14) {
	this.WID = w1;
	this.Name = w2;
	this.DamPossible = w3;
	this.DamMod = w4;
	this.Cost = w5;
	this.Worth = w6;
	// New property. Current armor value to sell
	this.Weight = w7;
	this.StmnReq = w8;
	this.CoorReq = w9;
	this.Use = w10;
	// 1=One handed; 2=Both hands
	this.Mode = w11;
	// M=Melee;Missle=M;T=Thrown: "MMT"
	this.DamType = w12;
	// Chop=C;Slash=S;Smash=S;Thrust=T: "CSST"
	this.Magic = w13;
	this.Renown = w14;
	this.DamageDone = GetWpnDamage();
	// Damage Delt per call
	// Class Inherited Methods:
}
// End Weapons Class
// =========================================================
//**TODO** 
//Prep Scene Frame 1
// Root TimeLine Variables                 (Global for this timeline)
//var SecondaryWpns = new WeaponClass(10, "Dagger", 1, 0, 50, 50, 1, 1, 4, 1, "M-T", "CS-T", 0, 0);
//var PrimaryWpns = new WeaponClass(23, "Short Sword", 2, -1, 200, 200, 3, 10, 4, 1, "M--", "CS-T", 0, 0);
//var NoWpns = new WeaponClass(0, "None", 0, 0, 0, 0, 0, 0, 0, 0, "---", "----", 0, 0);
//var BodyArm = new ArmorClass(103, "Leather Jerkin", 2, "No", 100, 100, 2, -2, -2, 8, 2, "-S--", 0, 0);
//var NoneArm = new ArmorClass(0, "None", 0, "No", 0, 0, 0, 0, 0, 0, 0, "----", 0, 0);

//**TODO** 
//	Set-up MMoG capabilities; Person(1) intialized prior to each Combat as a temporary combat record
//	The follow could be in external files to initialize the char's combat records
// 	for the campaigne.
console.log('MMoG Database and Combat records:\n   up to 4 member/player teams!\n   Records 5-8 are monster team records.\n Player Avatar is record 1\n Monster encountered uses record 6.\nRefer to book to migrate into a SQLite database or PouchDB.')
var Person = new Array();
Person[1] = {Target:6, TotalAP:0, WS:0, BS:0, PS:0, ModStmn:0, TempScore:0, Renown:0};
Person[2] = {Target:6, TotalAP:0, WS:0, BS:0, PS:0, ModStmn:0, TempScore:0, Renown:0};
Person[3] = {Target:6, TotalAP:0, WS:0, BS:0, PS:0, ModStmn:0, TempScore:0, Renown:0};
Person[4] = {Target:6, TotalAP:0, WS:0, BS:0, PS:0, ModStmn:0, TempScore:0, Renown:0};
//below are monster combat records
Person[5] = {Target:1, TotalAP:0, WS:0, BS:0, PS:0, ModStmn:0, TempScore:0, Renown:0};
Person[6] = {Target:1, TotalAP:0, WS:0, BS:0, PS:0, ModStmn:0, TempScore:0, Renown:0};
Person[7] = {Target:1, TotalAP:0, WS:0, BS:0, PS:0, ModStmn:0, TempScore:0, Renown:0};
Person[8] = {Target:1, TotalAP:0, WS:0, BS:0, PS:0, ModStmn:0, TempScore:0, Renown:0};

//CCP - Current Character Played
//**TODO**  Set for remote login and data access into members' personal avatar records
var CCP = new PersonClass(0,1,"Common Adventurer",0,"Warrior","Healthy","Folks",20,20,20,20,20,8,8,1,0,0,10,1,2,"N",2,"N",3,"Small Shield",0,"Leather Jerkin","Short Sword");
//console.table(CCP);

//Create Monster Array using MonsterClass object
//**TODO** Remote this static database onto database server; otherwise use PouchDB or SQLite
var M = new Array();
M[1] = {icon:"barbarian",Race:"Folks",Category:"Warrior",Stmn:15,Coor:14,Psych:8,Renown:3,HGold:47,HGem:1,Food:1,WSRaw:3,BSRaw:1,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[2] = {icon:"dwarf",Race:"Folks",Category:"Warrior",Stmn:14,Coor:13,Psych:8,Renown:3,HGold:76,HGem:0,Food:0,WSRaw:3,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[3] = {icon:"darkPriest",Race:"Dark Elf",Category:"Rogue",Stmn:13,Coor:16,Psych:9,Renown:3,HGold:89,HGem:2,Food:2,WSRaw:2,BSRaw:3,Move:15,Room:0,TotalAP:0,Armor:"",Weapn:"",WDam:0};
M[4] = {icon:"goblin",Race:"Goblin",Category:"Warrior",Stmn:13,Coor:12,Psych:8,Renown:2,HGold:34,HGem:2,Food:0,WSRaw:2,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[5] = {icon:"barbarian",Race:"Hobbit",Category:"Rogue",Stmn:9,Coor:13,Psych:10,Renown:4,HGold:57,HGem:1,Food:4,WSRaw:2,BSRaw:3,Move:8,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[6] = {icon:"dwarf",Race:"Dwarf",Category:"Warrior",Stmn:15,Coor:10,Psych:8,Renown:4,HGold:89,HGem:3,Food:1,WSRaw:3,BSRaw:2,Move:8,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[7] = {icon:"goblin",Race:"Goblin",Category:"Warrior",Stmn:13,Coor:11,Psych:8,Renown:2,HGold:52,HGem:0,Food:0,WSRaw:2,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[8] = {icon:"orc",Race:"Orc",Category:"Warrior",Stmn:11,Coor:13,Psych:8,Renown:3,HGold:77,HGem:0,Food:1,WSRaw:3,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[9] = {icon:"darkMage",Race:"Dark Mage",Category:"Mage",Stmn:12,Coor:12,Psych:8,Renown:3,HGold:98,HGem:0,Food:2,WSRaw:2,BSRaw:3,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[10] = {icon:"orc",Race:"Orc",Category:"Warrior",Stmn:13,Coor:11,Psych:8,Renown:4,HGold:37,HGem:0,Food:1,WSRaw:3,BSRaw:3,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[11] = {icon:"whiteMage",Race:"Goblin Mage",Category:"Mage",Stmn:10,Coor:14,Psych:8,Renown:3,HGold:23,HGem:1,Food:1,WSRaw:3,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[12] = {icon:"orc",Race:"Woodland Orc",Category:"Warrior",Stmn:11,Coor:13,Psych:8,Renown:4,HGold:93,HGem:1,Food:2,WSRaw:3,BSRaw:3,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[13] = {icon:"goblin",Race:"Goblin",Category:"Warrior",Stmn:12,Coor:12,Psych:8,Renown:3,HGold:76,HGem:0,Food:1,WSRaw:2,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[14] = {icon:"whitePriest",Race:"Elf Priest",Category:"Rogue",Stmn:9,Coor:17,Psych:10,Renown:6,HGold:97,HGem:2,Food:1,WSRaw:3,BSRaw:4,Move:15,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[15] = {icon:"dwarf",Race:"Dwarf Hero",Category:"Warrior",Stmn:13,Coor:13,Psych:9,Renown:6,HGold:103,HGem:4,Food:2,WSRaw:3,BSRaw:4,Move:8,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[16] = {icon:"goblin",Race:"Goblin Hero",Category:"Warrior",Stmn:11,Coor:18,Psych:8,Renown:8,HGold:78,HGem:3,Food:1,WSRaw:3,BSRaw:3,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[17] = {icon:"orc",Race:"Orc Hero",Category:"Warrior",Stmn:12,Coor:18,Psych:9,Renown:8,HGold:92,HGem:2,Food:1,WSRaw:4,BSRaw:4,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[18] = {icon:"hero2",Race:"Folks Hero",Category:"Warrior",Stmn:13,Coor:16,Psych:8,Renown:7,HGold:87,HGem:1,Food:0,WSRaw:4,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[19] = {icon:"mummy",Race:"Mummy",Category:"Undead",Stmn:9,Coor:11,Psych:7,Renown:4,HGold:0,HGem:0,Food:0,WSRaw:2,BSRaw:2,Move:8,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[20] = {icon:"skeleton",Race:"Skeleton",Category:"Undead",Stmn:8,Coor:11,Psych:4,Renown:2,HGold:0,HGem:0,Food:0,WSRaw:2,BSRaw:2,Move:8,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[21] = {icon:"skeleton",Race:"Skeleton",Category:"Undead",Stmn:8,Coor:11,Psych:4,Renown:2,HGold:0,HGem:0,Food:0,WSRaw:2,BSRaw:2,Move:8,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[22] = {icon:"zombie",Race:"Zombie",Category:"Undead",Stmn:10,Coor:11,Psych:6,Renown:3,HGold:0,HGem:0,Food:0,WSRaw:3,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[23] = {icon:"zombie",Race:"Zombie",Category:"Undead",Stmn:10,Coor:11,Psych:6,Renown:3,HGold:0,HGem:0,Food:0,WSRaw:3,BSRaw:2,Move:10,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[24] = {icon:"mummy",Race:"Mummy",Category:"Undead",Stmn:9,Coor:11,Psych:7,Renown:4,HGold:0,HGem:0,Food:0,WSRaw:2,BSRaw:2,Move:8,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[25] = {icon:"skeleton",Race:"Skeleton",Category:"Undead",Stmn:8,Coor:11,Psych:4,Renown:2,HGold:0,HGem:0,Food:0,WSRaw:2,BSRaw:2,Move:8,Room:0,Armor:"",TotalAP:0,Weapn:"",WDam:0};
M[26] = {icon:"wyvern",Race:"Young Wyvern",Category:"Mage",Stmn:26,Coor:16,Psych:14,Renown:12,HGold:890,HGem:14,Food:9,WSRaw:5,BSRaw:4,Move:20,Room:0,Armor:"",TotalAP:4,Weapn:"",WDam:0};

//Movement Table; could be extenally loaded
//**TODO** Remote this static database onto database server; otherwise upgrade to PouchDB or SQLite
var MT = new Array();
MT[0] = {RmID:'combat', North:0, East:0, South:0, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:0, mxPos:280, myPos:150};
MT[1] = {RmID:'R1', North:0, East:0, South:2, West:1, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:280, myPos:150};
MT[2] = {RmID:'R2', North:1, East:3, South:3, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:280, myPos:150};
MT[3] = {RmID:'R3', North:2, East:5, South:0, West:2, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:235, myPos:230};
MT[4] = {RmID:'R4', North:0, East:0, South:5, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:220, myPos:160};
MT[5] = {RmID:'R5', North:4, East:0, South:0, West:3, Up:15, Dn:13, Tres:0, Mnstr:0, Discovr:1, mxPos:200, myPos:230};
MT[6] = {RmID:'R6', North:0, East:1, South:0, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:0, mxPos:200, myPos:260};
MT[7] = {RmID:'R7', North:0, East:0, South:8, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:220, myPos:240};
MT[8] = {RmID:'R8', North:7, East:0, South:10, West:0, Up:9, Dn:13, Tres:0, Mnstr:0, Discovr:1, mxPos:150, myPos:260};
MT[9] = {RmID:'R9', North:0, East:0, South:19, West:0, Up:0, Dn:8, Tres:0, Mnstr:0, Discovr:1, mxPos:200, myPos:190};
MT[10] = {RmID:'R10', North:8, East:11, South:0, West:0, Up:9, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:265, myPos:215};
MT[11] = {RmID:'R11', North:0, East:0, South:0, West:10, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:450, myPos:290};
MT[12] = {RmID:'R12', North:0, East:0, South:0, West:13, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:210, myPos:210};
MT[13] = {RmID:'R13', North:0, East:12, South:0, West:0, Up:5, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:165, myPos:190};
MT[14] = {RmID:'R14', North:0, East:17, South:15, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:175, myPos:150};
MT[15] = {RmID:'R15', North:14, East:0, South:0, West:0, Up:0, Dn:5, Tres:0, Mnstr:0, Discovr:1, mxPos:175, myPos:190};
MT[16] = {RmID:'R16', North:17, East:0, South:0, West:19, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:190, myPos:220};
MT[17] = {RmID:'R17', North:18, East:0, South:16, West:14, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:235, myPos:240};
MT[18] = {RmID:'R18', North:0, East:0, South:17, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:200, myPos:170};
MT[19] = {RmID:'R19', North:9, East:16, South:0, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:1, mxPos:165, myPos:190};
MT[20] = {RmID:'Inventory', North:0, East:0, South:0, West:0, Up:0, Dn:0, Tres:0, Mnstr:0, Discovr:0, mxPos:1600, myPos:200};
// End of database structures
//**TODO** 
// NOTE: the following data structures are for development only.
//	The optimum usage is a local or remote database using PouchDB or SQLite.
//	Stay away from IndexDB since it is deprecated.
// =========================================================

//**TODO** Creating Game namespace called GAMEAPP; refactor GAMEAPP with your project name
window.GAMEAPP = {
	//US Copr. or Copyright; UTF8 circled c is \u00A9 equal to ©
	Copr: "Copyright © \u00A9 1974-2016, Stephen Gose. All rights reserved.\n",
	// reference to the Phaser.Game instance
	game: null,
	
	// If there's music in your game, and it needs to play through-out a 
	//	  few State swaps, then you could reference it below. 
	music: null,
	
	//Toggle background music theme on or off; starts in "on/true" state 
	musicToggle: true,
	
	//Your game can check MYGAMEAPP.orientated in the game loops 
	//	  to know if it should pause or not.
	//orientated: false,
	
	/**
	//Grid Tile-Map configurations
	//**TODO** Remote this static database onto database server; otherwise upgrade to PouchDB or SQLite
	//Tile-maps are the visual express separate from the Movement Tables metadata.
	tileSize: 64,	//twice the size of an avatar icon
	numRows: 3,		//adjustable for your game
	numCols: 3,		//adjustable for your game
	tileSpacing: 2,	//adjustable for your game
	tilesArray: [], //one way; thousand more to choose
	*/
	//Canvas dimensions: world and viewportHeight
	//**TODO** adjust for your game deployment
	viewportWidth: 550,	//game view
	viewportHeight: 440,
	worldWidth: 550,		//world view
	worldHeight: 440,
	
	// =========================================================
	//**TODO** refactor and adjust for your game deployment
	//	Trash Global Variables (alphabetical)
	//	Here we have some global level vars that persist regardless of State. 
	// =========================================================
	CmbtTurn: 1,		// Combat Round counter
	Cntr: 0,
	CrntRoom: 6,		// Current Room occupied
	DeadMonster: 0,
	doorN:{},
	doorE:{},
	doorS:{},
	doorW:{},
	doorN2:{},
	doorDn:{},
	doorUp:{},
	enemy:{},			//single player game; array used in MMoG
	Entrance:{},		//Room #6 only
	gameState: 'explore',
	//dynamic toolTip across game states
	//**TODO**: store information text in a database for dynamic language conversion.
	InfoText: "Score: "+CCP.Score+"\n Click on the Door to enter.",	
	KeyNum: 0,
	LastRoom: 6,		// Last Room entered, used to remove monsters from current room
	LastDoor:"East",	// help place avatar properly in new room entrance
	Logout: "EXIT",		//exit game defeated.
	movespeed: 10,		//default base movement points; this is not pixels.
	mxPos: 200,			// Monster _x position
	myPos: 260,			// Monster _y position
	Narr1: 'doodah',	// Player Combat Narrative text
	Narr2: "doodah",	// Monster Combat Narrative text
	player:{},			//single player game; array used in MMoG
	RoomAlert:"",		//HUD Room alert info
	rect:{},
	Trash: 0,
	Treasure:{},		//treasure icon
	//button styling
	styleBTN: { font: "28px Arial", fill: "#000000", align: "center" },
	//Combat HUD styling
	//	hero text
	styleCmbtH: { font: "9px Arial", fill: "#66ffff", align: "center" },	
	styleNarrH: { font: "9px Arial", fill: "#66ffff", align: "left" },
	//	monster text
	styleCmbtM: { font: "9px Arial", fill: "#66ff66", align: "center" },
	styleNarrM: { font: "9px Arial", fill: "#66ff66", align: "left" },
	//HUD styling
	styleHUD: { font: "14px Arial", fill: "#ff9900", align: "center" },
	//Room Alert styling
	styleRA: { font: "18px Arial", fill: "#ff9900", align: "right" },
	//toolTip styling
	styleTT: { font: "11px Arial", fill: "#ff9900", align: "center" },
	TxPos: 0,		// Treasure's default x position
	TyPos: 0,		// Treasure's default y position
	xPos: 90,		// Character default x position
	yPos: 200,		// Character default y position
	
	// here we will store all game phase/states
	//  state object filled as js files load.
	state: {},
	
	// =========================================================
	// -------------------------------------------
	// Main game Handler methods
	// -------------------------------------------
	//**TODO**:
	//	refactor and adjust for your game deployment
	//	remove console debug information on public deployment
	// =========================================================
	main: function(){
		this.game = new Phaser.Game(window.GAMEAPP.viewportWidth, window.GAMEAPP.viewportHeight, Phaser.AUTO, document.body, window.GAMEAPP.state.boot);
		this._DevelopCR();			//create avatar combat record
		//console.table(Person);	//debug
		console.log(' - Equip ALL Monsters in Database once per game.');
		this._MonsterPrep();
		this._AllotMonster();
		
		console.log(' - Creating internal static Monster Database:');
		console.table(M);
		
		console.log(' - Creating internal static Movement Table:\n See book for dynamically generated Movement Tables and Mazes.');
		console.log('Distributing 6 Treasures and 7 Monsters once per game.');
		this._AllotTreasure();
		console.table(MT);
	},
	// =========================================================
	// -------------------------------------------
	// Supporting game Function & Classes
	// -------------------------------------------
	//**TODO**:
	//	Change namespace from generic GAMEAPP to your project 
	//	refactor and adjust for your game deployment
	//	remove console debug information on public deployment
	// =========================================================
	_audioMgr: function(mode, game) {
		switch(mode) {
			case 'init': {
				GAMEAPP.Storage.initUnset('GAMEAPP.audio', true);
				GAMEAPP._audioStatus = GAMEAPP.Storage.get('GAMEAPP.audio');
				// GAMEAPP._soundClick = game.add.audio('audio-click');
				GAMEAPP._sound = [];
				GAMEAPP._sound['click'] = game.add.audio('audio-click');
				if(!GAMEAPP._soundMusic) {
					GAMEAPP._soundMusic = game.add.audio('audio-theme',1,true);
					GAMEAPP._soundMusic.volume = 0.5;
				}
				break;
			}
			case 'on': {
				GAMEAPP._audioStatus = true;
				break;
			}
			case 'off': {
				GAMEAPP._audioStatus = false;
				break;
			}
			case 'switch': {
				GAMEAPP._audioStatus =! GAMEAPP._audioStatus;
				break;
			}
			default: {}
		}
		if(GAMEAPP._audioStatus) {
			GAMEAPP._audioOffset = 0;
			if(GAMEAPP._soundMusic) {
				if(!GAMEAPP._soundMusic.isPlaying) {
					GAMEAPP._soundMusic.play('',0,1,true);
				}
			}
		}
		else {
			GAMEAPP._audioOffset = 4;
			if(GAMEAPP._soundMusic) {
				GAMEAPP._soundMusic.stop();
			}
		}
		GAMEAPP.Storage.set('GAMEAPP.audio',GAMEAPP._audioStatus);
		game.buttonAudio.setFrames(GAMEAPP._audioOffset+1, GAMEAPP._audioOffset+0, GAMEAPP._audioOffset+2);
	},
	// 
	// =========================================================
	_AllotTreasure: function() {
		var RmNum = 2;
		var Rm;
		var Cntr = 1;
		//**TODO**: 5 is a fixed value for demonstation game.
		//	Create and use a variable
		while (Cntr<5) {
			// This determines the Room Number
			//**TODO**: 
			// 	Notice: using a fixed number here; this
			//		could be substituted with  MT.length for dynamic adjustments
			RmNum = (Math.round(Math.random()*18))+1;
			if (MT[RmNum].Tres == 0) {
				var KeyNum = Math.round(Math.random()*100)+10;
				MT[RmNum].Tres += KeyNum;
				Cntr += 1;
//				console.log("Room #: "+MT[RmNum].RmID);
//				console.log("- Mnstr: #"+MT[RmNum].Mnstr);
//				console.log("- Tresr: $"+MT[RmNum].Tres);
			}
		}
		// Place Treasure in the Private Meeting Room and Treasury regardless
		//**TODO**: 
		// 	Notice: using a fixed number here; this
		//		could be substituted with  variable for dynamic adjustments
		KeyNum = Math.round(Math.random()*100)+50;
		MT[4].Tres += KeyNum;
		KeyNum = Math.round(Math.random()*200);
		MT[16].Tres += KeyNum;
//		console.log("Room #: "+MT[4].RmID);
//		console.log("- Mnstr: #"+MT[4].Mnstr);
//		console.log("- Tresr: $"+MT[4].Tres);
//		console.log("Room #: "+MT[16].RmID);
//		console.log("- Mnstr: #"+MT[16].Mnstr);
//		console.log("- Tresr: $"+MT[16].Tres);
//		console.log("Treasures Allocated.");
		console.log("=== Allocate Treasure completed: ===");
	
	},
	// 
	// =========================================================
	// Prep Frame 2
	 _AllotMonster: function() {
		var RmNum = 1;
		var Rm;
		var Cntr = 1;
		while (Cntr<7) {
			// This determines the Room Number
			//**TODO**: 
			// 	Notice: using a fixed number here; this
			//		could be substituted with  MT.length for dynamic adjustments
			RmNum = (Math.round(Math.random()*18))+1;
	
			if (MT[RmNum].Mnstr == 0) {
				//Monster static data file has 26 to choose from
				//**TODO**: 
				// 	Notice: using a fixed number here; this could be the variable M.length 
				//	upgrade to Access a local PouchDB or SQLite database
				//	upgrade to Access a centralized remote database server
				var KeyNum = (Math.round(Math.random()*25))+1;
				MT[RmNum].Mnstr = KeyNum;
				M[KeyNum].Room = RmNum;
				Cntr += 1;
	//			console.log("Room #: "+MT[RmNum].RmID);
	//			console.log("- Mnstr: #"+MT[RmNum].Mnstr);
	//			console.log("- Tresr: $"+MT[RmNum].Tres);
	
			}
		}
		// Place Monsters in the Private Meeting Room and Treasury regardless
		//Forced Debug routine for room 1
		//KeyNum = (Math.round(Math.random()*25))+1;
		//MT[1].Mnstr = KeyNum;
		
		//**TODO**: 
		// 	Notice: using a fixed number here; this
		//		could be substituted with  variable for dynamic adjustments
		KeyNum = (Math.round(Math.random()*25))+1;
		MT[4].Mnstr = KeyNum;
		M[KeyNum].Room = 4;
		KeyNum = (Math.round(Math.random()*20))+6;
		MT[16].Mnstr = KeyNum;
		M[KeyNum].Room = 16;
		//console.log("Room #: "+MT[1].RmID);
		//console.log("- Mnstr: #"+MT[1].Mnstr);
		//console.log("- Tresr: $"+MT[1].Tres);
	//	console.log("Room #: "+MT[4].RmID);
	//	console.log("- Mnstr: #"+MT[4].Mnstr);
	//	console.log("- Tresr: $"+MT[4].Tres);
	//	console.log("Room #: "+MT[16].RmID);
	//	console.log("- Mnstr: #"+MT[16].Mnstr);
	//	console.log("- Tresr: $"+MT[16].Tres);
	//	console.log("=== Monsters Allocated. ===");
	
	},
	
	//
	//====================================================
	//Prep Scene Frame 1
	 _CombatCheck: function(game){
		 //save current game progress when returning from combat state
		GAMEAPP.LastRoom = GAMEAPP.CrntRoom;

		console.log("Room #: "+GAMEAPP.CrntRoom+"; Opponent collision: combat phase.")
		this.camera.fade(0x000000, 200, false);
		this.time.events.add(200, function() {
			//ARRA Combat rv_3 through rv_8; switched statements used
			this.game.state.start('Combat');		
		}, this);
		
	},
	//
	//====================================================
	// Prep Frame 4
	//Develop Character Combat Record 
	 _DevelopCR: function(){  
		//Character CombtRecord Initialized and UPdated prior to combat- ONCE!!!
		Person[1].TotalAP = Number(CCP.TotalAP);
		Person[1].WS = ((Number(CCP.Stmn) * 2) + (Number(CCP.WSRaw) * 5));
		Person[1].BS = ((Number(CCP.Coor) * 2) + (Number(CCP.BSRaw) * 5));
		Person[1].PS = ((Number(CCP.Coor) * 2) + (Number(CCP.WSRaw) * 5));
		Person[1].ModStmn = Number(CCP.ModStmn);
		Person[1].Renown = Number(CCP.Renown);
		//console.log("Char Stats:");
		//console.log("  Total AP: " + Person[1].TotalAP);
		//console.log("        WS: " + Person[1].WS);
		//console.log("        BS: " + Person[1].BS);
		//console.log("        PS: " + Person[1].PS);
		//console.log("   ModStmn: " + Person[1].ModStmn);
	},
	//
	// =========================================================
	_ExitGame: function(){
		//**TODO**: 
		//	redirect your gamers to your destination
		window.open("https://leanpub.com/LoRD", "_blank");
	},
	// =========================================================
	//Main ARRA Entrance Door
	 _knockKnock: function(door){
		
		//debug
		console.log("Room #: "+this.CrntRoom+"; Door Clicked: "+door.name)
	
	},
	//
	// =========================================================
	_InventoryRoom: function(door){
		
		GAMEAPP.LastRoom = GAMEAPP.CrntRoom;
		//debug
		console.log("Room #: "+GAMEAPP.CrntRoom+"; Inventory Clicked: "+door.name);
		//visual sfx
		this.camera.fade(0x000000, 200, false);
		this.time.events.add(200, function() {
			this.game.state.start('Inventory');		//ARRA Inventory Scene rv_3 through rv_8
		}, this);
		
	},
	//
	// =========================================================
	//Prep Scene Frame 1
	// Movement performed
	// Monster moves in opposite direction of Char
	_MoveChar: function (cursor,player){
		//**TODO**:  adjust as required; 
		//	more weight carred results in slower movement?
		//	modifications for race?
		var speed = 250;			//in pixels; 
		player.body.velocity.x = 0;	//in pixels
		player.body.velocity.y = 0;	//in pixels
		//monitor player's movement input
		if (cursor.up.isDown){  
			player.body.velocity.y -= speed;  
		}
		if (cursor.down.isDown){  
			player.body.velocity.y += speed;  
		}
		if (cursor.right.isDown){  
			player.body.velocity.x += speed;  
		}
		if (cursor.left.isDown){  
			player.body.velocity.x -= speed;  
		} 
		
	},
	// 
	// =========================================================
	// Prep Frame 4
	 _MonsterPrep: function(game){
		//**TODO**: 
		// 	Notice: using a fixed number here; this
		//		could be substituted with  variable for dynamic adjustments
		//Equip Monster ONCE per game
		for(var i=1; i<26; i++){
			var Trash = (Math.round(Math.random()*6))+1;
		  //Random Armor Names and TotalAP protection as deductions from damage
			if (Trash == 1){
				M[i].Armor = "Small Shield";
				M[i].TotalAP += 1;
			}
			if ((Trash == 2) || (Trash == 0)){
				M[i].Armor = "Leather Jerkin";
				M[i].TotalAP += 2;
			}
			if (Trash == 3){
				M[i].Armor = "Shield & Leather Jerkin";
				M[i].TotalAP += 3;		
			}
			if (Trash == 4){
				M[i].Armor = "Ring Mail";
				M[i].TotalAP += 3;		
			}
			if (Trash == 5){
				M[i].Armor = "Chain Mail";
				M[i].TotalAP += 3;		
			}
			if (Trash == 6){
				M[i].Armor = "Ring Mail & Shield";
				M[i].TotalAP += 4;
			}
			
			Trash = (Math.round(Math.random()*6))+1;
			//Assign Random Weapons; Weapon Damage is the number of 6-sided dice.
			if (Trash == 1){
				M[i].Weapn = "Small Ax";
				M[i].WDam += 1;
			}
			if ((Trash == 2) || (Trash == 0)){
				M[i].Weapn = "Short Sword";
				M[i].WDam += 2;
			}
			if (Trash == 3){
				M[i].Weapn = "Mace";
				M[i].WDam += 2;
			}
			if (Trash == 4){
				M[i].Weapn = "Cutlass";
				M[i].WDam += 2;
			}
			if (Trash == 5){
				M[i].Weapn = "Long Bow & Sh. Sword";
				M[i].WDam += 2;
			}
			if (Trash == 6){
				M[i].Weapn = "Short Bow & Ax";
				M[i].WDam += 1;
			}
			if(i == 26){
				//Set Wyvern Armor
				M[26].Armor = "Scales";
				M[26].TotalAP = 4;
				//Set Wyvern natural weapons
				M[26].Weapn = "Fangs & Claws";
				M[26].WDam +=3;
			
			}
		}
		
	},
	//
	//====================================================
	//Prep Scene Frame 1
	_MoveMonster: function (cursor,monster){
		//**TODO**:  adjust as required; 
		//	more weight carred results in slower movement?
		//	modifications for race?
		var speed = 250;			//in pixels	  
		monster.body.velocity.x = 0;	//in pixels  
		monster.body.velocity.y = 0;	//in pixels
		if (cursor.up.isDown){  
			monster.body.velocity.y += speed;  
		}
		if (cursor.down.isDown){  
			monster.body.velocity.y -= speed;  
		}
		if (cursor.right.isDown){  
			monster.body.velocity.x -= speed;  
		}
		if (cursor.left.isDown){  
			monster.body.velocity.x += speed;  
		} 
		
	},
	//
	// =========================================================
	_newGame: function(){
		//**TODO**:  adjust as required
		//	redirect gamers to your site for new game
		window.open("https://adventurers-of-renown.com/gameapp/", "_blank");
	},
	//
	// =========================================================
	_playAudio: function(sound) {
		if(GAMEAPP._audioStatus) {
			if(GAMEAPP._sound && GAMEAPP._sound[sound]) {
				GAMEAPP._sound[sound].play();
			}
		}
	},
	// 
	// =========================================================
	_PostMonster: function (game,enemy){
		
		//create an opponent; Check for monster in this room
			if(MT[this.CrntRoom].Mnstr > 0){
				
				this.enemy = this.game.add.sprite(MT[this.CrntRoom].mxPos,MT[this.CrntRoom].myPos,'avatar');
				this.enemy.frameName = String(M[MT[this.CrntRoom].Mnstr].icon+'.bmp');
				this.enemy.body.collideWorldBounds = true;
				this.enemy.enableBody = true;
				this.enemy.body.immovable = true;
				this.game.physics.enable(this.enemy, Phaser.Physics.ARCADE);
				
				this._PUpdate();
				
			}
	},
	//
	// =========================================================
	_PostTres: function (game,Treasure){
		
		if(MT[this.CrntRoom].Tres > 0){
			//**TODO**: store information text in a database for dynamic language conversion.
			InfoText = "There treasure here! See it?!!\n Score: " + CCP.Score;  
			this.Treasure = game.add.sprite(0,0,'avatar');
			this.Treasure.frameName = 'treasure.bmp';
			this.Treasure.body.collideWorldBounds = true;	
			
			//Place Treasure Chest icon mid-way between
			this.Treasure.x = Number((xPos + MT[this.CrntRoom].mxPos)/2);
			this.Treasure.y = Number((yPos + MT[this.CrntRoom].myPos)/2);
			}
			
	},
	//
	// =========================================================
	// Prep Frame 3: Player Updates Combat Record to current stats
	//**TODO**:  adjust as required to deploy array index 1-4 are player(s); 5-8 are antagonsists but could gamer controlled as
	//	single player for Multi-avatar teams; OR
	//	multi-player single avatar controlled
	_PUpdate: function (){
		var CTurnNum = 0;
		GAMEAPP.CmbtTurn = 0;
		GAMEAPP.Narr1 = "";
		GAMEAPP.Narr2 = "";
		//Character UPdated ONCE after Person Combat Record initialized.
		Person[1].TotalAP = Number(CCP.TotalAP);
		Person[1].WS = ((Number(CCP.Stmn) * 2) + (Number(CCP.WSRaw) * 5));
		Person[1].BS = ((Number(CCP.Coor) * 2) + (Number(CCP.BSRaw) * 5));
		Person[1].PS = ((Number(CCP.Coor) * 2) + (Number(CCP.WSRaw) * 5));
		Person[1].ModStmn = Number(CCP.ModStmn);
		Person[1].Renown = Number(CCP.Renown);
	//	console.log("Char Stats Re-read:");
	//	console.log("  Total AP: " + Person[1].TotalAP);
	//	console.log("        WS: " + Person[1].WS);
	//	console.log("        BS: " + Person[1].BS);
	//	console.log("        PS: " + Person[1].PS);
	//	console.log("   ModStmn: " + Person[1].ModStmn);
	
		//Monster UPdates
		//setting Computer controlled antagonist;
		Person[6].TotalAP = (M[MT[this.CrntRoom].Mnstr].TotalAP);
		Person[6].Coor = Number(M[MT[this.CrntRoom].Mnstr].Coor);
		Person[6].Food = Number(M[MT[this.CrntRoom].Mnstr].Food);
		Person[6].Gold = Number(M[MT[this.CrntRoom].Mnstr].HGold);
		Person[6].Gem = Number(M[MT[this.CrntRoom].Mnstr].HGem);
		Person[6].WS = ((Number(M[MT[this.CrntRoom].Mnstr].Stmn) * 2) + (Number(M[MT[this.CrntRoom].Mnstr].WSRaw) * 5));
		Person[6].BS = ((Number(M[MT[this.CrntRoom].Mnstr].Coor) * 2) + (Number(M[MT[this.CrntRoom].Mnstr].BSRaw) * 5));
		Person[6].PS = ((Number(M[MT[this.CrntRoom].Mnstr].Coor) * 2) + (Number(M[MT[this.CrntRoom].Mnstr].WSRaw) * 5));
		Person[6].ModStmn = Number(M[MT[this.CrntRoom].Mnstr].Stmn);
		Person[6].Renown = Number(M[MT[this.CrntRoom].Mnstr].Renown);
	//	console.log("Monster Stats:");
	//	console.log("  Total AP: " + Person[6].TotalAP);
	//	console.log("        WS: " + Person[6].WS);
	//	console.log("        BS: " + Person[6].BS);
	//	console.log("        PS: " + Person[6].PS);
	//	console.log("   ModStmn: " + Person[6].ModStmn);
	//debug
	console.table(Person);
	},
	//
	//====================================================
	_RenownCheck: function (game){
		//**TODO**: store information text in a database for dynamic language conversion.
		//is a monster in this room?
		if (MT[this.CrntRoom].Mnstr > 0){
			//Ran away while monster was still living in the room.
			CCP.Renown -= 1;
			GAMEAPP.InfoText = "Score :"+CCP.TempScore+"\n Running from Combat? \n Renown is " + CCP.Renown;
		}
	},
	// 
	// =========================================================
	_RmAdmin: function (CrntRoom){
					
		//add to avatar experience for Room discovery
		CCP.Score += Number(MT[this.CrntRoom].Discovr);
		MT[this.CrntRoom].Discovr = 0;
				
	},
	// 
	// =========================================================
	//Prep Scene Frame 1
	//**TODO**: store information in a database for dynamic avatar inventory.
	_WeaponClass: function (w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14) {
		this.WID = w1;
		this.Name = w2;
		this.DamPossible = w3;
		this.DamMod = w4;
		this.Cost = w5;
		this.Worth = w6;
		// New property. Current armor value to sell
		this.Weight = w7;
		this.StmnReq = w8;
		this.CoorReq = w9;
		this.Use = w10;
		// 1=One handed; 2=Both hands
		this.Mode = w11;
		// M=Melee;Missle=M;T=Thrown: "MMT"
		this.DamType = w12;
		// Chop=C;Slash=S;Smash=S;Thrust=T: "CSST"
		this.Magic = w13;
		this.Renown = w14;
		this.DamageDone = this._GetWpnDamage();
		// Damage Delt per call
		// Class Inherited Methods:
	}
	// 
	// =========================================================
	// -------------------------------------------
	// End Main game Handler
	// -------------------------------------------
	// =========================================================

	/**
	//TODO: integration
	_labelButton: function(game,x,y,key,label,callback,  
		callbackContext, overFrame, outFrame, downFrame, upFrame){
		Phaser.Button.call(this,game,x,y,key,callback,  
		callbackContext, overFrame, outFrame, downFrame, upFrame);  
		//Style how you wish...    
		this.style = {'font': '10px Arial','fill':'black'};  
		this.anchor.setTo( 0.5, 0.5 );  
		this.label = new Phaser.Text(game, 0, 0, label, this.style);  
		//puts the label in the center of the button  
		this.label.anchor.setTo( 0.5, 0.5 );  
		this.addChild(this.label);  
		this.setLabel( label );  
		//adds button to game  
		game.add.existing( this );  	
	}
	_labelButton.prototype = Object.create(Phaser.Button.prototype);  
	_labelButton.prototype.constructor = _labelButton;  
	_labelButton.prototype.setLabel = function( label ) {  
		this.label.setText(label);  
	}
	*/

};

/** DEPRECATED METHOD - NEVER EVER USE THIS!
* 	See Phaser.js Game Design Workbook for complete explanation
*	https://leanpub.com/phaserjsgamedesignworkbook
* 	window.onload = function () {
*	    let game = new Phaser.Game(0, 0, Phaser.AUTO, document.body);
*	};
*/

//preferred lauch method for BOM.
window.addEventListener('DOMContentLoaded', function(){
	window.GAMEAPP.main();
}, false);

See Examples here


Play Phase

The "play.js" is the "Game Framework Mechanisms" (GFM) Component. It holds the "... all the visual elements ... " of the game. We could replace this file with another and have a "new game" using the same Game Mechanics (GM).

Room States R1.js through R19.js are all similar in construction. Refer to your Bonus Download files for details on each Room State.

/**
 * File Name: R##.js
 * File URL: https://www.adventurers-of-renown.com/GAMEAPP/index.html
 * Description: File for controlling and displaying game entry scenes; managing global variables throughout game state.
 * Author: Stephen Gose
 * Version: 0.0.0.8
 * 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.
 *
 */
"use strict";
window.GAMEAPP.state.R6 = {
	preload: function(){
		console.log("loading Room 6 state");
		GAMEAPP.CrntRoom = 6;
		this.game.load.image('R6', 'assets/images/staticRooms/R6.jpg');
		this.game.load.atlas('doorButton','assets/images/doors/Doors.png','assets/images/doors/Doors.json');
		this.game.load.atlas('avatar','assets/icons/arraIcons.png','assets/icons/arraIcons.json');
		this.game.load.atlas('tres','assets/icons/arraIcons.png','assets/icons/arraIcons.json');
		this.load.spritesheet('button', 'assets/spriteSheets/mmog-sprites-silver.png', 129, 30);
		this.load.atlas('inventoryButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.atlas('exitButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.atlas('fightButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');
		this.load.atlas('talkButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json');

	},
	
	create: function(){
		console.log("creating Room 6 state");
		this.game.add.image(0, 0, 'R6');
		var rect = new Phaser.Rectangle(90, 100, 200, 200);
		//Set a neutral background color
		this.game.stage.backgroundColor = "#000";
		//Set game to ARCADE physics systemLanguage
		this.game.physics.startSystem(Phaser.Physics.ARCADE);
		this.game.renderer.renderSession.roundPixels = true;
		this.game.world.enableBody = true;
		
		//Create Room
		this.Room = this.game.add.group();  
		this.Room.enableBody = true; 
		this.game.physics.enable(this.Room, Phaser.Physics.ARCADE);

		this.NorthWall = this.game.add.sprite(90,110,box({length:190,width:16,color:'#999'}));	
		this.NorthWall.enableBody = true;
		this.NorthWall.body.immovable = true;
		this.NorthWall.visible = false;
		this.Room.add(this.NorthWall);
		this.NorthWall.alignTo(rect, Phaser.TOP_CENTER);
		
		this.SouthWall = this.game.add.sprite(0,200,box({length:190,width:16,color:'#999'}));
		this.SouthWall.body.immovable = true;
		this.SouthWall.visible = false;
		this.Room.add(this.SouthWall);
		this.SouthWall.alignTo(rect, Phaser.BOTTOM_CENTER);
		
		this.WestWall = this.game.add.sprite(200,16,box({length:16,width:190,color:'#999'}));
		this.WestWall.body.immovable = true;
		this.WestWall.visible = false;
		this.Room.add(this.WestWall);
		this.WestWall.alignTo(rect, Phaser.RIGHT_CENTER);
		
		this.EastWall = this.game.add.sprite(90,16,box({length:16,width:190,color:'#999'}));
		this.EastWall.body.immovable = true;
		this.EastWall.visible = false;
		this.Room.add(this.EastWall);
		this.EastWall.alignTo(rect, Phaser.LEFT_CENTER);

		//Main Entrance Doors
		var Entrance = this.game.add.sprite(90,120,'doorButton'); //perfectly aligned over placeholder
		Entrance.name = "Main Entrance";
		Entrance.frameName = 'mainEntrance.jpg';
		Entrance.body.immovable = true;
		Entrance.inputEnabled = true;
		
		Entrance.events.onInputDown.add(this.newRoom, this);
		//insert into RoomGroup
		this.Room.add(Entrance);
		
		//create treasure if needed; check for treasure in this room
		if(MT[GAMEAPP.CrntRoom].Tres > 0){
			GAMEAPP.InfoText = "Score: "+CCP.Score+"\n Click on the Door to enter.\nThere treasure here! See it?!!";
			this.Treasure = this.game.add.sprite(200,200,'tres');
			this.Treasure.frameName = 'treasure.bmp';
			this.Treasure.body.collideWorldBounds = true;
			this.Treasure.enableBody = true;
			this.Treasure.body.immovable = true;
			this.Treasure.inputEnabled = true;
			this.game.physics.enable(this.Treasure, Phaser.Physics.ARCADE);
			//clicking treasure for mobile interaction
			this.Treasure.events.onInputDown.add(this.CTreasure, this);
			this.Treasure.alignIn(rect, Phaser.BOTTOM_CENTER);
			
		}
		
		this.inventorytxt = this.game.add.text(0, 0, "Inventory" , GAMEAPP.styleBTN);	
		this.exittxt = this.game.add.text(0, 0, "Exit" , GAMEAPP.styleBTN);	
		this._toolTip = this.game.add.text(this.game.world.width-100, this.game.world.height-90, GAMEAPP.InfoText, GAMEAPP.styleTT);
		this._toolTip.anchor.set(0.5);
		GAMEAPP.RoomAlert = "";
		
		// Inventory button 
		this.inventoryButton = this.game.add.button(65, 338, 'button', GAMEAPP._InventoryRoom, this, 2, 1, 0,1);
		this.inventoryButton.anchor.set(0.5,0.5);
		this.inventoryButton.scale.setTo(0.5,0.5);
		this.inventoryButton.addChild(this.inventorytxt).anchor.set(0.5,0.5);
		
		// Exit button 
		this.exitButton = this.game.add.button(65, 361, 'button', GAMEAPP._ExitGame, this, 2, 1, 0,1);
		this.exitButton.anchor.set(0.5,0.5);
		this.exitButton.scale.setTo(0.5,0.5);
		this.exitButton.addChild(this.exittxt).anchor.set(0.5,0.5);
		
		//create an opponent; Check for monster in this room
		if(MT[GAMEAPP.CrntRoom].Mnstr > 0){
			GAMEAPP.RoomAlert = "Beware, a " + M[MT[GAMEAPP.CrntRoom].Mnstr].Race + " is here!"
			GAMEAPP.raTxt = this.game.add.text(this.game.world.width-268, 65, GAMEAPP.RoomAlert, GAMEAPP.styleRA);
			GAMEAPP.raTxt.anchor.set(0);
			this.enemy = this.game.add.sprite(MT[GAMEAPP.CrntRoom].mxPos,MT[GAMEAPP.CrntRoom].myPos,'avatar');
			this.enemy.frameName = String(M[MT[GAMEAPP.CrntRoom].Mnstr].icon+'.bmp');
			this.enemy.body.collideWorldBounds = true;
			this.game.physics.enable(this.enemy, Phaser.Physics.ARCADE);
		
			this.enemy.alignIn(rect, Phaser.RIGHT_CENTER);
			
			GAMEAPP._PUpdate();
			//clicking fight for mobile interaction
			// Fight button 
			this.fighttxt = this.game.add.text(0, 0, "Fight" , GAMEAPP.styleBTN);
			this.fightButton = this.game.add.button(152, 338, 'button', GAMEAPP._CombatCheck, this, 2, 1, 0,1);
			this.fightButton.anchor.set(0.5,0.5);
			this.fightButton.scale.setTo(0.5,0.5);
			this.fightButton.addChild(this.fighttxt).anchor.set(0.5,0.5);
			
			// Talk button 
			var talktxt = this.game.add.text(0, 0, "Talk" , GAMEAPP.styleBTN);
			var talkButton = this.game.add.button(152, 361, 'button', this._talkToMonster, this, 2, 1, 0,1);
			talkButton.anchor.set(0.5,0.5);
			talkButton.scale.setTo(0.5,0.5);
			talkButton.addChild(talktxt).anchor.set(0.5,0.5);
		}
			
		GAMEAPP._RmAdmin(GAMEAPP.CrntRoom);
		
		//place character
		this.player = this.game.add.sprite(GAMEAPP.xPos,GAMEAPP.yPos,'avatar');
		this.player.frameName = 'avatar.bmp';
		this.player.body.collideWorldBounds = true;	
		this.cursor = this.game.input.keyboard.createCursorKeys();
		this.player.alignIn(rect, Phaser.LEFT_CENTER);

	},
	
	update: function(){
		GAMEAPP._MoveChar(this.cursor,this.player);
		this.game.physics.arcade.collide(this.player, this.Room);
		
		//Check for monster in this room
		if (MT[GAMEAPP.CrntRoom].Mnstr > 0) {
			GAMEAPP._MoveMonster(this.cursor,this.enemy);
			this.game.physics.arcade.collide(this.enemy, this.Room);
			this.game.physics.arcade.overlap(this.player,this.enemy,GAMEAPP._CombatCheck,null,this); 
					
		}
		//Check for treasure in this room
		if (MT[GAMEAPP.CrntRoom].Tres > 0) {
			
			this.game.physics.arcade.collide(this.player,this.Treasure,this.CTreasure,null,this); 
			
		}
		this._toolTip.setText(GAMEAPP.InfoText);
	},
	//
	// =========================================================
	//Main ARRA Door click handler.
	//  it is an exception use case
	newRoom: function(door){
		GAMEAPP.LastRoom = GAMEAPP.CrntRoom;
		GAMEAPP.LastDoor = door.name;
		console.log('Last Door Used: '+GAMEAPP.LastDoor);
		
		//debug
		console.log("New Room #: "+GAMEAPP.CrntRoom+"; Door Clicked: "+door.name);
		
		this.camera.fade(0x000000, 200, false);
		this.time.events.add(200, function() {
			this.game.state.start('R'+MT[GAMEAPP.LastRoom].East);		//ARRA Main Entrance (hard coded) rv_3 through rv_8
		}, this);
		
	},
	//
	//====================================================
	_talkToMonster: function(){
		GAMEAPP.InfoText = "... mmm, not in the mood to negotiate?!";
	},
	//
	//====================================================
	CTreasure: function(){
		CCP.HGold += MT[GAMEAPP.CrntRoom].Tres;
		this.Treasure.kill();
		GAMEAPP.InfoText = "You found $"+MT[GAMEAPP.CrntRoom].Tres+" in the chest.";
		MT[GAMEAPP.CrntRoom].Tres = 0;
		this._toolTip.setText("You found $"+MT[GAMEAPP.CrntRoom].Tres+" in the chest."); 
	}
};
	//
	// =========================================================
	//create a box Image (pseudo graphics) for the HTML5 canvas. 
	var box = function(options) {  
		var bxImg = GAMEAPP.game.add.bitmapData(options.length,options.width);  
		bxImg.ctx.beginPath();  
		bxImg.ctx.rect(0,0,options.length,options.width);  
		bxImg.ctx.fillStyle = options.color;  
		bxImg.ctx.fill();  
		return bxImg;  
	};

See Examples here


Story.js (13kB)

/**
 * File Name: story.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.8
 * 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 Game Prototype preloader immediate game resources ", "color:white; background:red");
		console.log("%c  Starting my awesome MMoG game Prototype!       \n  | https://renown-games.com/shop |                    \n  | \u2665\u2665\u2665\u2665\u2665 -> $120 License included in book!      \n  | Book available at: https://leanpub.com/LoRD | ",
	"color:white; background:blue");
		this.game.load.image('story', 'assets/images/staticRooms/story.jpg');
		//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  state");
		this.game.add.image(0, 0, 'story');
		var buttonContinue = this.add.button(this.world.width, this.world.height-100, 'button-continue', this.clickContinue, this, 1, 0, 2);
		
		buttonContinue.anchor.set(1,1);
		buttonContinue.x = this.world.width+buttonContinue.width+20;
		
		this.add.tween(buttonContinue).to({x: this.world.width-20}, 500, Phaser.Easing.Exponential.Out, true);

		this.camera.flash(0x000000, 500, false);
	},
	
	update: function(){
		
	},
	
	clickContinue: function() {
		GAMEAPP._playAudio('click');
		this.camera.fade(0x000000, 200, false);
		this.time.events.add(200, function() {
			//this.game.state.start('Main');	//BBS & Flash website: TIGStart method
			this.game.state.start('R6');		//ARRA Main Entrance rv_3 through rv_8
		}, this);
		
	},
	
	_preloadResources() {
	var pack = this.resources;
		for(var method in pack) {
			pack[method].forEach(function(args) {
				var loader = this.load[method];
				loader && loader.apply(this.load, args);
			}, this);
		}
	}
};

//internal static; JSON game resources
this.resources = {
	'image':[
		['button', 'assets/spriteSheets/mmog-sprites-silver.png', 129, 30],
		['combat', 'assets/images/staticRooms/combat.jpg'],
		['Inventory', 'assets/images/staticRooms/inventory.jpg'],
		['R1', 'assets/images/staticRooms/R1.jpg'],
		['R2', 'assets/images/staticRooms/R2.jpg'],
		['R3', 'assets/images/staticRooms/R3.jpg'],
		['R4', 'assets/images/staticRooms/R4.jpg'],
		['R5', 'assets/images/staticRooms/R5.jpg'],
		['R6', 'assets/images/staticRooms/R6.jpg'],
		['R7', 'assets/images/staticRooms/R7.jpg'],
		['R8', 'assets/images/staticRooms/R8.jpg'],
		['R9', 'assets/images/staticRooms/R9.jpg'],
		['R10', 'assets/images/staticRooms/R10.jpg'],
		['R11', 'assets/images/staticRooms/R11.jpg'],
		['R12', 'assets/images/staticRooms/R12.jpg'],
		['R13', 'assets/images/staticRooms/R13.jpg'],
		['R14', 'assets/images/staticRooms/R14.jpg'],
		['R15', 'assets/images/staticRooms/R15.jpg'],
		['R16', 'assets/images/staticRooms/R16.jpg'],
		['R17', 'assets/images/staticRooms/R17.jpg'],
		['R18', 'assets/images/staticRooms/R18.jpg'],
		['R19', 'assets/images/staticRooms/R19.jpg']
	],
	'spritesheet':[
		['button', 'assets/spriteSheets/mmog-sprites-silver.png', 129, 30],
	],
	'atlas':[
		['soundButton','assets/spriteSheets/soundButton.png','assets/spriteSheets/mmm-soundButton.json'],
		['button-continue','assets/spriteSheets/RightArrow-Phaser.png','assets/spriteSheets/arrowR-sprites.json'],
		['aboutUsButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['creditButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['donaButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['gameOverButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['helpButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['moreButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['optButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['playButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['scoresButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['shareButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['webButton','assets/spriteSheets/mmog-sprites-silver.png','assets/spriteSheets/mmog-sprites.json'],
		['ARRADeath','assets/spriteSheets/ARRADeath/ARRADeath.png','assets/spriteSheets/ARRADeath/ARRADeath.json'],
		['avatar','assets/icons/arraIcons.png','assets/icons/arraIcons.json'],
		['doorButton','assets/images/doors/Doors.png','assets/images/doors/Doors.json']
		
	],
	'audio':[
		['audio-theme',['assets/audio/yewtree.mp3','assets/audio/yewtree.ogg']]
	]
};

See Examples here

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