Browse Source

* Removed framework Phaser from iFractions
** new file /js/gameMechanics.js handles the things that Phaser used to do for the code, such as:
*** loading media: language and audio (fetch API), image and spritesheet (HTMLImageElement)
*** media manipulation and adding it on screen (canvas element)
*** adding geometric figures on screen: rectangle, arc (canvas element)
*** providing necessary mathematical functions
*** timer
*** button event handler (click, mouseIn, mouseOut)
*** gameloop
*** spritesheet animation
*** P.s.: without phaser states, the guidelines to creating new code has changed (soon documentation will be available)

* Bug fix:
** in the 'mixed' sublevel of the 'circleOne' game, there was a bug where there were only circles that went right
** in the 'squareOne' game, sublevel 'A', if player clicked on first square on the floor the animation wouldnt behave as expected
** changed fixed urls on the code (language and audio urls)

* GUI change:
** help pointer was resized
** change in darkblue color
** some GUI elements that were images, now are canvas elements (fraction lines, loader in map - loading bar and rectangle around it)
** cleaned some smudges in some game images
** darkened audio icon that was lighter than other icons
** fixed some spritesheets that werent being cut correctly in code due to inconsistent dimensions (tractor and kid)

* Directory / file change:
** reorganized some directory names in /assets/img/
** removed /js/boot.js

* Other:
** added an fluxogram as a comment to help understand the game/level/sublevel/difficulty names
** some code refactoring

laira 4 years ago
parent
commit
36b637c257
72 changed files with 2991 additions and 105252 deletions
  1. 0 0
      assets/img/NOT-USED/block.png
  2. 0 0
      assets/img/NOT-USED/fractionLine.png
  3. 0 0
      assets/img/NOT-USED/pgbar.png
  4. 0 0
      assets/img/NOT-USED/progressBar.png
  5. BIN
      assets/img/character/kid/run.png
  6. BIN
      assets/img/character/kid/walk.png
  7. BIN
      assets/img/character/tractor/frame.png
  8. BIN
      assets/img/character/tractor/tractor.png
  9. 0 0
      assets/img/interac_icon/down.png
  10. 0 0
      assets/img/interac_icon/error.png
  11. 0 0
      assets/img/interac_icon/ok.png
  12. 0 0
      assets/img/interac_icon/pointer.png
  13. 0 0
      assets/img/interac_icon/selectionBox.png
  14. 0 0
      assets/img/levels/backup/circleOne_1.png
  15. 0 0
      assets/img/levels/backup/circleOne_2.png
  16. 0 0
      assets/img/levels/backup/levels_v1.psd
  17. 0 0
      assets/img/levels/backup/levels_v2.psd
  18. 0 0
      assets/img/levels/backup/squareOne_1.png
  19. 0 0
      assets/img/levels/backup/squareOne_2.png
  20. 0 0
      assets/img/levels/backup/squareTwo_3.png
  21. 0 0
      assets/img/levels/circleOne_1.png
  22. 0 0
      assets/img/levels/circleOne_2.png
  23. 0 0
      assets/img/levels/squareOne_1.png
  24. 0 0
      assets/img/levels/squareOne_2.png
  25. 0 0
      assets/img/levels/squareTwo_3.png
  26. BIN
      assets/img/navIcon/audio_48x48.png
  27. BIN
      assets/img/navig_icon/audio.png
  28. 0 0
      assets/img/navig_icon/back.png
  29. 0 0
      assets/img/navig_icon/help.png
  30. 0 0
      assets/img/navig_icon/home.png
  31. 0 0
      assets/img/navig_icon/language.png
  32. 0 0
      assets/img/navig_icon/menu.png
  33. 0 0
      assets/img/non_interac_icon/double.png
  34. 0 0
      assets/img/non_interac_icon/equal.png
  35. BIN
      assets/img/non_interac_icon/left_arrow.png
  36. 0 0
      assets/img/non_interac_icon/right_arrow.png
  37. BIN
      assets/img/scenario/tree4.png
  38. 0 0
      assets/img/scene/bg.jpg
  39. 0 0
      assets/img/scene/bg_map.png
  40. 0 0
      assets/img/scene/bush.png
  41. 0 0
      assets/img/scene/cloud.png
  42. 0 0
      assets/img/scene/farm.png
  43. 0 0
      assets/img/scene/flag.png
  44. 0 0
      assets/img/scene/floor.png
  45. 0 0
      assets/img/scene/garage.png
  46. 0 0
      assets/img/scene/house.png
  47. 0 0
      assets/img/scene/place.png
  48. 0 0
      assets/img/scene/place_off.png
  49. 0 0
      assets/img/scene/place_on.png
  50. 0 0
      assets/img/scene/road.png
  51. 0 0
      assets/img/scene/rock.png
  52. 0 0
      assets/img/scene/school.png
  53. 0 0
      assets/img/scene/sign.png
  54. 0 0
      assets/img/scene/tree.png
  55. 0 0
      assets/img/scene/tree2.png
  56. 0 0
      assets/img/scene/tree3.png
  57. BIN
      assets/img/scene/tree4.png
  58. 39 20
      index.html
  59. 0 85
      js/boot.js
  60. 377 381
      js/circleOne.js
  61. 200 200
      js/difficulty.js
  62. 783 0
      js/gameMechanics.js
  63. 218 282
      js/globals.js
  64. 261 212
      js/map.js
  65. 114 109
      js/menu.js
  66. 0 103065
      js/phaser/phaser.js
  67. 0 1
      js/phaser/phaser.map
  68. 0 28
      js/phaser/phaser.min.js
  69. 223 74
      js/preMenu.js
  70. 498 436
      js/squareOne.js
  71. 271 353
      js/squareTwo.js
  72. 7 6
      php/save.php

assets/img/navIcon/block.png → assets/img/NOT-USED/block.png


assets/img/operator/fractionLine.png → assets/img/NOT-USED/fractionLine.png


assets/img/scenario/pgbar.png → assets/img/NOT-USED/pgbar.png


assets/img/navIcon/progressBar.png → assets/img/NOT-USED/progressBar.png


BIN
assets/img/character/kid/run.png


BIN
assets/img/character/kid/walk.png


BIN
assets/img/character/tractor/frame.png


BIN
assets/img/character/tractor/tractor.png


assets/img/help/down.png → assets/img/interac_icon/down.png


assets/img/help/error.png → assets/img/interac_icon/error.png


assets/img/help/ok.png → assets/img/interac_icon/ok.png


assets/img/help/pointer.png → assets/img/interac_icon/pointer.png


assets/img/help/selectionBox.png → assets/img/interac_icon/selectionBox.png


assets/img/game/backup/circleOne_1.png → assets/img/levels/backup/circleOne_1.png


assets/img/game/backup/circleOne_2.png → assets/img/levels/backup/circleOne_2.png


assets/img/game/backup/fases projeto 1.0.psd → assets/img/levels/backup/levels_v1.psd


assets/img/game/backup/fases projeto 2.0.psd → assets/img/levels/backup/levels_v2.psd


assets/img/game/backup/squareOne_1.png → assets/img/levels/backup/squareOne_1.png


assets/img/game/backup/squareOne_2.png → assets/img/levels/backup/squareOne_2.png


assets/img/game/backup/squareTwo_3.png → assets/img/levels/backup/squareTwo_3.png


assets/img/game/circleOne_1.png → assets/img/levels/circleOne_1.png


assets/img/game/circleOne_2.png → assets/img/levels/circleOne_2.png


assets/img/game/squareOne_1.png → assets/img/levels/squareOne_1.png


assets/img/game/squareOne_2.png → assets/img/levels/squareOne_2.png


assets/img/game/squareTwo_3.png → assets/img/levels/squareTwo_3.png


BIN
assets/img/navIcon/audio_48x48.png


BIN
assets/img/navig_icon/audio.png


assets/img/navIcon/back.png → assets/img/navig_icon/back.png


assets/img/navIcon/help.png → assets/img/navig_icon/help.png


assets/img/navIcon/home.png → assets/img/navig_icon/home.png


assets/img/navIcon/language.png → assets/img/navig_icon/language.png


assets/img/navIcon/menu.png → assets/img/navig_icon/menu.png


assets/img/help/double.png → assets/img/non_interac_icon/double.png


assets/img/operator/equal.png → assets/img/non_interac_icon/equal.png


BIN
assets/img/non_interac_icon/left_arrow.png


assets/img/help/arrow.png → assets/img/non_interac_icon/right_arrow.png


BIN
assets/img/scenario/tree4.png


assets/img/scenario/bg.jpg → assets/img/scene/bg.jpg


assets/img/scenario/bg_map.png → assets/img/scene/bg_map.png


assets/img/scenario/birch.png → assets/img/scene/bush.png


assets/img/scenario/cloud.png → assets/img/scene/cloud.png


assets/img/scenario/farm.png → assets/img/scene/farm.png


assets/img/scenario/flag.png → assets/img/scene/flag.png


assets/img/scenario/floor.png → assets/img/scene/floor.png


assets/img/scenario/garage.png → assets/img/scene/garage.png


assets/img/scenario/house.png → assets/img/scene/house.png


assets/img/scenario/place.png → assets/img/scene/place.png


assets/img/scenario/place_a.png → assets/img/scene/place_off.png


assets/img/scenario/place_b.png → assets/img/scene/place_on.png


assets/img/scenario/road.png → assets/img/scene/road.png


assets/img/scenario/rock.png → assets/img/scene/rock.png


assets/img/scenario/school.png → assets/img/scene/school.png


assets/img/scenario/sign.png → assets/img/scene/sign.png


assets/img/scenario/tree.png → assets/img/scene/tree.png


assets/img/scenario/tree2.png → assets/img/scene/tree2.png


assets/img/scenario/tree3.png → assets/img/scene/tree3.png


BIN
assets/img/scene/tree4.png


+ 39 - 20
index.html

@@ -7,22 +7,9 @@
 	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 	<meta name="description" content="Educational game for teaching fractions" />
 	<meta name="keywords" content="ifractions, fraction, game" />
-	<link rel="shortcut icon" href="assets/img/scenario/flag.png">
+	<link rel="shortcut icon" href="assets/img/scene/flag.png">
 	<title> iFractions </title>
-	<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
-
-	<script src="js/phaser/phaser.min.js"></script>
-
-	<script type="text/javascript" src="js/preMenu.js"></script>
-	<script type="text/javascript" src="js/menu.js"></script>
-	<script type="text/javascript" src="js/difficulty.js"></script>
-	<script type="text/javascript" src="js/map.js"></script>
-	<script type="text/javascript" src="js/circleOne.js"></script>
-	<script type="text/javascript" src="js/squareOne.js"></script>
-	<script type="text/javascript" src="js/squareTwo.js"></script>
-	<script type="text/javascript" src="js/globals.js"></script>
-
-	<script type="text/javascript" src="js/boot.js"></script>
+	<link rel="stylesheet" href="css/bootstrap.min.css">
 
 	<style>
 		#text-field {
@@ -33,19 +20,25 @@
 		}
 
 		input[type=text] {
-			background-color: rgb(239, 245, 245);
+			background-color: #fff;
 			padding: 15px 40px;
 			box-sizing: border-box;
 			border: 3px solid #ccc;
 			font-size: 44px;
 			font-family: Arial;
-			color: rgb(0, 0, 0);
+			color: #000;
 			text-align: center;
 		}
 
 		input:focus {
 			outline: 3px solid #85accc;
 		}
+
+		#iFractions-canvas {
+			padding: 0 auto 0 auto;
+			border: solid 3px #fff;
+		}
+
 	</style>
 
 </head>
@@ -57,13 +50,15 @@
 		<div class="clearfix"></div>
 
 		<div class="panel panel-primary">
-			<div class="panel-heading">IFRACTIONS GAME</div>
+		<div class="panel-heading">IFRACTIONS GAME</div>
 			<div class="panel-body">
-				<!-- fractions-game é o id que puxa o canvas do phaser -->
-				<div id="fractions-game" style="padding: 0 auto 0 auto;"></div>
+				<!-- iFractions game -->
+				<canvas id="iFractions-canvas"></canvas>
 			</div>
 		</div>
 
+		<div id="div-fps"><!-- display frames per second--></div>
+
 		<div class="panel panel-info">
 			<div class="panel-heading">TEAM</div>
 			<div class="panel-body text-center">
@@ -105,6 +100,30 @@
 
 	</div>
 
+	<script src="js/preMenu.js"></script>
+	<script src="js/menu.js"></script>
+	<script src="js/difficulty.js"></script>
+	<script src="js/map.js"></script>
+	<script src="js/circleOne.js"></script>
+	<script src="js/squareOne.js"></script>
+	<script src="js/squareTwo.js"></script>
+	<script src="js/globals.js"></script>
+	<script src="js/gameMechanics.js"></script>
+
+	<script>
+		
+		const displayFps = document.getElementById("div-fps");
+
+		const canvas = document.getElementById("iFractions-canvas");
+		canvas.width = defaultWidth; 
+		canvas.height = defaultHeight;
+
+		const context = canvas.getContext("2d");
+
+		boot.preload();
+	
+	</script>
+
 </body>
 
 </html>

+ 0 - 85
js/boot.js

@@ -1,85 +0,0 @@
-// Start phaser
-const game = new Phaser.Game(
-	defaultWidth,
-	defaultHeight,
-	Phaser.CANVAS,
-	'fractions-game'
-);
-
-// Game state : preload progress bar icon to use while preloading game assets
-
-let loadProgressBar = {
-	preload: function () {
-		game.load.image('progressBar', imgsrc + 'scenario/pgbar.png');
-	},
-	create: function () {
-		game.state.start('loadAssets');
-	}
-};
-
-// Game state : Load assets (and calls first game screen)
-
-let loadAssets = {
-
-	preload: function () {
-
-		// Create progress bar
-		const progressBar = game.add.sprite(game.world.centerX, game.world.centerY, 'progressBar');
-		progressBar.anchor.setTo(0.5, 0.5);
-		// Executes progress bar untill the end of preload function
-		game.load.setPreloadSprite(progressBar);
-
-		// Sets default background color (persistent through screen changes)
-		game.stage.backgroundColor = colors.blueBckg;
-
-		// Loading assets
-
-		loadAudios(media.boot('audio'));
-
-		for (let i = 0, image = media.boot('image'); i < image.length; i++) {
-			game.load.image(image[i][0], image[i][1]);
-		}
-
-		for (let i = 0, sprite = media.boot('spritesheet'); i < sprite.length; i++) {
-			game.load.spritesheet(sprite[i][0], sprite[i][1], sprite[i][2], sprite[i][3], sprite[i][4]);
-		}
-
-
-	},
-
-	create: function () {
-
-		// Centers phaser canvas in its containing div
-		game.scaleMode = Phaser.ScaleManager.SHOW_ALL;
-		game.scale.pageAlignHorizontally = true;
-		game.scale.pageAlignVertically = true;
-
-		// Enable phaser Arcade Physics system
-		game.physics.startSystem(Phaser.Physics.ARCADE);
-
-		// Calls first screen seen by the player
-		game.state.start('language');
-
-	}
-
-};
-
-// Adding game states
-
-game.state.add('language', langState); // preMenu.js
-game.state.add('load', loadState); // preMenu.js
-game.state.add('name', nameState); // preMenu.js
-game.state.add('menu', menuState); // menu.js
-game.state.add('map', mapState); // map.js
-game.state.add('end', endState); // map.js
-game.state.add('difficulty', difficultyState); // difficulty.js
-game.state.add('gameCircleOne', gameCircleOne); // circleOne.js
-game.state.add('gameSquareOne', gameSquareOne); // squareOne.js
-game.state.add('gameSquareTwo', gameSquareTwo); // squareTwo.js
-game.state.add('loadProgressBar', loadProgressBar); // boot.js
-game.state.add('loadAssets', loadAssets); // boot.js
-
-// Calls first game state
-
-game.state.start('loadProgressBar');
-

File diff suppressed because it is too large
+ 377 - 381
js/circleOne.js


+ 200 - 200
js/difficulty.js

@@ -1,297 +1,297 @@
-/*
-    let difficultyState = {
-        preload: function(){},
-        create: function(){},
-        ---------------------------- end of phaser functions
-        func_loadMap: function()
-        func_setLabel: function()
-    };
-*/
-
 // DIFFICULTY SCREEN: player can select (I) sublevel type, (II) game difficulty and (III) turn on/off fractions labels
-let difficultyState = {
+const difficultyScreen = {
 
     preload: function () {
 
-        let curMedia;
+        document.body.style.cursor = "auto";
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
 
-        switch (currentGameState) {
-            case 'gameSquareOne': curMedia = media.gameSquareOne; break;
-            case 'gameSquareTwo': curMedia = media.gameSquareTwo; break;
-            case 'gameCircleOne': curMedia = media.gameCircleOne; break;
-        }
+        self = this;
 
-        for (let i = 0, image = curMedia('image'); i < image.length; i++) {
-            game.load.image(image[i][0], image[i][1]);
-        }
-        for (let i = 0, sprite = curMedia('spritesheet'); i < sprite.length; i++) {
-            game.load.spritesheet(sprite[i][0], sprite[i][1], sprite[i][2], sprite[i][3], sprite[i][4]);
-        }
-        for (let i = 0, audio = curMedia('audio'); i < audio.length; i++) {
-            game.load.audio(audio[i][0], audio[i][1][0], audio[i][1][1]);
-        }
+        // LOADING MEDIA
+        game.load.sprite(game.url[gameTypeString].sprite);
+        game.load.image(game.url[gameTypeString].image);
 
     },
 
     create: function () {
 
+        game.render.clear();
+
+        // Background color
+        game.add.graphic.rect(0, 0, 900, 600, colors.white, 0, colors.blueBckg, 1);
+
         // Calls function that loads navigation icons
-        iconSettings.func_addIcons(true, true,
-            false, true, false,
+        navigationIcons.func_addIcons(false, true, false,
             true, false,
             false, false);
 
-        // TITLE
+        // Title
+        game.add.text(defaultWidth / 2, 40, game.lang.game_menu_title, textStyles.title2);
 
-        const title = game.add.text(game.world.centerX, 40, lang.game_menu_title, textStyles.title2);
-        title.anchor.setTo(0.5, 0.5);
+        // Icon that turns fraction labels ON/OFF
+        if (gameTypeString != 'squareTwo') {
 
-        // TURN LABEL ON/OFF ICON
+            const frame = (fractionLabel) ? 1 : 0;
 
-        if (currentGameState != 'gameSquareTwo') {
             // Text : 'with/without' labeling the fractions
-            let labelText = game.add.text(game.world.centerX - 110, 80, "", textStyles.subtitle2);
-            labelText.text = levelLabel ? lang.with_name + " " + lang.label_name : lang.without_name + " " + lang.label_name;
-            labelText.anchor.setTo(0, 0.5);
+            this.labelText = game.add.text(defaultWidth / 2 - 100, 105, "", textStyles.subtitle2l);
+            this.labelText.name = fractionLabel ? game.lang.with_name + " " + game.lang.label_name : game.lang.without_name + " " + game.lang.label_name;
             // Selection box
-            let selectionBox = game.add.sprite(game.world.centerX - 110 - 30, 75, 'select');
-            selectionBox.frame = levelLabel ? 1 : 0;
-            selectionBox.anchor.setTo(0.5, 0.5);
-            selectionBox.scale.setTo(0.12);
-            selectionBox.inputEnabled = true;
-            selectionBox.input.useHandCursor = true;
-            selectionBox.events.onInputDown.add(this.func_setLabel, { selectionBox: selectionBox, labelText: labelText });
+            this.selectionBox = game.add.sprite(defaultWidth / 2 - 110 - 30, 75, 'select', frame, 0.12);
         }
 
         // SETTING DIFFICULTY LEVELS (STAIR)
 
+        this.stairs = [];
+
         const maxStairHeight = 120;  // Maximum height of the stairs        
+
         let stairHeight;    // Height growth of a stair
         let stairWidth;     // Width of the stairs
-        let startStair;     // Start 'x' position of the stairs
-        let startTheme;     // Start 'x' position of the illustrations on the left (character/arrow/equal sign)
-        let startShape;     // STart 'x' position of the illustrations on the right (shapes)
-        let maxSublevel;
-        let maxDifficulty;
-
-        switch (currentGameState) {
-            case "gameSquareOne":
+
+        let maxSublevel;    // number of sublevels
+        let maxDifficulty;  // Number of difficulty stairs (in each sublevel)
+
+        let xTheme;     // Start 'x' position of the illustrations on the left (theme: character/arrow/equalSign)
+        let xStair;     // Start 'x' position of the stairs
+        let xShape;     // Start 'x' position of the illustrations on the right (shapes)
+
+        switch (gameTypeString) {
+            case "squareOne":
                 stairHeight = 40;
                 stairWidth = 100;
-                startStair = 320;
-                startTheme = 180;
-                startShape = (startTheme / 2) + startStair + stairWidth * 3;
                 maxSublevel = 2;
                 maxDifficulty = 3;
+                xTheme = 180;
+                xStair = 320;
+                xShape = (xTheme / 2) + xStair + stairWidth * maxDifficulty;
                 break;
-            case "gameSquareTwo":
-            case "gameCircleOne":
+            case "squareTwo":
+            case "circleOne":
                 stairHeight = 29;
                 stairWidth = 85;
-                startStair = 240;
-                startTheme = 150;
-                startShape = (startTheme / 2) + startStair + stairWidth * 5;
                 maxSublevel = 3;
                 maxDifficulty = 5;
+                xTheme = 150;
+                xStair = 240;
+                xShape = (xTheme / 2) + xStair + stairWidth * maxDifficulty;
                 break;
-            default: if (debugMode) console.log("Error! Name of the game state is not valid!");
-        }
-
-        let themeIcons = [];
-        let arrowIcons = [];
-        let shapeIcons = [];
-
-        let stairs = [];
-
-        const aux = {
-            maxSublevel: null,
-            maxDifficulty: null,
-            color: [colors.diffBlue, colors.diffRed, colors.diffPurple],
-            base_y1: [135, 285, 435],
-            sublevel_1: ['Plus', 'Minus', 'Mixed'],
-            sublevel_2: ['A', 'B', 'C'],
-            get sublevel() {
-                return (currentGameState == 'gameSquareTwo') ? this.sublevel_2 : this.sublevel_1;
-            },
         }
 
         // Placing icons
-        switch (currentGameState) {
+        switch (gameTypeString) {
 
-            case "gameSquareOne":
+            case "squareOne":
 
                 // Blue square
-                shapeIcons[0] = game.add.graphics(startShape, 175);
-                shapeIcons[0].anchor.setTo(0.5, 0.5);
-                shapeIcons[0].lineStyle(2, colors.darkBlue);
-                shapeIcons[0].beginFill(colors.lightBlue);
-                shapeIcons[0].drawRect(0, 0, 80, 40);
-                shapeIcons[0].endFill();
+                game.add.graphic.rect(xShape, 175, 80, 40, colors.darkBlue, 2, colors.lightBlue, 1);
                 // Red square
-                shapeIcons[1] = game.add.graphics(startShape, 330);
-                shapeIcons[1].anchor.setTo(0.5, 0.5);
-                shapeIcons[1].lineStyle(2, colors.red);
-                shapeIcons[1].beginFill(colors.lightBlue);
-                shapeIcons[1].drawRect(0, 0, 80, 40);
-                shapeIcons[1].endFill();
+                game.add.graphic.rect(xShape, 330, 80, 40, colors.red, 2, colors.lightBlue, 1);
 
                 // Green tractor
-                themeIcons[0] = game.add.sprite(startTheme + 30, 215, 'tractor');
-                themeIcons[0].frame = 1;
-                themeIcons[0].scale.setTo(0.5);
-                themeIcons[0].alpha = 0.9;
-                themeIcons[0].anchor.setTo(0.5, 0.5);
+                game.add.sprite(xTheme + 30 - 50, 215 - 40, 'tractor', 1, 0.5);
                 // Red tractor
-                themeIcons[1] = game.add.sprite(startTheme + 70, 370, 'tractor');
-                themeIcons[1].frame = 5;
-                themeIcons[1].scale.setTo(0.5);
-                themeIcons[1].alpha = 0.9;
-                themeIcons[1].anchor.setTo(0.5, 0.5);
+                game.add.sprite(xTheme + 70 - 50, 370 - 41, 'tractor', 5, 0.5);
 
                 // Plus Arrow
-                arrowIcons[0] = game.add.sprite(startTheme + 100, 215, 'h_arrow');
-                arrowIcons[0].scale.setTo(0.3);
-                arrowIcons[0].alpha = 0.9;
-                arrowIcons[0].anchor.setTo(0.5, 0.5);
+                game.add.image(xTheme + 100 - 20, 215 - 20, 'arrow_right', 0.3);
                 // Minus Arrow
-                arrowIcons[1] = game.add.sprite(startTheme, 370, 'h_arrow');
-                arrowIcons[1].scale.setTo(0.3);
-                arrowIcons[1].alpha = 0.9;
-                arrowIcons[1].anchor.setTo(0.5, 0.5);
-                arrowIcons[1].scale.x *= -1;
+                game.add.image(xTheme - 20, 370 - 20, 'arrow_left', 0.3);
 
                 break;
-            case "gameCircleOne":
+
+            case "circleOne":
 
                 // Blue Circle
-                shapeIcons[0] = game.add.graphics(startShape, 175);
-                shapeIcons[0].anchor.setTo(0.5, 0.5);
-                shapeIcons[0].lineStyle(2, colors.darkBlue);
-                shapeIcons[0].beginFill(colors.lightBlue);
-                shapeIcons[0].drawCircle(0, 0, 60);
-                shapeIcons[0].endFill();
+                game.add.graphic.circle(xShape, 175, 60, colors.darkBlue, 2, colors.lightBlue, 1);
                 // Red Circle
-                shapeIcons[1] = game.add.graphics(startShape, 330);
-                shapeIcons[1].anchor.setTo(0.5, 0.5);
-                shapeIcons[1].lineStyle(2, colors.red);
-                shapeIcons[1].beginFill(colors.lightBlue);
-                shapeIcons[1].drawCircle(0, 0, 60);
-                shapeIcons[1].endFill();
-                // Both blue and red circles
-                shapeIcons[2] = game.add.graphics(startShape - 30, 485);
-                shapeIcons[2].anchor.setTo(0.5, 0.5);
-                shapeIcons[2].lineStyle(2, colors.darkBlue);
-                shapeIcons[2].beginFill(colors.lightBlue);
-                shapeIcons[2].drawCircle(0, 0, 60);
-                shapeIcons[2].endFill();
-                shapeIcons[3] = game.add.graphics(startShape + 40, 485);
-                shapeIcons[3].anchor.setTo(0.5, 0.5);
-                shapeIcons[3].lineStyle(2, colors.red);
-                shapeIcons[3].beginFill(colors.lightBlue);
-                shapeIcons[3].drawCircle(0, 0, 60);
-                shapeIcons[3].endFill();
+                game.add.graphic.circle(xShape, 330, 60, colors.red, 2, colors.lightBlue, 1);
+                // Blue and red circle
+                game.add.graphic.circle(xShape - 30, 485, 60, colors.darkBlue, 2, colors.lightBlue, 1);
+                game.add.graphic.circle(xShape + 40, 485, 60, colors.red, 2, colors.lightBlue, 1);
 
                 // Kid plus
-                themeIcons[0] = game.add.sprite(startTheme, 195, 'kid_walk');
-                themeIcons[0].scale.setTo(0.6);
-                themeIcons[0].alpha = 0.8;
-                themeIcons[0].anchor.setTo(0.5, 0.5);
+                game.add.sprite(xTheme, 195, 'kid_walk', 0, 0.6).anchor(0.5, 0.5);
                 // Kid minus
-                themeIcons[1] = game.add.sprite(startTheme + 40, 350, 'kid_walk');
-                themeIcons[1].scale.setTo(-0.6, 0.6);
-                themeIcons[1].alpha = 0.8;
-                themeIcons[1].anchor.setTo(0.5, 0.5);
+                game.add.sprite(xTheme + 40, 350, 'kid_walk', 12, 0.6).anchor(0.5, 0.5);
 
                 // Plus arrow
-                arrowIcons[0] = game.add.sprite(startTheme + 40, 195, 'h_arrow');
-                arrowIcons[0].scale.setTo(0.35);
-                arrowIcons[0].alpha = 0.8;
-                arrowIcons[0].anchor.setTo(0.5, 0.5);
+                game.add.image(xTheme + 40 - 20, 195, 'arrow_right', 0.35);
                 // Minus arrow
-                arrowIcons[1] = game.add.sprite(startTheme, 350, 'h_arrow');
-                arrowIcons[1].scale.setTo(-0.35, 0.35);
-                arrowIcons[1].alpha = 0.8;
-                arrowIcons[1].anchor.setTo(0.5, 0.5);
+                game.add.image(xTheme - 20, 350 - 20, 'arrow_left', 0.35);
                 // Both plus and minus arrows
-                arrowIcons[2] = game.add.sprite(startTheme + 20, 500, 'h_double');
-                arrowIcons[2].scale.setTo(0.5);
-                arrowIcons[2].alpha = 0.8;
-                arrowIcons[2].anchor.setTo(0.5, 0.5);
+                game.add.image(xTheme + 20 - 30, 500 - 40, 'arrow_double', 0.5);
 
                 break;
-            case "gameSquareTwo":
 
-                themeIcons[0] = game.add.sprite(startTheme, 370, 'equal');
-                themeIcons[0].scale.setTo(0.7);
-                themeIcons[0].anchor.setTo(0.5, 0.5);
+            case "squareTwo":
+
+                // Equal sign
+                game.add.image(xTheme - 40, 370 - 40, 'equal', 0.7);
 
                 break;
-            default: if (debugMode) console.log("Error: couldn't finish loading difficulty screen assets");
 
         }
 
+        const aux = {
+            color: [colors.diffBlue, colors.diffRed, colors.diffPurple],
+            y: [135, 285, 435],
+
+            _sublevel: [['Plus', 'Minus', 'Mixed'], ['A', 'B', 'C']],
+            get sublevel() { return (gameTypeString == 'squareTwo') ? this._sublevel[1] : this._sublevel[0]; },
+        };
+
         // Placing difficulty 'stairs'
-        for (let sublevel = 0; sublevel < maxSublevel; sublevel++) {
-            for (let difficulty = 1; difficulty <= maxDifficulty; difficulty++) {
-                // Position
-                const x1 = startStair + (stairWidth * (difficulty - 1));
-                const y1 = aux.base_y1[sublevel] + maxStairHeight - difficulty * stairHeight;
-                const x2 = stairWidth;//x1 + 40;
-                const y2 = stairHeight * difficulty;//y1 + 24;
-                // Graphics
-                stairs[difficulty] = game.add.graphics(0, 0);
-                stairs[difficulty].lineStyle(1, colors.blueBckg);
-                stairs[difficulty].beginFill(aux.color[sublevel]);
-                stairs[difficulty].drawRect(x1, y1, x2, y2);
-                stairs[difficulty].endFill();
-
-                stairs[difficulty].inputEnabled = true;
-                stairs[difficulty].input.useHandCursor = true;
-                stairs[difficulty].events.onInputDown.add(this.func_loadMap, { difficulty: difficulty, sublevelType: aux.sublevel[sublevel] });
-                stairs[difficulty].events.onInputOver.add(function (item) { item.alpha = 0.5; }, this);
-                stairs[difficulty].events.onInputOut.add(function (item) { item.alpha = 1; }, this);
+        for (let i_subl = 0; i_subl < maxSublevel; i_subl++) { // sublevel (vertical)
+
+            for (let j_dif = 1; j_dif <= maxDifficulty; j_dif++) { // difficulty (horizontal)
+
+                // Parameters
+                const x = xStair + (stairWidth * (j_dif - 1));
+                const y = aux.y[i_subl] + maxStairHeight - j_dif * stairHeight;
+                const width = stairWidth;
+                const height = stairHeight * j_dif;
+
+                // Difficulty stairs
+                const stair = game.add.graphic.rect(x, y, width, height, colors.blueBckg, 1, aux.color[i_subl], 1);
+                stair.difficulty = j_dif;
+                stair.sublevelType = aux.sublevel[i_subl];
+
+                this.stairs.push(stair);
+
                 // Labels
-                const xl = x1 + stairWidth / 2; //x label
-                const yl = y1 + (stairHeight * difficulty) / 2; //y label
-                const label = game.add.text(xl, yl, difficulty, textStyles.difficultyLabel);
-                label.anchor.setTo(0.5, 0.4);
+                const xLabel = x + stairWidth / 2;
+                const yLabel = y + (stairHeight * j_dif) / 2 + 10;
+                game.add.text(xLabel, yLabel, j_dif, textStyles.difficultyLabel);
+
+            }
+        }
+
+        game.event.add('click', difficultyScreen.func_onInputDown);
+        game.event.add('mousemove', difficultyScreen.func_onInputOver);
+
+        game.render.all();
+
+    },
+
+
+
+    /* EVENT HANDLER */
+
+    func_onInputDown: function (mouseEvent) {
+
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+
+        // check if turned labels ON/OFF
+        if (gameTypeString != 'squareTwo') {
+
+            const cur = difficultyScreen.selectionBox;
+
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+            if (valid) difficultyScreen.func_setLabel(cur, difficultyScreen.labelText);
+
+        }
+
+        // check difficulty stairs
+        difficultyScreen.stairs.forEach((cur) => {
+
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+            if (valid) {
+                game.event.clear(self);
+                difficultyScreen.func_loadMap(cur.difficulty, cur.sublevelType);
+            }
+        });
+
+        navigationIcons.func_onInputDown(x, y);
+
+    },
+
+    func_onInputOver: function (mouseEvent) {
+
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+        const flag = [false, false];
+
+        // check difficulty stairs
+        difficultyScreen.stairs.forEach((cur) => {
+
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+            if (valid) {
+                flag[0] = true;
+                cur.alpha = 0.5;
+            } else {
+                cur.alpha = 1;
+            }
+        });
+
+        if (gameTypeString != 'squareTwo') {
+
+            const cur = difficultyScreen.selectionBox;
+
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+            if (valid) {
+                flag[1] = true;
             }
         }
 
+        if (flag[0] || flag[1]) document.body.style.cursor = "pointer";
+        else document.body.style.cursor = "auto";
+
+        navigationIcons.func_onInputOver(x, y);
+
+        game.render.all();
+
     },
 
+
+    /* GAME FUNCTIONS */
+
     // Calls map state
-    func_loadMap: function () {
+    func_loadMap: function (stairDifficulty, stairSublevelType) {
 
-        if (audioStatus) sound.beepSound.play();
+        if (audioStatus) game.audio.beepSound.play();
 
         mapPosition = 0;   //Map position
-        mapCanMove = true;       //Move no next point
-        levelDifficulty = this.difficulty;  // difficulty for selected level (1..3 or 1..5)
-        sublevelType = this.sublevelType;   //Type of game
+        mapMove = true;       //Move no next point
+        gameDifficulty = stairDifficulty;  // difficulty for selected level (1..3 or 1..5)
+        sublevelType = stairSublevelType;   //Type of game
         completedLevels = 0;       //reset the game progress when entering a new level
 
-        game.state.start('map');
+        mapScreen.preload();
 
     },
 
-    func_setLabel: function () {
+    func_setLabel: function (selectionBox, selectionLabel) {
 
-        if (levelLabel) {
+        if (fractionLabel) {
 
-            levelLabel = false;
-            this.selectionBox.frame = 0;
-            this.labelText.text = lang.without_name + " " + lang.label_name;
+            fractionLabel = false;
+            selectionBox.curFrame = 0;
+            selectionLabel.name = game.lang.without_name + " " + game.lang.label_name;
 
         } else {
 
-            levelLabel = true;
-            this.selectionBox.frame = 1;
-            this.labelText.text = lang.with_name + " " + lang.label_name;
+            fractionLabel = true;
+            selectionBox.curFrame = 1;
+            selectionLabel.name = game.lang.with_name + " " + game.lang.label_name;
 
         }
 
-        if (audioStatus) sound.beepSound.play();
+        if (audioStatus) game.audio.beepSound.play();
 
+        game.render.all();
     }
+
 };

+ 783 - 0
js/gameMechanics.js

@@ -0,0 +1,783 @@
+const game = {
+
+	audio: {}, lang: {}, // Holds cache reference to media : Directly used in code to get audio and dicitonary
+	image: {}, sprite: {}, // Holds cache reference to media : Not directly used in code
+	mediaTypes: ['lang', 'audio', 'image', 'sprite'],
+	loadedMedia: [],
+	isLoaded: [],
+	
+	// List of media URL
+	url: {
+		boot: {
+			image: [
+				// Scene
+				['bgimage', medSrc + 'scene/bg.jpg'],
+				['bgmap', 	medSrc + 'scene/bg_map.png'],
+				['bush', 	medSrc + 'scene/bush.png'],
+				['cloud', 	medSrc + 'scene/cloud.png'],
+				['floor', 	medSrc + 'scene/floor.png'],
+				['place_off', 	medSrc + 'scene/place_off.png'],
+				['place_on', 	medSrc + 'scene/place_on.png'],
+				['rock', 	medSrc + 'scene/rock.png'],
+				['road', 	medSrc + 'scene/road.png'],
+				['sign', 	medSrc + 'scene/sign.png'],
+				['tree1', 	medSrc + 'scene/tree.png'],
+				['tree2', 	medSrc + 'scene/tree2.png'],
+				['tree3', 	medSrc + 'scene/tree3.png'],
+				['tree4', 	medSrc + 'scene/tree4.png'],
+				// Flags
+				['flag_BR', medSrc + 'flag/BRAZ.jpg'],
+				['flag_FR', medSrc + 'flag/FRAN.jpg'],
+				['flag_IT', medSrc + 'flag/ITAL.png'],
+				['flag_PE', medSrc + 'flag/PERU.jpg'],
+				['flag_US', medSrc + 'flag/UNST.jpg'],
+				// Navigation icons on the top of the page
+				['back', 		medSrc + 'navig_icon/back.png'],
+				['help', 		medSrc + 'navig_icon/help.png'],
+				['home', 		medSrc + 'navig_icon/home.png'],
+				['language', 	medSrc + 'navig_icon/language.png'],
+				['menu', 		medSrc + 'navig_icon/menu.png'],
+				// Interactive icons
+				['arrow_down', 		medSrc + 'interac_icon/down.png'],
+				['error', 			medSrc + 'interac_icon/error.png'],
+				['help_pointer', 	medSrc + 'interac_icon/pointer.png'],
+				['ok',				medSrc + 'interac_icon/ok.png'],
+				// Non-interactive icons
+				['arrow_double', 	medSrc + 'non_interac_icon/double.png'],
+				['arrow_left', 		medSrc + 'non_interac_icon/left_arrow.png'],
+				['arrow_right', 	medSrc + 'non_interac_icon/right_arrow.png'],
+				['equal', 			medSrc + 'non_interac_icon/equal.png']
+			],
+			sprite: [
+				// Game Sprites
+				['kid_walk', 	medSrc + 'character/kid/walk.png', 26],
+				// Navigation icons on the top of the page
+				['audio', 		medSrc + 'navig_icon/audio.png', 2],
+				// Interactive icons
+				['select', 		medSrc + 'interac_icon/selectionBox.png', 2]
+			],
+			audio: [
+				// Sound effects
+				['beepSound', ['assets/audio/beep.ogg', 'assets/audio/beep.mp3']],
+				['okSound', ['assets/audio/ok.ogg', 'assets/audio/ok.mp3']],
+				['errorSound', ['assets/audio/error.ogg', 'assets/audio/error.mp3']]
+			]
+		},
+		menu: {
+			// @@ TRY TO MAKE GAME+I NOVAMENTE PARA NAO PRECISAR DEFINIR O NOME DO JOGO SEMPRE
+			image: [
+				// Level Icons
+				['game0', medSrc + 'levels/squareOne_1.png', 'Square', 'A'], // Square I
+				['game1', medSrc + 'levels/squareOne_2.png', 'Square', 'B'], // Square II
+				['game2', medSrc + 'levels/circleOne_1.png', 'Circle', 'A'], // Circle I
+				['game3', medSrc + 'levels/circleOne_2.png', 'Circle', 'B'], // Circle II
+				['game4', medSrc + 'levels/squareTwo_3.png', 'Square', 'C']	// Square III
+			],
+			//if (debugMode) {
+			//	for (let i = 0; i < 8; i++) {
+			//		image.push(['', medSrc + 'levels/squareTwo_3.png', 'Square', 'C']);
+			//	}
+			//}
+			sprite: [],
+			audio: []
+		},
+		squareOne: {
+			image: [
+				// Scene
+				['farm', 	medSrc + 'scene/farm.png'],
+				['garage', 	medSrc + 'scene/garage.png']
+			],
+			sprite: [
+				// Game sprites
+				['tractor', medSrc + 'character/tractor/tractor.png', 15]
+			],
+			audio: []
+		},
+		squareTwo: {
+			image: [
+				// Scene
+				['house', 	medSrc + 'scene/house.png'],
+				['school', 	medSrc + 'scene/school.png']
+			],
+			sprite: [
+				// Game sprites
+				['kid_standing', 	medSrc + 'character/kid/lost.png', 6],
+				['kid_run', 		medSrc + 'character/kid/run.png', 12]
+			],
+			audio: []
+		},
+		circleOne: {
+			image: [
+				// Scene
+				['house', medSrc + 'scene/house.png'],
+				['school', medSrc + 'scene/school.png'],
+				// Game images
+				['balloon', medSrc + 'character/balloon/airballoon_upper.png'],
+				['balloon_basket', medSrc + 'character/balloon/airballoon_base.png']
+			],
+			sprite: [
+				// Game sprites
+				['kid_run', medSrc + 'character/kid/run.png', 12]
+			],
+			audio: []
+		},
+	},
+
+	// Loads a list of URL to Cache
+	load: {
+		lang: function (url) {
+			game.isLoaded['lang'] = false;
+			game.loadedMedia['lang'] = 0;
+			game.lang = {}; // clear previously loaded language
+			const init = { mode: "same-origin" };
+			fetch(url, init)
+				.then(function (response) {
+					return response.text();
+				})
+				.then(function (text) {
+					let msg = text.split("\n");
+					msg.forEach(cur => {
+						try {
+							let msg = cur.split("=");
+							game.lang[msg[0].trim()] = msg[1].trim();
+						} catch (Error) { if (debugMode) console.log("Sintax error fixed"); }
+						game.load._informMediaIsLoaded(msg.length, 'lang');
+					});
+				});
+		},
+		audio: function (urls) {
+			game.isLoaded['audio'] = false;
+			game.loadedMedia['audio'] = 0;
+			urls = this._getNotLoadedUrls(urls, game.audio);
+			if (urls.length == 0) {
+				game.load._informMediaIsLoaded(0, 'audio');
+			} else {
+				const init = { mode: "same-origin" };
+				urls.forEach(cur => {
+					fetch(cur[1][1], init)
+						.then(response => response.blob())
+						.then(function (myBlob) {
+							game.audio[cur[0]] = new Audio(URL.createObjectURL(myBlob));
+							game.load._informMediaIsLoaded(urls.length, 'audio');
+						});
+				});
+			}
+		},
+		image: function (urls) {
+			game.isLoaded['image'] = false;
+			game.loadedMedia['image'] = 0;
+			urls = this._getNotLoadedUrls(urls, game.image);
+			if (urls.length == 0) {
+				game.load._informMediaIsLoaded(0, 'image');
+			} else {
+				urls.forEach(cur => {
+					const img = new Image(); //HTMLImageElement
+					img.onload = () => {
+						game.image[cur[0]] = img;
+						game.load._informMediaIsLoaded(urls.length, 'image');
+					}
+					img.src = cur[1];
+				});
+			}
+		},
+		sprite: function (urls) {
+			game.isLoaded['sprite'] = false;
+			game.loadedMedia['sprite'] = 0;
+			urls = this._getNotLoadedUrls(urls, game.sprite);
+			if (urls.length == 0) {
+				game.load._informMediaIsLoaded(0, 'sprite');
+			} else {
+				urls.forEach(cur => {
+					const img = new Image(); //HTMLImageElement
+					img.onload = () => {
+						game.sprite[cur[0]] = img;
+						game.load._informMediaIsLoaded(urls.length, 'sprite');
+					}
+					img.src = cur[1];
+					img.frames = cur[2];
+				});
+			}
+		},
+		// get list of urls and return only valid ones
+		_getNotLoadedUrls: function (urls, media) {
+			const newUrls = [];
+			urls.forEach(cur => { if (media[cur[0]] == undefined) newUrls.push(cur); });
+			return newUrls;
+		},
+		_informMediaIsLoaded: function (total, type) {
+			if (game.loadedMedia[type] == total - 1) { // if all media of that type was loaded	
+				game.isLoaded[type] = true;
+				game.load._isPreloadDone(type);
+			}
+			game.loadedMedia[type]++;
+		},
+		// Calls create() for current screen if all media for screen was loaded
+		_isPreloadDone: function (type) {
+			let flag = true;
+			for (let i in game.mediaTypes) {
+				// if all media for the screen was loaded flag wont change
+				if (game.isLoaded[game.mediaTypes[i]] == false) {
+					flag = false;
+					break;
+				}
+			}
+			// if flag doesnt change preload is complete
+			if (flag) {
+				game.isLoaded = [];
+				game.loadedMedia[type] = 0;
+				self.create();
+			}
+		}
+	},
+
+	// Adds new media to "media queue" to be rendered by current screen
+	add: {
+		// game.add.image(x, y, img)
+		// game.add.image(x, y, img, scale)
+		// game.add.image(x, y, img, scaleWidth, scaleHeigth)
+		// game.add.image(x, y, img, scaleWidth, scaleHeigth, alpha)
+		image: function (x, y, img, sW, sH, alpha) {
+			if (x == undefined || y == undefined || img == undefined) console.error("Game error: parameters missing");
+			else if (game.image[img] == undefined) console.error("Game error: image not found in cache: " + img);
+			else {
+				const med = {
+					typeOfMedia: 'image',
+					name: img,
+
+					x: x || 0,
+					y: y || 0,
+					_xWithAnchor: x || 0,
+					_yWithAnchor: y || 0,
+					xAnchor: 0,
+					yAnchor: 0,
+
+					scaleWidth: sW || 1,
+					scaleHeight: sW || 1,
+					width: game.image[img].width,
+					height: game.image[img].height,
+
+					alpha: alpha || 1,
+
+					anchor: function (xAnchor, yAnchor) {
+						this.xAnchor = xAnchor;
+						this.yAnchor = yAnchor;
+					},
+
+					get xWithAnchor() { return this.x - (this.width * this.scaleWidth * this.xAnchor); },
+					get yWithAnchor() { return this.y - (this.height * this.scaleHeight * this.yAnchor); }
+				};
+				if (sH != undefined) med.scaleHeight = sH;
+				game.render.queue.push(med);
+				return med;
+			}
+		},
+		// game.add.sprite(x, y, img) 
+		// game.add.sprite(x, y, img, curFrame) 
+		// game.add.sprite(x, y, img, curFrame, scale) 
+		sprite: function (x, y, img, curFrame, scale) {
+			if (x == undefined || y == undefined || img == undefined) console.error("Game error: parameters missing");
+			else if (game.sprite[img] == undefined) console.error("Game error: sprite not found in cache: " + img);
+			else {
+				const med = {
+					typeOfMedia: 'sprite',
+					name: img,
+
+					x: x || 0,
+					y: y || 0,
+					_xWithAnchor: x || 0,
+					_yWithAnchor: y || 0,
+					xAnchor: 0,
+					yAnchor: 0,
+
+					scaleWidth: scale || 1,
+					scaleHeight: scale || 1,
+					width: game.sprite[img].width / game.sprite[img].frames, // frame width
+					height: game.sprite[img].height, // frame height
+
+					curFrame: curFrame || 0,
+
+					alpha: 1,
+
+					anchor: function (xAnchor, yAnchor) {
+						this.xAnchor = xAnchor;
+						this.yAnchor = yAnchor;
+					},
+
+					get xWithAnchor() { return this.x - (this.width * this.scaleWidth * this.xAnchor); },
+					get yWithAnchor() { return this.y - (this.height * this.scaleHeight * this.yAnchor); }
+				};
+				game.render.queue.push(med);
+				return med;
+			}
+		},
+		// game.add.text(x, y, text)
+		// game.add.text(x, y, text, style) 
+		text: function (x, y, text, style) {
+			if (x == undefined || y == undefined || text == undefined) console.error("Game error: parameters missing");
+			else {
+				const med = {
+					typeOfMedia: 'text',
+					name: text,
+
+					x: x || 0,
+					y: y || 0,
+					_xWithAnchor: x || 0,
+					_yWithAnchor: y || 0,
+					xAnchor: 0,
+					yAnchor: 0,
+
+					style: style || textStyles.default,
+
+					alpha: 1,
+
+					anchor: function () { console.error("Game error: there's no anchor for text"); },
+
+					get xWithAnchor() { return this.x; },
+					get yWithAnchor() { return this.y; }
+				};
+				game.render.queue.push(med);
+				return med;
+			}
+		},
+		graphic: {
+			// game.add.graphics.rect(x, y, width, height)
+			// game.add.graphics.rect(x, y, width, height, lineColor)
+			// game.add.graphics.rect(x, y, width, height, lineColor, lineWidth)
+			// game.add.graphics.rect(x, y, width, height, lineColor, lineWidth, fillColor)
+			// game.add.graphics.rect(x, y, width, height, lineColor, lineWidth, fillColor, alpha)
+			rect: function (x, y, width, height, lineColor, lineWidth, fillColor, alpha) {
+				if (x == undefined || y == undefined || width == undefined || height == undefined) console.error("Game error: parameters missing");
+				else {
+					const med = {
+						typeOfMedia: 'rect',
+
+						x: x || 0,
+						y: y || 0,
+						_xWithAnchor: x || 0,
+						_yWithAnchor: y || 0,
+						xAnchor: 0,
+						yAnchor: 0,
+
+						scaleWidth: 1,
+						scaleHeight: 1,
+						width: width || 50,
+						height: height || 50,
+
+						lineColor: lineColor || colors.black,
+						lineWidth: lineWidth || 0,	// by default there's no line width
+						fillColor: fillColor || 0,
+
+						alpha: (alpha != undefined) ? alpha : 1,
+
+						anchor: function (xAnchor, yAnchor) {
+							this.xAnchor = xAnchor;
+							this.yAnchor = yAnchor;
+						},
+
+						get xWithAnchor() { return this.x - (this.width * this.scaleWidth * this.xAnchor); },
+						get yWithAnchor() { return this.y - (this.height * this.scaleHeight * this.yAnchor); }
+					};
+					game.render.queue.push(med);
+					return med;
+				}
+			},
+			// game.add.graphics.circle(x, y, diameter)
+			// game.add.graphics.circle(x, y, diameter, lineColor)
+			// game.add.graphics.circle(x, y, diameter, lineColor, lineWidth)
+			// game.add.graphics.circle(x, y, diameter, lineColor, lineWidth, fillColor)
+			// game.add.graphics.circle(x, y, diameter, lineColor, lineWidth, fillColor, alpha)
+			circle: function (x, y, diameter, lineColor, lineWidth, fillColor, alpha) {
+				if (x == undefined || y == undefined || diameter == undefined) console.error("Game error: parameters missing");
+				else {
+					const med = {
+						typeOfMedia: 'arc',
+
+						x: x || 0,
+						y: y || 0,
+						_xWithAnchor: x || 0,
+						_yWithAnchor: y || 0,
+						xAnchor: 0,
+						yAnchor: 0,
+
+						diameter: diameter || 50,
+						angleStart: 0,
+						angleEnd: 2 * Math.PI,
+						anticlockwise: false,
+
+						scaleWidth: 1,
+						scaleHeight: 1,
+						width: diameter,
+						height: diameter,
+
+						lineColor: lineColor || colors.black,
+						lineWidth: lineWidth || 0, 		// by default there's no line width
+						fillColor: fillColor || colors.white,
+
+						alpha: (alpha != undefined) ? alpha : 1,
+
+						anchor: function (xAnchor, yAnchor) {
+							this.xAnchor = xAnchor;
+							this.yAnchor = yAnchor;
+						},
+
+						get xWithAnchor() { return this.x - (this.width * this.scaleWidth * this.xAnchor); },
+						get yWithAnchor() { return this.y - (this.height * this.scaleHeight * this.yAnchor); }
+					};
+					game.render.queue.push(med);
+					return med;
+				}
+			},
+			// game.add.graphics.arc(x, y, diameter, angleStart, angleEnd, anticlockWise)
+			// game.add.graphics.arc(x, y, diameter, angleStart, angleEnd, anticlockWise, lineColor)
+			// game.add.graphics.arc(x, y, diameter, angleStart, angleEnd, anticlockWise, lineColor, lineWidth)
+			// game.add.graphics.arc(x, y, diameter, angleStart, angleEnd, anticlockWise, lineColor, lineWidth, fillColor)
+			// game.add.graphics.arc(x, y, diameter, angleStart, angleEnd, anticlockWise, lineColor, lineWidth, fillColor, alpha)
+			arc: function (x, y, diameter, angleStart, angleEnd, anticlockwise, lineColor, lineWidth, fillColor, alpha) {
+				if (x == undefined || y == undefined || diameter == undefined || angleStart == undefined || angleEnd == undefined) console.error("Game error: parameters missing");
+				else {
+					const med = {
+						typeOfMedia: 'arc',
+
+						x: x || 0,
+						y: y || 0,
+						_xWithAnchor: x || 0,
+						_yWithAnchor: y || 0,
+						xAnchor: 0,
+						yAnchor: 0,
+
+						diameter: diameter || 50,
+						angleStart: angleStart,
+						angleEnd: angleEnd,
+						anticlockwise: anticlockwise || false,
+
+						scaleWidth: 1,
+						scaleHeight: 1,
+						width: diameter,
+						height: diameter,
+
+						lineColor: lineColor || colors.black,
+						lineWidth: lineWidth || 0, 		// by default there's no line width
+						fillColor: fillColor || colors.white,
+
+						alpha: (alpha != undefined) ? alpha : 1,
+
+						anchor: function (xAnchor, yAnchor) {
+							this.xAnchor = xAnchor;
+							this.yAnchor = yAnchor;
+						},
+
+						get xWithAnchor() { return this.x - (this.width * this.scaleWidth * this.xAnchor); },
+						get yWithAnchor() { return this.y - (this.height * this.scaleHeight * this.yAnchor); }
+					};
+					game.render.queue.push(med);
+					return med;
+				}
+			}
+		}
+	},
+
+	// Renders media on current screen
+	render: {
+		queue: [], // media queue to be rendered by the current state
+		_image: function (cur) {	// ( x, y, img, sW, sH, alpha)
+			const x = cur.xWithAnchor, y = cur.yWithAnchor;
+			if (cur.rotate && cur.rotate != 0) {
+				context.save();
+				context.translate(cur.x, cur.y);
+				context.rotate(cur.rotate * Math.PI / 180);
+				context.translate(-cur.x, -cur.y);
+			}
+			context.globalAlpha = cur.alpha;
+			context.drawImage(
+				game.image[cur.name],
+				x,
+				y,
+				cur.width * cur.scaleWidth,
+				cur.height * cur.scaleHeight
+			);
+			context.globalAlpha = 1;
+			if (cur.rotate && cur.rotate != 0) context.restore();
+		},
+		_sprite: function (cur) {	// ( x, y, img, curFrame, s )
+			const x = cur.xWithAnchor, y = cur.yWithAnchor;
+			if (cur.rotate && cur.rotate != 0) {
+				context.save();
+				context.translate(cur.x, cur.y);
+				context.rotate(cur.rotate * Math.PI / 180);
+				context.translate(-cur.x, -cur.y);
+			}
+			context.globalAlpha = cur.alpha;
+			context.drawImage(
+				game.sprite[cur.name],
+				cur.width * cur.curFrame,
+				0,
+				cur.width,
+				cur.height,
+				x,
+				y,
+				cur.width * cur.scaleWidth,
+				cur.height * cur.scaleHeight
+			);
+			context.globalAlpha = 1;
+			if (cur.rotate && cur.rotate != 0) context.restore();
+		},
+		_text: function (cur) {		// ( x, y, text, style )
+			const x = cur.xWithAnchor, y = cur.yWithAnchor;
+			if (cur.rotate && cur.rotate != 0) {
+				context.save();
+				context.translate(cur.x, cur.y);
+				context.rotate(cur.rotate * Math.PI / 180);
+				context.translate(-cur.x, -cur.y);
+			}
+			context.globalAlpha = cur.alpha;
+			context.font = cur.style.font;
+			context.textAlign = cur.style.align;
+			context.fillStyle = cur.style.fill;
+			context.fillText(cur.name, x, y);
+			context.globalAlpha = 1;
+			if (cur.rotate && cur.rotate != 0) context.restore();
+		},
+		_graphic: {
+			_rect: function (cur) { // ( x, y, width, height, lineColor, lineWidth, fillColor, alpha)
+				const x = cur.xWithAnchor, y = cur.yWithAnchor;
+				if (cur.rotate && cur.rotate != 0) {
+					context.save();
+					context.translate(cur.x, cur.y);
+					context.rotate(cur.rotate * Math.PI / 180);
+					context.translate(-cur.x, -cur.y);
+				}
+				context.globalAlpha = cur.alpha;
+				if (cur.fillColor != 0) {
+					context.fillStyle = cur.fillColor;
+					context.fillRect(x, y, cur.width, cur.height);
+				}
+				if (cur.lineWidth != 0) {
+					context.strokeStyle = cur.lineColor;
+					context.lineWidth = cur.lineWidth;
+					context.strokeRect(x, y, cur.width, cur.height);
+				}
+				context.globalAlpha = 1;
+				if (cur.rotate && cur.rotate != 0) context.restore();
+			},
+
+			_arc: function (cur) {	// ( x, y, diameter, angleStart, angleEnd, anticlockWise, lineColor, lineWidth, fillColor, alpha);
+				const x = cur.xWithAnchor, y = cur.yWithAnchor;
+				if (cur.rotate && cur.rotate != 0) {
+					context.save();
+					context.translate(cur.x, cur.y);
+					context.rotate(cur.rotate * Math.PI / 180);
+					context.translate(-cur.x, -cur.y);
+				}
+				context.globalAlpha = cur.alpha;
+				context.fillStyle = cur.fillColor;
+				context.strokeStyle = cur.lineColor;
+				context.lineWidth = cur.lineWidth;
+				context.beginPath();
+				if (cur.angleEnd != 2 * Math.PI) context.lineTo(x, y);
+				context.arc(x, y, cur.diameter / 2, cur.angleStart, cur.angleEnd, cur.anticlockwise);
+				if (cur.angleEnd != 2 * Math.PI) context.lineTo(x, y);
+				context.fill();
+				context.stroke();
+				context.globalAlpha = 1;
+				if (cur.rotate && cur.rotate != 0) context.restore();
+			},
+
+		},
+		// game.render.all() : draws all queued media to screen
+		all: function () {
+			game.render.queue.forEach(cur => {
+				switch (cur.typeOfMedia) {
+					case 'image': this._image(cur); break;
+					case 'sprite': this._sprite(cur); break;
+					case 'text': this._text(cur); break;
+					case 'rect': this._graphic._rect(cur); break;
+					case 'arc': this._graphic._arc(cur); break;
+				}
+			});
+
+		},
+		// game.render.clear() : clears all queued media
+		clear: function () {
+			game.render.queue = [];
+		}
+	},
+
+	// Math functions
+	math: {
+		randomInRange: function (min, max) { // integer
+			min = Math.ceil(min);
+			max = Math.floor(max);
+			return Math.floor(Math.random() * (max - min + 1) + min); //The maximum is inclusive and the minimum is also inclusive
+		},
+		randomDivisor: function (number) { //Get random divisor for a number
+			const validDivisors = []; // Divisors found
+			for (let i = 2; i < number; i++) {
+				// if 'number' can be divided by 'i', add to list of 'validDivisors'
+				if (number % i == 0) validDivisors.push(i);
+			}
+			const randIndex = game.math.randomInRange(0, validDivisors.length - 1);
+			return validDivisors[randIndex];
+		},
+		degreeToRad: function (degree) {
+			return degree * Math.PI / 180;
+		},
+		radToDegree: function (radian) {
+			return radian * 180 / Math.PI;
+		},
+		distanceToPointer: function (xMouse, xIcon, yMouse, yIcon) {
+			const a = Math.max(xMouse, xIcon) - Math.min(xMouse, xIcon);
+			const b = Math.max(yMouse, yIcon) - Math.min(yMouse, yIcon);
+			return Math.sqrt(a * a + b * b);
+		},
+	},
+
+	// Timer 
+	timer: {
+		_start: 0,	// start time
+		_end: 0,	// end time
+		elapsed: 0, // elapsed time
+		start: function () {
+			game.timer._start = game.timer._end = game.timer._elapsed = 0; // clear
+			game.timer._start = new Date().getTime(); // set start time
+		},
+		stop: function () {
+			if (game.timer._start != 0 && game.timer._end == 0) { // if timer has started but not finished
+				game.timer._end = new Date().getTime(); // set end time
+				game.timer._elapsed = Math.floor((game.timer._end - game.timer._start) / 1000); // set elapsed time
+			}
+		},
+		get elapsed() { return game.timer._elapsed; }
+	},
+
+	// Handles to pointer events
+	event: {
+		_list: [], // list of events in current state
+		add: function (name, func) {
+			canvas.addEventListener(name, func); // param : name of the event, function to be called
+			game.event._list.push([name, func]);
+		},
+		clear: function () {
+			game.event._list.forEach(cur => {
+				canvas.removeEventListener(cur[0], cur[1]);
+			});
+			game.event._list = [];
+		},
+	},
+
+	// Game loop : handles repetition of method update and sprite animation
+	// game.loop.start();
+	// game.loop.stop();
+	loop: {
+		id: undefined,		// holds animation event
+		curState: undefined,	// state that called loop
+		status: "off", 	// loop status can be : 'on', 'ending' or 'off'
+		waitingToStart: undefined,
+		startTime: 0,
+		DURATION: 1000 / 60, // 1000: 1 second | 60: expected frames per second
+		start: function (state) {
+			if (game.loop.status == "off") {
+				game.loop.curState = state;
+				game.loop.startTime = new Date().getTime();
+				game.loop.status = "on";
+				game.loop.id = requestAnimationFrame(game.loop._run);
+			} else { // if "game.loop.status" is either "on" or "ending"
+				game.loop.waitingToStart = state;
+				if (game.loop.status == "on") game.loop.stop();
+			}
+		},
+		stop: function () {
+			if (game.loop.status == "on") game.loop.status = "ending";
+		},
+		_run: function () {
+			if (game.loop.status != "on") {
+				game.loop._clear();
+			} else {
+				const timestamp = new Date().getTime();
+				const runtime = timestamp - game.loop.startTime;
+				if (runtime >= game.loop.DURATION) {
+					if (debugMode) {
+						let fps = runtime / 1000;
+						fps = Math.round(1 / fps);
+						displayFps.innerHTML = "Fps: " + fps; // show fps
+					}
+					// Update state
+					game.loop.curState.update();
+					// Animate state
+					game.animation._run();
+				}
+				game.loop.id = requestAnimationFrame(game.loop._run);
+			}
+		},
+		_clear: function () {
+			if (game.loop.id != undefined) {
+				cancelAnimationFrame(game.loop.id);	// cancel animation event
+				game.loop.id = undefined;		// clear object that holds animation event	
+				game.loop.curState = undefined;	// clear object that holds current state
+				game.loop.status = "off"; 	// inform animation must end (read in _run())
+				displayFps.innerHTML = "";	// Stop showing fps
+			}
+			if (game.loop.waitingToStart != undefined) {
+				const temp = game.loop.waitingToStart;
+				game.loop.waitingToStart = undefined;
+				game.loop.start(temp);
+			}
+		},
+	},
+
+	// Change frames in queued spritesheets making animation
+	// game.animation.play(<animationName>); 
+	// game.animation.stop(<animationName>);
+	// game.animation.clear();
+	animation: {
+		queue: [], // animation queue for current level
+		count: 0,
+		play: function (name) {
+			let newAnimation;
+			// gets first object that has that animation name (name) in game.render.queue
+			for (let i in game.render.queue) {
+				if (game.render.queue[i].animation != undefined && game.render.queue[i].animation[0] == name) {
+					newAnimation = game.render.queue[i];
+					break;
+				}
+			}
+			// If found, saves object in game.animation.queue
+			if (newAnimation != undefined) game.animation.queue.push(newAnimation);
+		},
+		stop: function (name) {
+			// remove all with that name is game.animation.queue
+			game.animation.queue.forEach(cur => {
+				if (cur.animation[0] == name) {
+					game.animation.queue.splice(cur, 1);
+				}
+			});
+		},
+		_run: function () {
+			game.animation.queue.forEach(character => {
+				if (!character.animation[2] || game.animation.count % character.animation[2] == 0) {
+					const i = character.animation[1].indexOf(character.curFrame);
+					if (i == -1) { // frame not found
+						if (debugMode) console.error("Game error: animation frame not found");
+					} else if (i < character.animation[1].length - 1) { // go to next frame
+						character.curFrame = character.animation[1][i + 1];
+					} else {
+						character.curFrame = character.animation[1][0]; // if last frame, restart
+					}
+				}
+			});
+			game.animation.count++;
+		},
+		clear: function () {
+			// resets animation count
+			game.animation.count = 0;
+			// clears property 'animation' from objects in game.render.queue
+			game.render.queue.forEach(cur => {
+				if (cur.animation != undefined) {
+					delete cur.animation;
+				}
+			});
+			// clears game.animation.queue
+			game.animation.queue = [];
+		},
+	}
+
+};

+ 218 - 282
js/globals.js

@@ -1,385 +1,321 @@
-const imgsrc = "assets/img/"
 const defaultWidth = 900;
 const defaultHeight = 600;
+const medSrc = "assets/img/";
 
 const debugMode = false; 	// Turns console messages ON/OFF
 let audioStatus = false; 	// Turns game audio ON/OFF
+let fractionLabel = true; 	// Turns showing fractions in levels ON/OFF
 
 let playerName;
-let langString; 			// String that contains the selected language
-let lang = {};
-let sound = {};
-
-let levelLabel = true; 		// Turns explicitly showing the fractions in levels ON/OFF
-
-let currentGameState; 		// Name of the current selected 'game' state
-let self;
+let langString; 		// String that contains the selected language
+
+let self;				// Current state
+
+let mapPosition;		// character position in the map (1..4 valid, 5 end)
+let mapMove;			// When true, the character can move to next position in the map
+let completedLevels;	// Number of finished levels in the map
+
+/*
+.................................................... 
+.............square.................circle.......... }					} (gameShape)		 			 
+.........../........\.................|............. } game (gameType)
+........One..........Two.............One............ }
+......./...\..........|............./...\........... 
+......A.....B.........C............A.....B.......... } level (levelType)
+.(floor)..(stack)..(equal).....(floor).(circle)..... } 
+.......\./............|..............\./............ 
+........|.............|...............|............. 
+......./.\........../.|.\.........../.|.\........... 
+...Plus...Minus....A..B..C.....Plus.Minus.Mixed..... } sublevel (sublevelType)
+.......\./..........\.|./...........\.|./........... 
+........|.............|...............|............. 
+......1,2,3.......1,2,3,4,5.......1,2,3,4,5......... } difficulty (gameDifficulty)
+.................................................... 
+*/
+
+const TESTE = {
+	gameShape: [
+		'Square',
+		'Square',
+		'Circle'
+	],
+	gameType: [
+		'squareOne',
+		'squareTwo',
+		'circleOne'
+	],
+	levelType: [
+		['A', 'B'],
+		['C'],
+		['A', 'B']
+	],
+	sublevelType: [
+		['Plus', 'Minus'],
+		['A', 'B', 'C'],
+		['Plus', 'Minus', 'Mixed']
+	],
+	gameDifficulty: [
+		3,
+		5,
+		5
+	],
+};
 
-let mapPosition;			// character position in the map
-let mapCanMove;				// When true the character can move to next position in the map
-let completedLevels;		// Number of finished levels in the map
+/* GAME TYPE (in menu screen)
+ * can be: squareOne, 'SquareTwo' or 'CircleOne' */
+let gameType, gameTypeString;
 
-let levelShape;		 	    // Can be 'circle' or 'square'
-let levelDifficulty; 		// A value from 1..3 or 1..5 that defines the current level difficulty
+let gameShape;	// can be: 'circle' or 'square'
 
-/* LEVEL TYPE (the ones in the menu screen)
- * in squareOne/circleOne can be: 'A' (click on the floor) or 'B' (click on the amount to go/stacked figures)
- * in squareTwo           can be: 'C' (comparing fractions) */
+/* LEVEL TYPE (in menu screen)
+ * in squareOne/circleOne 	can be: 'A' (click on the floor) or 'B' (click on the amount to go/stacked figures)
+ * in squareTwo           	can be: 'C' (comparing fractions) */
 let levelType;
 
-/* SUBLEVEL TYPE (the ones in the difficulty screen)
- * in squareOne		levels can be: 'Plus' or 'Minus'
- * in circleOne 	levels can be: 'Plus', 'Minus' or 'Mixed'
- * in squareTwo     levels can be: 'A', 'B' or 'C' */
+/* SUBLEVEL TYPE (in difficulty screen)
+ * in squareOne		can be: 'Plus' or 'Minus'
+ * in circleOne 	can be: 'Plus', 'Minus' or 'Mixed'
+ * in squareTwo     can be: 'A', 'B' or 'C' */
 let sublevelType;
 
-let timer, totalTime; // Counts time spent in each game
+/* GAME DIFFICULTY 
+ * in squareOne 			can be: 1..3
+ * in circleOne/squareTwo	can be: 1..5 */
+let gameDifficulty;
+
 
-const hip = "143.107.45.11"; // Host ip
 
-// Colors available
+// Colors
 const colors = {
+	white: "#fff",
+	black: "#000",
+	gray: "#708090",
+
 	// used in text
-	green: 		"#00804d",
-	darkRed: 	"#330000",
-	blue: 		"#003cb3",
+	green: "#00804d",
+	blue: "#003cb3",
+
+	darkRed: "#330000",
 	mediumBlue: "#000080",
-	black: 		"#000000",
-	almostWhite: "#f0f5f5",
+
 	// difficulty stairs
-	diffBlue: 	"0x99b3ff",
-	diffRed: 	"0xff6666",
-	diffPurple: "0xb366ff",
+	diffBlue: "#99b3ff",
+	diffRed: "#ff6666",
+	diffPurple: "#b366ff",
+
 	// Background color
-	blueBckg: 		0xcce5ff, // default 
-	blueBckgLevel: 	0xa8c0e6, // in gameSquareOne (used for floor gap)
+	blueBckg: "#cce5ff", // default 
+	blueBckgLevel: "#a8c0e6", // in squareOne (used for floor gap)
+
 	// ok button in name State
-	teal:			0x3d5c5c,
+	teal: "#3d5c5c",
+
 	// difficulty symbols and game color identifier 
-	darkBlue: 		0x31314e,
-	red: 			0xb30000,
-	lightBlue: 		0xefeff5,
-	// gameSquareTwo
-	darkRed_: 		0x330000,
-	lightRed: 		0xd27979,
-	lighterRed: 	0xf2d9d9,
-	darkGreen: 		0x1e2f2f,
-	lightGreen: 	0x83afaf,
-	lighterGreen: 	0xe0ebeb,
+	red: "#b30000",
+
+	darkBlue: "#183780",
+	lightBlue: "#efeff5",
+
+	// squareTwo
+	darkRed: "#330000",
+	lightRed: "#d27979",
+	lighterRed: "#2d9d9",
+
+	darkGreen: "#1e2f2f",
+	lightGreen: "#83afaf",
+	lighterGreen: "#e0ebeb",
 };
 
-// Text styles available
+// Text styles
 const textStyles = {
 
+	dafault: { font: "12px Arial", fill: colors.black, align: "center" },
+
 	// titles
 	title1: { font: "32px Arial", fill: colors.green, align: "center" },
 	title2: { font: "27px Arial", fill: colors.green, align: "center" },
+	title2right: { font: "27px Arial", fill: colors.green, align: 'right' },
 
 	overtitle: { font: "20px Arial", fill: colors.darkRed, align: "center" },
+	overtitlel: { font: "20px Arial", fill: colors.darkRed, align: "left" },
+	overtitler: { font: "20px Arial", fill: colors.darkRed, align: "right" },
 
 	subtitle1: { font: "27px Arial", fill: colors.blue, align: "center" },
 	subtitle2: { font: "27px Arial", fill: colors.black, align: "center" },
+	subtitle2l: { font: "27px Arial", fill: colors.black, align: "left" },
+	subtitle2r: { font: "27px Arial", fill: colors.black, align: "right" },
 
 	// button labels
-	buttonLabel: { font: '34px Arial', fill: colors.almostWhite, align: 'center' },
-	difficultyLabel: { font: '25px Arial', fill: colors.almostWhite, align: 'center' },
+	buttonLabel: { font: '34px Arial', fill: colors.white, align: 'center' },
+	difficultyLabel: { font: '25px Arial', fill: colors.white, align: 'center' },
 	// in game labels
 	valueLabelBlue1: { font: '26px Arial', fill: colors.mediumBlue, align: 'center' },
-	valueLabelBlue2: { font: '20px Arial', fill: colors.mediumBlue, align: 'center' }, // numbers in gameSquareTwo
-	valueLabelBlue3: { font: '15px Arial', fill: colors.mediumBlue, align: 'center' }, // fractions numbers in gameSquareOne
+	valueLabelBlue2: { font: '20px Arial', fill: colors.mediumBlue, align: 'center' }, // numbers in squareTwo
+	valueLabelBlue3: { font: '15px Arial', fill: colors.mediumBlue, align: 'center' }, // fractions numbers in squareOne
 
 };
 
-// images, spritesheets and audio files
-const media = {
-
-	boot: function (type) {
-		image = [
-			// scenario
-			['birch',	imgsrc + 'scenario/birch.png'],
-			['bgimage', imgsrc + 'scenario/bg.jpg'],
-			['bgmap',	imgsrc + 'scenario/bg_map.png'],
-			['cloud', 	imgsrc + 'scenario/cloud.png'],
-			['floor', 	imgsrc + 'scenario/floor.png'],
-			['place_a', imgsrc + 'scenario/place_a.png'],
-			['place_b', imgsrc + 'scenario/place_b.png'],
-			['rock', 	imgsrc + 'scenario/rock.png'],
-			['road', 	imgsrc + 'scenario/road.png'],
-			['sign', 	imgsrc + 'scenario/sign.png'],
-			['tree1', 	imgsrc + 'scenario/tree.png'],
-			['tree2', 	imgsrc + 'scenario/tree2.png'],
-			['tree3', 	imgsrc + 'scenario/tree3.png'],
-			['tree4', 	imgsrc + 'scenario/tree4.png'],
-			// flags
-			['flag_BR', imgsrc + 'flag/BRAZ.jpg'],
-			['flag_FR', imgsrc + 'flag/FRAN.jpg'],
-			['flag_IT', imgsrc + 'flag/ITAL.png'],
-			['flag_PE', imgsrc + 'flag/PERU.jpg'],
-			['flag_US', imgsrc + 'flag/UNST.jpg'],
-			// Navigation icons on the top of the page
-			['back', 	imgsrc + 'navIcon/back.png'],
-			['block', 	imgsrc + 'navIcon/block.png'],
-			['help',	imgsrc + 'navIcon/help.png'],
-			['home', 	imgsrc + 'navIcon/home.png'],
-			['world', 	imgsrc + 'navIcon/language.png'],
-			['list', 	imgsrc + 'navIcon/menu.png'],
-			['pgbar', 	imgsrc + 'navIcon/progressBar.png'],
-			// mathematical operators 
-			['equal', 			imgsrc + 'operator/equal.png'],
-			['fractionLine', 	imgsrc + 'operator/fractionLine.png'],
-			//feedback options 
-			['h_arrow', 	imgsrc + 'help/arrow.png'],
-			['h_double', 	imgsrc + 'help/double.png'],
-			['down', 		imgsrc + 'help/down.png'],
-			['h_error', 	imgsrc + 'help/error.png'],
-			['h_ok', 		imgsrc + 'help/ok.png'],
-			['pointer', 	imgsrc + 'help/pointer.png'],
-		];
-		spritesheet = [
-			// Game Sprites
-			['kid_walk', imgsrc + 'character/kid/walk.png', 78, 175, 26],
-			// Menu icons n the top of the page
-			['audio', 	imgsrc + 'navIcon/audio_48x48.png', 48, 48, 2],
-			// feedback options 
-			['select', 	imgsrc + 'help/selectionBox.png', 310, 310, 2],
-		];
-		audio = [
-			// Sound effects
-			['beepSound', ['/Ifractions-web/assets/audio/beep.ogg', '/Ifractions-web/assets/audio/beep.mp3']],
-			['okSound', ['/Ifractions-web/assets/audio/ok.ogg', '/Ifractions-web/assets/audio/ok.mp3']],
-			['errorSound', ['/Ifractions-web/assets/audio/error.ogg', '/Ifractions-web/assets/audio/error.mp3']],
-		];
-		return media.returnType(type);
-	},
-
-	gameSquareOne: function (type) {
-		image = [
-			// scenario
-			['farm', 	imgsrc + 'scenario/farm.png'],
-			['garage', 	imgsrc + 'scenario/garage.png'],
-		];
-		spritesheet = [
-			// Game sprites
-			['tractor', imgsrc + 'character/tractor/frame.png', 201, 144, 10]
-		];
-		audio = [];
-		return media.returnType(type);
-	},
-
-	gameSquareTwo: function (type) {
-		image = [
-			// scenario
-			['house', 	imgsrc + 'scenario/house.png'],
-			['school', 	imgsrc + 'scenario/school.png'],
-		];
-		spritesheet = [
-			['kid_lost',	imgsrc + 'character/kid/lost.png', 72, 170, 6],
-			['kid_run', 	imgsrc + 'character/kid/run.png', 82, 178, 12],
-		];
-		audio = [];
-		return media.returnType(type);
-	},
-
-	gameCircleOne: function (type) {
-		image = [
-			// scenario
-			['house', 	imgsrc + 'scenario/house.png'],
-			['school', 	imgsrc + 'scenario/school.png'],
-			// Game Sprites
-			['balloon', 		imgsrc + 'character/balloon/airballoon_upper.png'],
-			['balloon_basket', 	imgsrc + 'character/balloon/airballoon_base.png'],
-		];
-		spritesheet = [
-			['kid_run', imgsrc + 'character/kid/run.png', 82, 178, 12],
-		];
-		audio = [];
-		return media.returnType(type);
-	},
-
-	menu: function (type) {
-		image = [
-			// level Icrons
-			['', imgsrc + 'game/squareOne_1.png', 'Square', 'A'], // Square I
-			['', imgsrc + 'game/squareOne_2.png', 'Square', 'B'], // Square II
-			['', imgsrc + 'game/circleOne_1.png', 'Circle', 'A'], // Circle I
-			['', imgsrc + 'game/circleOne_2.png', 'Circle', 'B'], // Circle II
-			['', imgsrc + 'game/squareTwo_3.png', 'Square', 'C']	// Square III
-		];
-		if (debugMode) {
-			for (let i = 0; i < 8; i++) {
-				image.push(['', imgsrc + 'game/squareTwo_3.png', 'Square', 'C']);
-			}
-		}
-		audio = [];
-		spritesheet = [];
-		return media.returnType(type);
-	},
+// Navigation icons on the top of the screen
+const navigationIcons = {
 
-	returnType: function (type) {
-		if (type == 'image') return image;
-		else if (type == 'spritesheet') return spritesheet;
-		else if (type == 'audio') return audio;
-	},
-
-};
+	// Add navigation icons on the top of the screen based on parameters
 
-// Control navigation icons on the top of the screen
-let iconSettings = {
+	func_addIcons: function (left_btn0, left_btn1, left_btn2, 	// first 3 icon spaces
+		right_btn0, right_btn1, 			// last 2 icon spaces
+		level, helpBtn) { 					// auxiliar variables
 
-	// Add navigation icons on the top of the screen based on parameters
-	func_addIcons: function (left_side, right_side, // icon side
-		left_btn0, left_btn1, left_btn2, // first 3 icon spaces
-		right_btn0, right_btn1, // last 2 icon spaces
-		level, helpBtn) { // auxiliar variables
+		this.level = level;
+		this.helpBtn = helpBtn;
 
 		let left_x = 10;
 		let right_x = defaultWidth - 50 - 10;
 
+		this.iconsList = [];
+
 		// 'Descriptive labels' for the navigation icons
 
-		if (left_side) this.left_text = game.add.text(left_x, 53, "", textStyles.overtitle);
+		this.left_text = game.add.text(left_x, 73, "", textStyles.overtitlel);
 
-		if (right_side) {
-			this.right_text = game.add.text(right_x + 50, 53, "", textStyles.overtitle);
-			this.right_text.anchor.setTo(1, 0.02);
-		}
+		this.right_text = game.add.text(right_x + 50, 73, "", textStyles.overtitler);
 
 		// 'Icons' on the LEFT side of the page
 
 		if (left_btn0) { // Return to select difficulty screen
-			const icon_back = game.add.sprite(left_x, 10, 'back');
-
-			icon_back.inputEnabled = true;
-			icon_back.input.useHandCursor = true;
-			icon_back.events.onInputDown.add(this.func_callState, { state: level });
-			icon_back.events.onInputOver.add(function () { this.left_text.text = lang.menu_back }, { left_text: this.left_text });
-			icon_back.events.onInputOut.add(function () { this.left_text.text = "" }, { left_text: this.left_text });
-			// Offsets value of x for next icon
-			left_x += 50;
+			const icon_back = game.add.image(left_x, 10, 'back');
+			this.iconsList.push(icon_back);
+			left_x += 50; // Offsets value of x for next icon
 		}
 
 		if (left_btn1) { // Return to main menu screen
-			const icon_list = game.add.sprite(left_x, 10, 'list');
-
-			icon_list.inputEnabled = true;
-			icon_list.input.useHandCursor = true;
-			icon_list.events.onInputDown.add(this.func_callState, { state: "menu" });
-			icon_list.events.onInputOver.add(function () { this.left_text.text = lang.menu_list }, { left_text: this.left_text });
-			icon_list.events.onInputOut.add(function () { this.left_text.text = "" }, { left_text: this.left_text });
-			// Offsets value of x for next icon
-			left_x += 50;
+			const icon_list = game.add.image(left_x, 10, 'menu');
+			this.iconsList.push(icon_list);
+			left_x += 50; // Offsets value of x for next icon
 		}
 
 		if (left_btn2) { // In some levels, shows solution to the game
-			const icon_help = game.add.sprite(left_x, 10, 'help');
-
-			icon_help.inputEnabled = true;
-			icon_help.input.useHandCursor = true;
-			icon_help.events.onInputDown.add(helpBtn);
-			icon_help.events.onInputOver.add(function () { this.left_text.text = lang.menu_help }, { left_text: this.left_text });
-			icon_help.events.onInputOut.add(function () { this.left_text.text = "" }, { left_text: this.left_text });
-			// Offsets value of x for next icon
-			left_x += 50;
+			const icon_help = game.add.image(left_x, 10, 'help');
+			this.iconsList.push(icon_help);
+			left_x += 50; // Offsets value of x for next icon
 		}
 
 		// 'Icons' on the RIGHT side of the page
 
 		if (right_btn0) { // Turns game audio on/off
-			this.icon_audio = game.add.sprite(right_x, 10, 'audio');
-			audioStatus ? this.icon_audio.frame = 0 : this.icon_audio.frame = 1;
-
-			this.icon_audio.inputEnabled = true;
-			this.icon_audio.input.useHandCursor = true;
-			this.icon_audio.events.onInputDown.add(function () { if (audioStatus) { audioStatus = false; this.icon_audio.frame = 1; } else { audioStatus = true; this.icon_audio.frame = 0; } }, { icon_audio: this.icon_audio });
-			this.icon_audio.events.onInputOver.add(function () { this.right_text.text = lang.audio }, { right_text: this.right_text });
-			this.icon_audio.events.onInputOut.add(function () { this.right_text.text = "" }, { right_text: this.right_text });
-			// Offsets value of x for next icon
-			right_x -= 50;
+			this.icon_audio = game.add.sprite(right_x, 10, 'audio', 1);
+			audioStatus ? this.icon_audio.curFrame = 0 : this.icon_audio.curFrame = 1;
+			this.iconsList.push(this.icon_audio);
+			right_x -= 50; // Offsets value of x for next icon
 		}
 
 		if (right_btn1) { // Return to select language screen
-			this.icon_world = game.add.sprite(right_x, 10, 'world');
-
-			this.icon_world.inputEnabled = true;
-			this.icon_world.input.useHandCursor = true;
-			this.icon_world.events.onInputDown.add(this.func_callState, { state: "language" });
-			this.icon_world.events.onInputOver.add(function () { this.right_text.text = lang.menu_world }, { right_text: this.right_text });
-			this.icon_world.events.onInputOut.add(function () { this.right_text.text = "" }, { right_text: this.right_text });
-			// Offsets value of x for next icon
-			right_x -= 50;
+			icon_world = game.add.image(right_x, 10, 'language');
+			this.iconsList.push(icon_world);
+			right_x -= 50; // Offsets value of x for next icon
 		}
 
 	},
 
-	// refresh values of x for icons when menu screen move sideways
-	func_refreshRightIcons_x: function (newWidth) {
-		this.right_text.x = newWidth - 10;
-		this.icon_audio.x = newWidth - 50 - 10;
-		this.icon_world.x = newWidth - 50 - 50 - 10;
-	},
-
-	func_callState: function () {
+	func_CallScreen: function (screen) {
 
-		if (audioStatus) sound.beepSound.play();
+		if (audioStatus) game.audio.beepSound.play();
 
-		game.state.start(this.state);
+		game.event.clear(self);
 
-	}
+		screen.preload();
 
-};
+	},
 
-let loadLangs = function (url) {
+	func_onInputDown: function (x, y) {
+
+		navigationIcons.iconsList.forEach(cur => {
+
+			const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+				(x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+			if (valid) {
+				if (cur.name == 'back') navigationIcons.func_CallScreen(navigationIcons.level);
+				else if (cur.name == 'menu') navigationIcons.func_CallScreen(menuScreen);
+				else if (cur.name == 'help') navigationIcons.helpBtn();
+				else if (cur.name == 'language') navigationIcons.func_CallScreen(langScreen);
+				else if (cur.name == 'audio') {
+					if (audioStatus) {
+						audioStatus = false;
+						navigationIcons.icon_audio.curFrame = 1;
+					} else {
+						audioStatus = true;
+						navigationIcons.icon_audio.curFrame = 0;
+					}
+					game.render.all();
+				}
+			}
+		});
+	},
 
-	lang = {};
+	func_onInputOver: function (x, y) {
 
-	var init = {
-		mode: "same-origin"
-	};
+		let flag = false;
 
-	fetch(url, init)
+		navigationIcons.iconsList.forEach(cur => {
 
-		.then(function (response) {
-			return response.text();
-		})
+			const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+				(x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
 
-		.then(function (text) {
+			if (valid) {
 
-			let msg = text.split("\n");
+				flag = true;
 
-			msg.forEach((temp) => {
+				if (cur.name == 'back') navigationIcons.left_text.name = game.lang.menu_back;
+				else if (cur.name == 'menu') navigationIcons.left_text.name = game.lang.menu_list;
+				else if (cur.name == 'help') navigationIcons.left_text.name = game.lang.menu_help;
 
-				try {
+				else if (cur.name == 'language') navigationIcons.right_text.name = game.lang.menu_world;
+				else if (cur.name == 'audio') navigationIcons.right_text.name = game.lang.audio;
 
-					let msg = temp.split("=");
+			}
 
-					lang[msg[0].trim()] = msg[1].trim();
+		});
 
-				} catch { console.log("erro de sintaxe corrigido"); }
+		if (!flag) {
+			navigationIcons.left_text.name = "";
+			navigationIcons.right_text.name = "";
+		} else {
+			document.body.style.cursor = "pointer";
+		}
 
-			});
+	}
 
-		});
+};
 
-}
+// Send game information to database 
+const postScore = function (extraData) {
 
-let loadAudios = function (audiosURL) {
+	// Create some variables we need to send to our PHP file
+	const data = "s_ip=143.107.45.11"
+		+ "&s_name=" + playerName
+		+ "&s_lang=" + langString
+		+ extraData;
 
-	sound = {};
+	const url = "php/save.php";
 
-	var init = {
-		mode: "same-origin",
-	};
+	const hr = new XMLHttpRequest();
 
-	audiosURL.forEach((item) => {
+	hr.open("POST", url, true);
 
-		fetch(item[1][1], init)
+	hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
 
-			.then(response => response.blob())
+	hr.onreadystatechange = function () {
+		if (debugMode) console.log(hr);
+		if (hr.readyState == 4 && hr.status == 200) {
+			if (debugMode) console.log(hr.responseText);
+		}
+	}
 
-			.then(function (myBlob) {
-				sound[item[0]] = new Audio(URL.createObjectURL(myBlob));
-			})
+	// Send the data to PHP now... and wait for response to update the status div
+	hr.send(data); // Actually execute the request
 
-	});
+	if (debugMode) {
+		console.log("processing...");
+		console.log(data);
+	}
 
 };

+ 261 - 212
js/map.js

@@ -1,315 +1,364 @@
-/*
-    let mapState = {
-        create: function(){},
-        update: function(){},
-        ---------------------------- end of phaser functions
-        func_loadGame: function(){},
-    }
-
-    let endState = {
-        create: function(){},
-        update: function(){},
-        ---------------------------- end of phaser functions
-    };
-*/
-
 // MAP SCREEN: game map where character advances as he passes a level
-let mapState = {
+const mapScreen = {
+
+    preload: function () {
+
+        document.body.style.cursor = "auto";
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
+
+        self = this;
+
+        // NOTHING TO LOAD HERE 
+        mapScreen.create();
+
+    },
 
     create: function () {
 
-        // Background
+        game.render.clear();
+
+        // Background color
+        game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
+
+        // map
         game.add.image(0, 40, 'bgmap');
 
         // Calls function that loads navigation icons
-        iconSettings.func_addIcons(true, false,
-            true, true, false,
-            false, false,
-            'difficulty', false);
+        navigationIcons.func_addIcons(true, true, false, // left icons
+            false, false, // right icons
+            difficultyScreen, false);
 
         // Progress bar
-        let percentText = completedLevels * 25;
-        let percentBlocks = completedLevels;
+        const percentText = completedLevels * 25;
 
-        for (let p = 0; p < percentBlocks; p++) {
-            let block = game.add.image(660 + p * 37.5, 10, 'block');
-            block.scale.setTo(2.6, 1);
-        }
-
-        game.add.text(820, 10, percentText + '%', textStyles.subtitle2);
-        game.add.text(650, 10, lang.difficulty + ' ' + levelDifficulty, textStyles.subtitle2).anchor.setTo(1, 0);
-        game.add.image(660, 10, 'pgbar');
+        if (completedLevels != 0) game.add.graphic.rect(660, 10, completedLevels * 37.5, 35, undefined, 0, colors.gray, 1);
+        game.add.graphic.rect(661, 11, 149, 34, colors.black, 3, undefined, 1);
+        game.add.text(820, 38, percentText + '%', textStyles.subtitle2l);
+        game.add.text(650, 38, game.lang.difficulty + ' ' + gameDifficulty, textStyles.subtitle2r);
 
-        // Road
+        // Map positions
         this.points = {
-            'x': [90, 204, 318, 432, 546, 660],
-            'y': [486, 422, 358, 294, 230, 166]
+            x: [90, 204, 318, 432, 546, 660],
+            y: [486, 422, 358, 294, 230, 166]
         };
 
-        if (currentGameState == "gameSquareOne") {
+        if (gameTypeString == "squareOne") {
             //Garage
-            let garage = game.add.image(this.points.x[0], this.points.y[0], 'garage');
-            garage.scale.setTo(0.4);
-            garage.anchor.setTo(0.5, 1);
+            game.add.image(this.points.x[0], this.points.y[0], 'garage', 0.4).anchor(0.5, 1);
             //Farm
-            let farm = game.add.image(this.points.x[5], this.points.y[5], 'farm');
-            farm.scale.setTo(0.6);
-            farm.anchor.setTo(0.1, 0.7);
+            game.add.image(this.points.x[5], this.points.y[5], 'farm', 0.6).anchor(0.1, 0.7);
         } else {
             //House
-            let house = game.add.image(this.points.x[0], this.points.y[0], 'house');
-            house.scale.setTo(0.7);
-            house.anchor.setTo(0.7, 0.8);
+            game.add.image(this.points.x[0], this.points.y[0], 'house', 0.7).anchor(0.7, 0.8);
             //School
-            let school = game.add.image(this.points.x[5], this.points.y[5], 'school');
-            school.scale.setTo(0.35);
-            school.anchor.setTo(0.2, 0.7);
+            game.add.image(this.points.x[5], this.points.y[5], 'school', 0.35).anchor(0.2, 0.7);
         }
 
-        //Trees and Rocks
-
+        // Rocks and bushes
         const rocks = {
-            'x': [156, 275, 276, 441, 452, 590, 712],
-            'y': [309, 543, 259, 156, 419, 136, 316]
-        }
+            x: [156, 275, 276, 441, 452, 590, 712],
+            y: [309, 543, 259, 156, 419, 136, 316],
+            type: [1, 1, 2, 1, 2, 2, 2]
+        };
 
-        const r_types = [1, 1, 2, 1, 2, 2, 2];
-
-        for (let i = 0; i < r_types.length; i++) {
-            if (r_types[i] == 1) {
-                let sprite = game.add.image(rocks.x[i], rocks.y[i], 'rock');
-                sprite.scale.setTo(0.32);
-                sprite.anchor.setTo(0.5, 0.95);
-            } else if (r_types[i] == 2) {
-                let sprite = game.add.image(rocks.x[i], rocks.y[i], 'birch');
-                sprite.scale.setTo(0.4);
-                sprite.anchor.setTo(0.5, 0.95);
+        for (let i in rocks.type) {
+            if (rocks.type[i] == 1) {
+                game.add.image(rocks.x[i], rocks.y[i], 'rock', 0.32).anchor(0.5, 0.95);
+            } else {
+                game.add.image(rocks.x[i], rocks.y[i], 'bush', 0.4).anchor(0.5, 0.95);
             }
         }
 
+        // Trees
         const trees = {
-            'x': [105, 214, 354, 364, 570, 600, 740, 779],
-            'y': [341, 219, 180, 520, 550, 392, 488, 286]
-        }
-
-        const t_types = [2, 4, 3, 4, 1, 2, 4, 4];
+            x: [105, 214, 354, 364, 570, 600, 740, 779],
+            y: [341, 219, 180, 520, 550, 392, 488, 286],
+            type: [2, 4, 3, 4, 1, 2, 4, 4]
+        };
 
-        for (let i = 0; i < t_types.length; i++) {
-            const sprite = game.add.image(trees.x[i], trees.y[i], 'tree' + t_types[i]);
-            sprite.scale.setTo(0.6);
-            sprite.anchor.setTo(0.5, 0.95);
+        for (let i in trees.type) {
+            game.add.image(trees.x[i], trees.y[i], 'tree' + trees.type[i], 0.6).anchor(0.5, 0.95);
         }
 
         // Map positions
-        for (let p = 1; p < this.points.x.length - 1; p++) {
+        for (let i = 1; i < this.points.x.length - 1; i++) {
 
-            const aux = (p < mapPosition || (mapCanMove && p == mapPosition)) ? 'place_b' : 'place_a';
-            const place = game.add.image(this.points.x[p], this.points.y[p], aux);
-            place.anchor.setTo(0.5, 0.5);
-            place.scale.setTo(0.3);
+            const aux = (i < mapPosition || (mapMove && i == mapPosition)) ? 'place_on' : 'place_off';
 
-            const sign = game.add.image(this.points.x[p] - 20, this.points.y[p] - 60, 'sign');
-            sign.anchor.setTo(0.5, 1);
-            sign.scale.setTo(0.4);
+            // Map road positions
+            game.add.image(this.points.x[i], this.points.y[i], aux, 0.3).anchor(0.5, 0.5);
+
+            // Level signs
+            game.add.image(this.points.x[i] - 20, this.points.y[i] - 60, 'sign', 0.4).anchor(0.5, 1);
+            game.add.text(this.points.x[i] - 20, this.points.y[i] - 79, i, textStyles.difficultyLabel);
 
-            if (p > 0 && p < this.points.x.length - 1) {
-                const text = game.add.text(this.points.x[p] - 23, this.points.y[p] - 84, p, textStyles.difficultyLabel);
-                text.anchor.setTo(0.35, 0.5);
-            }
         }
 
-        if (currentGameState == "gameSquareOne") {
-            this.character = game.add.sprite(this.points.x[mapPosition], this.points.y[mapPosition], 'tractor');
+        // Game Character 
+        if (gameTypeString == "squareOne") {
 
             if (sublevelType == 'Plus') {
-                this.character.animations.add('walk', [0, 1, 2, 3, 4]);
-                this.character.scale.setTo(0.5);
+                this.character = game.add.sprite(this.points.x[mapPosition], this.points.y[mapPosition], 'tractor', 0, 0.5);
+                this.character.animation = ["green_tractor", [0, 1, 2, 3, 4], 3];
             } else {
-                this.character.animations.add('walk', [5, 6, 7, 8, 9]);
-                this.character.scale.setTo(-0.5, 0.5);
+                this.character = game.add.sprite(this.points.x[mapPosition], this.points.y[mapPosition], 'tractor', 10, 0.5);
+                this.character.animation = ["red_tractor", [10, 11, 12, 13, 14], 3];
             }
 
-            this.character.animations.play('walk', 5, true);
+            this.character.rotate = -30; // 25 anticlock
 
         } else {
-            this.character = game.add.sprite(this.points.x[mapPosition], this.points.y[mapPosition], 'kid_run');
-            this.character.animations.add('run');
-            this.character.animations.play('run', 6, true);
-            this.character.scale.setTo(0.5);
+
+            this.character = game.add.sprite(this.points.x[mapPosition], this.points.y[mapPosition], 'kid_run', 0, 0.4);
+            this.character.animation = ["kid", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3];
+
         }
 
-        this.character.anchor.setTo(0.5, 1);
-        this.character.angle -= 25;
+        this.character.anchor(0.5, 1);
+        game.animation.play(this.character.animation[0]);
 
-        game.physics.arcade.enable(this.character);
 
-        // Delay to next level
         this.count = 0;
-        this.wait = 60;
+
+        const speed = 60;
+        const xA = this.points.x[mapPosition];
+        const yA = this.points.y[mapPosition];
+        const xB = this.points.x[mapPosition + 1];
+        const yB = this.points.y[mapPosition + 1];
+        self.speedX = (xB - xA) / speed;
+        self.speedY = (yA - yB) / speed;
+
+        game.event.add("click", mapScreen.func_onInputDown);
+        game.event.add("mousemove", mapScreen.func_onInputOver);
+
+        game.render.all();
+
+        game.loop.start(this);
 
     },
 
     update: function () {
 
-        // Wait 2 seconds before moving or staring a game
-        this.count++;
-        if (this.count <= this.wait) return;
+        let endUpdate = false;
 
-        if (!mapCanMove) {
-            this.func_loadGame();
-        }
+        self.count++;
+
+        if (self.count > 60) { // Wait 1 second before moving or staring a game
+
+            if (mapMove) { // move character on screen for 1 second
+                self.character.x += self.speedX;
+                self.character.y -= self.speedY;
+                if (Math.ceil(self.character.x) >= self.points.x[mapPosition + 1]) { // reached next map position
+                    mapMove = false;
+                    mapPosition++; //set new next position
+                }
+            }
 
-        // If momevent is enabled, move to next point from actual
-        if (mapCanMove) {
-            game.physics.arcade.moveToXY(
-                this.character,
-                this.points.x[mapPosition + 1],
-                this.points.y[mapPosition + 1],
-                100
-            );
-
-            // I kid/tractor reached the end, stop movement
-            if (Math.ceil(this.character.x) == this.points.x[mapPosition + 1] || Math.ceil(this.character.y) == this.points.y[mapPosition + 1]) {
-                mapCanMove = false;
-                mapPosition += 1; //Update position
+            if (!mapMove) {
+                endUpdate = true;
             }
+
+
+        }
+
+        game.render.all();
+
+        if (endUpdate) {
+            game.animation.stop(self.character.animation[0]);
+            self.func_loadGame();
         }
+
     },
 
-    //MapLoading function
+
+
+    /* EVENT HANDLER */
+
+    func_onInputDown: function (mouseEvent) {
+
+        navigationIcons.func_onInputDown(mouseEvent.offsetX, mouseEvent.offsetY);
+
+    },
+
+    func_onInputOver: function (mouseEvent) {
+
+        navigationIcons.func_onInputOver(mouseEvent.offsetX, mouseEvent.offsetY);
+
+    },
+
+
+
+    /* GAME FUNCTIONS */
+
     func_loadGame: function () {
 
-        if (audioStatus) sound.beepSound.play();
+        if (audioStatus) game.audio.beepSound.play();
 
-        if (mapPosition <= 4) game.state.start(currentGameState);
-        else game.state.start('end');
+        if (mapPosition <= 4) gameType.preload();
+        else endScreen.preload();
 
-    }
+    },
 
 };
 
 // ENDING SCREEN: animation after a full level is completed
-let endState = {
+const endScreen = {
+
+    preload: function () {
+
+        document.body.style.cursor = "auto";
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
+
+        self = this;
+
+        // NOTHING TO LOAD HERE
+        endScreen.create();
+
+    },
 
     create: function () {
 
+        game.render.clear();
+        self.preAnimate = false;
+        self.animate = true;
+
+        // Background color
+        game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
+
         // Background
         game.add.image(0, 0, 'bgimage');
 
         //Clouds
         game.add.image(300, 100, 'cloud');
         game.add.image(660, 80, 'cloud');
-        game.add.image(110, 85, 'cloud').scale.setTo(0.8);
+        game.add.image(110, 85, 'cloud', 0.8);
 
         //Floor
-        for (let i = 0; i < 9; i++) {
-            game.add.image(i * 100, 501, 'floor');
-        }
+        for (let i = 0; i < 9; i++) { game.add.image(i * 100, 501, 'floor'); }
 
         // Progress bar
-        for (let p = 0; p < 5; p++) {
-            let block = game.add.image(660 + p * 30, 10, 'block');
-            block.scale.setTo(2, 1); //Scaling to double width
-        }
-        game.add.text(820, 10, '100%', textStyles.subtitle2);
-        game.add.text(650, 10, lang.difficulty + ' ' + levelDifficulty, textStyles.subtitle2).anchor.setTo(1, 0);
-        game.add.image(660, 10, 'pgbar');
-
-        game.add.sprite(30, 280, 'tree4');
-        game.add.sprite(360, 250, 'tree2');
-
-        if (currentGameState == 'gameCircleOne') {
-
-            //School and trees
-            game.add.sprite(600, 222, 'school').scale.setTo(0.7);
-            //kid
-            this.kid = game.add.sprite(0, -152, 'kid_run');
-            this.kid.anchor.setTo(0.5, 0.5);
-            this.kid.scale.setTo(0.7);
-            this.kid.animations.add('walk', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
-            //globo
-            this.balloon = game.add.sprite(0, -260, 'balloon');
-            this.balloon.anchor.setTo(0.5, 0.5);
-            this.basket = game.add.sprite(0, -150, 'balloon_basket');
-            this.basket.anchor.setTo(0.5, 0.5);
-
-        } else if (currentGameState == 'gameSquareTwo') {
-
-            //School and trees
-            game.add.sprite(600, 222, 'school').scale.setTo(0.7);
-            //kid
-            this.kid = game.add.sprite(0, 460, 'kid_run');
-            this.kid.anchor.setTo(0.5, 0.5);
-            this.kid.scale.setTo(0.7);
-            this.kid.animations.add('walk', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
-
-            this.kid.animations.play('walk', 6, true);
-
-        } else if (currentGameState == 'gameSquareOne') {
-
-            //Farm and trees
-            game.add.sprite(650, 260, 'farm').scale.setTo(1.1);
-            //tractor
-            this.tractor = game.add.sprite(0, 490, 'tractor');
-            this.tractor.anchor.setTo(0.5, 0.5);
-            this.tractor.scale.setTo(0.8);
-            if (sublevelType == 'Plus') this.tractor.animations.add('tractor_run', [0, 1, 2, 3, 4]);
-            else {
-                this.tractor.animations.add('tractor_run', [5, 6, 7, 8, 9]);
-                this.tractor.scale.x *= -1;
-            }
-            this.tractor.animations.play('tractor_run', 5, true);
+        game.add.graphic.rect(660, 10, 4 * 37.5, 35, undefined, 0, colors.gray, 1); // progress
+        game.add.graphic.rect(661, 11, 149, 34, colors.black, 3, undefined, 1); // box
+        game.add.text(820, 38, '100%', textStyles.subtitle2l);
+        game.add.text(650, 38, game.lang.difficulty + ' ' + gameDifficulty, textStyles.subtitle2r);
+
+        game.add.image(360, 545, 'tree4', 0.7).anchor(0, 1);
+
+        // Level character
+        switch (gameTypeString) {
+
+            case 'circleOne':
+
+                this.preAnimate = true;
+                this.animate = false;
+
+                //School
+                game.add.image(600, 222, 'school', 0.7);
+
+                //kid
+                this.character = game.add.sprite(0, -152, 'kid_run', 0, 0.7);
+                this.character.anchor(0.5, 0.5);
+                this.character.animation = ['move', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 3];
+
+                // balloon
+                this.balloon = game.add.image(0, -260, 'balloon');
+                this.balloon.anchor(0.5, 0.5);
+
+                this.basket = game.add.image(0, -150, 'balloon_basket');
+                this.basket.anchor(0.5, 0.5);
+
+                break;
+
+            case 'squareTwo':
+
+                //School
+                game.add.image(600, 222, 'school', 0.7);
+
+                //kid
+                this.character = game.add.sprite(0, 460, 'kid_run', 6, 0.7);
+                this.character.anchor(0.5, 0.5);
+                this.character.animation = ['move', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 3];
+
+                break;
+
+            case 'squareOne':
+
+                //Farm
+                game.add.image(650, 260, 'farm', 1.1);
+
+                //tractor
+                this.character = game.add.sprite(0, 490, 'tractor', 0, 0.7);
+                this.character.anchor(0.5, 0.5);
+                if (sublevelType == 'Plus') {
+                    this.character.animation = ['move', [0, 1, 2, 3, 4], 4];
+                } else {
+                    this.character.curFrame = 10;
+                    this.character.animation = ['move', [10, 11, 12, 13, 14], 4];
+                }
+
+                break;
 
-        } else {
-            if (debugMode) console.log("Error! Name of the game state is not valid!");
         }
 
+        if (this.animate) game.animation.play(this.character.animation[0]);
+
+        game.add.image(30, 585, 'tree4', 0.85).anchor(0, 1);
+
+        game.render.all();
+
+        game.loop.start(this);
+
     },
 
     update: function () {
 
-        if (currentGameState == 'gameCircleOne') {
+        // Balloon falling
+        if (self.preAnimate) {
 
-            if (this.kid.y >= 460) {
-                this.kid.animations.play('walk', 6, true);
-                if (this.kid.x <= 700) {
-                    this.kid.x += 2;
-                } else {
-                    completedLevels = 0;
-                    game.state.start('menu');
-                }
-            } else {
-                this.balloon.y += 2;
-                this.basket.y += 2;
-                this.kid.y += 2;
+            if (self.character.y < 460) {
 
-                this.balloon.x += 1;
-                this.basket.x += 1;
-                this.kid.x += 1;
-            }
+                self.balloon.y += 2;
+                self.basket.y += 2;
+                self.character.y += 2;
 
-        } else if (currentGameState == 'gameSquareTwo') {
+                self.balloon.x++;
+                self.basket.x++;
+                self.character.x++;
 
-            if (this.kid.x <= 700) {
-                this.kid.x += 2;
             } else {
-                completedLevels = 0;
-                game.state.start('menu');
+
+                self.preAnimate = false;
+                self.animate = true;
+                game.animation.play(self.character.animation[0]);
+
             }
 
-        } else if (currentGameState == 'gameSquareOne') {
+        }
+
+        // character running
+        if (self.animate) {
+
+            if (self.character.x <= 700) {
+
+                self.character.x += 2;
 
-            if (this.tractor.x <= 700) {
-                this.tractor.x += 2;
             } else {
+
+                animate = false;
                 completedLevels = 0;
-                game.state.start('menu');
+                game.animation.stop(self.character.animation[0]);
+                menuScreen.preload();
+
             }
 
-        } else {
-            if (debugMode) console.log("Error! Name of the game state is not valid!");
         }
 
+        game.render.all();
+
     },
 
-}
+};

+ 114 - 109
js/menu.js

@@ -1,189 +1,194 @@
-/*
-    let menuState = {
-        preload: function(){},
-        create: function(){},
-        ---------------------------- end of phaser functions
-        func_loadGame: function(){},
-        func_showTitle: function(){},
-        func_clearTitle: function(){},
-    }
-*/
-
 // MENU SCREEN: main menu of the game where the user can select the level he wants to play
-let menuState = {
+const menuScreen = {
 
     preload: function () {
-        for (let i = 0, menuIcons = media.menu('image'); i < menuIcons.length; i++) {
-            game.load.image('game' + i, menuIcons[i][1]);
-        }
+
+        document.body.style.cursor = "auto";
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
+
+        self = this;
+
+        // LOADING MEDIA
+        game.load.image(game.url.menu.image);
+
     },
 
     create: function () {
+        game.render.clear();
 
-        // SCREEN SETTINGS
+        // Background color
+        game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
 
-        // The menu screen can hold up to 8 levels without needing a side scroller
-        // If there are more than 8 levels, sets 'extraWidth'
-        if (media.menu('image').length > 8) {
-            const aux = media.menu('image').length - 8;
-            this.extraWidth = (aux % 2 == 0) ? (aux / 2) * 235 : ((aux + 1) / 2) * 235; // Each extra column holds 2 levels 
-        } else {
-            this.extraWidth = 0;
+        // Adds floor
+        for (let i = 0; i < defaultWidth / 100; i++) {
+            game.add.image(i * 100, 501, 'floor');
         }
 
-        // Refreshes stage size to have the 'extraWidth' if necessary (visible part of the screen remains the default)
-        this.game.world.setBounds(0, 0, this.game.world.width + this.extraWidth, this.game.world.height);
-
         // LABELS
 
         // Adds Overtitle: Welcome, <player name>!
-        this.player_info = game.add.text(this.game.world.centerX - this.extraWidth / 2, 40, lang.welcome + ", " + playerName + "!", textStyles.overtitle);
-        this.player_info.anchor.setTo(0.5, 0.5);
+        game.add.text(defaultWidth / 2, 40, game.lang.welcome + ", " + playerName + "!", textStyles.overtitle);
 
         // Adds Title : Select a game
-        this.title = game.add.text(this.game.world.centerX - this.extraWidth / 2, 80, lang.menu_title, textStyles.title1);
-        this.title.anchor.setTo(0.5, 0.5);
+        game.add.text(defaultWidth / 2, 80, game.lang.menu_title, textStyles.title1);
 
         // Adds Subtitle : <game mode> 
-        this.lbl_game = game.add.text(this.game.world.centerX - this.extraWidth / 2, 110, "", textStyles.subtitle1);
-        this.lbl_game.anchor.setTo(0.5, 0.5);
+        this.lbl_game = game.add.text(defaultWidth / 2, 110, "", textStyles.subtitle1);
 
         // ICONS
 
         // Calls function that loads navigation icons
-        iconSettings.func_addIcons(false, true,
-            false, false, false,
+        navigationIcons.func_addIcons(false, false, false,
             true, true,
             false, false);
 
-        // BACKGROUND
-
-        // Adds floor
-        for (let i = 0, width = this.game.world.width; i < width / 100; i++) {
-            game.add.image(i * 100, 501, 'floor');
-        }
-
         // GAME LEVELS BUTTONS
 
         // Base coordinates for level buttons
         let x = -350; // First column
         let y = -70; // Top line
-        const menuObjList = [];
 
-        for (let i = 0, length = media.menu('image').length; i < length; i++) {
+        menuScreen.menuObjList = [];
+
+        for (let i in game.url.menu.image) {
+
             // Adds level buttons
-            menuObjList[i] = game.add.sprite(defaultWidth / 2 + x, this.game.world.centerY + y, 'game' + i);
-            menuObjList[i].anchor.setTo(0.5, 0.5);
-            // Events
-            menuObjList[i].inputEnabled = true;
-            menuObjList[i].input.useHandCursor = true;
-            menuObjList[i].events.onInputDown.add(this.func_loadGame, { levelType: media.menu('image')[i][3], shape: media.menu('image')[i][2], game: this.game, extraWidth: this.extraWidth });
-            menuObjList[i].events.onInputOver.add(this.func_showTitle, { levelType: media.menu('image')[i][3], shape: media.menu('image')[i][2], menu: menuObjList[i], lbl_game: this.lbl_game });
-            menuObjList[i].events.onInputOut.add(this.func_clearTitle, { menu: menuObjList[i], lbl_game: this.lbl_game });
+            //try {
+            this.menuObjList[i] = game.add.image(defaultWidth / 2 + x, defaultHeight / 2 + y, 'game' + i);
+            this.menuObjList[i].anchor(0.5, 0.5);
+            this.menuObjList[i].levelType = game.url.menu.image[i][3];
+            this.menuObjList[i].gameShape = game.url.menu.image[i][2];
+            //}catch (e) { console.log("Erro:",e)}
             // Refreshes coordinates for next button
-            if (i % 2 == 0) {
-                y = 90; // The next will be at the bottom line
-            } else {
+            if (i % 2 == 0) y = 90; // The next will be at the bottom line
+            else {
                 y = -70; // The next will be at the top line
                 x += 235; // The next will be at the next column
             }
+
         }
 
-        // TURNING 'MOUSE INPUT CAPTURE' ON TO MANAGE PAGE SCROLL
-        this.input.mouse.capture = true;
+        game.event.add("click", menuScreen.func_onInputDown);
+        game.event.add("mousemove", menuScreen.func_onInputOver);
+
+        game.render.all();
 
     },
 
-    // MANAGES SIDE SCROLLING
-    update: function () {
 
-        // On mouse release calls function
-        if (this.input.activePointer.leftButton.isUp) {
-            this.inputUp();
-        }
 
-        // On mouse click calls function
-        if (this.input.activePointer.leftButton.isDown) {
-            this.inputDown();
-        }
+    /* EVENT HANDLER*/
+
+    func_onInputDown: function (mouseEvent) {
 
-        // If true side scrolls
-        if (this.isCameraMoving) {
-            // 'this.camera' is a shorthand for 'World.camera'
-            this.camera.x += (this.inputStartPosition.x - this.input.activePointer.x) / 10;
-
-            const move = (this.game.world.centerX - this.extraWidth / 2) + this.camera.x;;
-            // Elements that appear fixed in the screen
-            this.title.x = move;
-            this.lbl_game.x = move;
-            this.player_info.x = move;
-            iconSettings.func_refreshRightIcons_x((defaultWidth) + this.camera.x);
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+
+        for (let i in menuScreen.menuObjList) {
+
+            const cur = menuScreen.menuObjList[i];
+
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+            if (valid) {
+                menuScreen.func_loadGame(game.url.menu.image[i][3], game.url.menu.image[i][2]);
+                break;
+            }
         }
 
-    },
+        navigationIcons.func_onInputDown(x, y);
 
-    // ON RELEASE
-    inputUp: function () {
-        this.isCameraMoving = false;
     },
 
-    // ON CLICK
-    inputDown: function () {
-        if (!this.isCameraMoving) {
-            this.inputStartPosition = new Phaser.Point(this.input.activePointer.x, this.input.activePointer.y);
+    func_onInputOver: function (mouseEvent) {
+
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+        let flag = false;
+
+        menuScreen.menuObjList.forEach(cur => {
+
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+            if (valid) {
+                flag = true;
+                cur.scaleWidth = cur.scaleHeight = 1.05;
+                menuScreen.func_showTitle(cur.levelType, cur.gameShape);
+            } else {
+                cur.scaleWidth = cur.scaleHeight = 1;
+            }
+
+        });
+
+        if (!flag) {
+            menuScreen.func_clearTitle();
         }
-        // Allows side scrolling to be checked as true
-        this.isCameraMoving = true;
+
+        navigationIcons.func_onInputOver(x, y);
+
+        game.render.all();
+
     },
 
+
+
+    /* GAME FUNCTIONS */
+
     //calls the selected game menu screen
-    func_loadGame: function () {
+    func_loadGame: function (level, shape) {
 
-        // Sets stage width back to default
-        this.game.world.setBounds(0, 0, defaultWidth, this.game.world.height);
+        if (audioStatus) game.audio.beepSound.play();
 
-        if (audioStatus) sound.beepSound.play();
+        gameShape = shape;
+        levelType = level;
 
-        levelShape = this.shape;
-        levelType = this.levelType;
+        if (levelType == "C") gameTypeString = gameShape.toLowerCase() + "Two";
+        else gameTypeString = gameShape.toLowerCase() + "One";
 
-        if (levelType == "C") currentGameState = "game" + levelShape + "Two";
-        else currentGameState = "game" + levelShape + "One";
+        switch (gameTypeString) {
+            case 'squareOne': gameType = squareOne; break;
+            case 'squareTwo': gameType = squareTwo; break;
+            case 'circleOne': gameType = circleOne; break;
+            default: console.error("Game error: the name of the game is not valid");
+        }
 
-        if (debugMode) console.log("Game State: " + currentGameState + ", " + levelType);
+        if (debugMode) console.log("Game State: " + gameTypeString + ", " + levelType);
 
         // Calls level difficulty screen
-        game.state.start('difficulty');
+        difficultyScreen.preload();
 
     },
 
-    func_showTitle: function () {
+    func_showTitle: function (levelType, gameShape) {
 
         let title = "", type = "";
 
-        if (this.levelType == 'A') type = "I";
-        else if (this.levelType == 'B') type = "II";
-        else if (this.levelType == 'C') type = "III";
+        if (levelType == 'A') type = "I";
+        else if (levelType == 'B') type = "II";
+        else if (levelType == 'C') type = "III";
 
-        if (this.shape == "Circle") title += lang.circle_name;
-        else if (this.shape == "Square") title += lang.square_name;
+        if (gameShape == "Circle") title += game.lang.circle_name;
+        else if (gameShape == "Square") title += game.lang.square_name;
 
         if (type != "") title += " " + type;
 
         // Shows level title on the label
-        this.lbl_game.text = title;
-        // Increases size of button when mouse is on top of it
-        this.menu.scale.setTo(1.05);
+        menuScreen.lbl_game.name = title;
+
+        document.body.style.cursor = "pointer";
 
     },
 
     func_clearTitle: function () {
 
         // Removes text from label
-        this.lbl_game.text = "";
-        // changes button size back to default
-        this.menu.scale.setTo(1);
+        menuScreen.lbl_game.name = "";
 
+        document.body.style.cursor = "auto";
     }
 
 };

File diff suppressed because it is too large
+ 0 - 103065
js/phaser/phaser.js


File diff suppressed because it is too large
+ 0 - 1
js/phaser/phaser.map


File diff suppressed because it is too large
+ 0 - 28
js/phaser/phaser.min.js


+ 223 - 74
js/preMenu.js

@@ -1,86 +1,165 @@
-/*
-    let langState = {
-        create: function(){},
-        -------------------------------------- end of phaser functions
-        func_setLang: function(){} //calls loadState
-    };
-    
-    let loadState = {
-        preload: function(){},
-        create: function(){} //calls nameState
-        -------------------------------------- end of phaser functions
-    };
-        
-    let nameState = {
-        create: function(){},
-        -------------------------------------- end of phaser functions
-        func_checkEmptyName: function(){}
-        func_saveName: function(){}
-    };
-*/
+// Only called once
+const boot = {
+
+    preload: function () {
+
+        document.body.style.cursor = "auto";
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
+
+        self = this;
+
+        // LOADING MEDIA
+        game.load.audio(game.url.boot.audio);
+        game.load.image(game.url.boot.image);
+        game.load.sprite(game.url.boot.sprite);
+
+    },
+
+    create: function () {
+        // Calls first screen seen by the player
+        langScreen.preload();
+    }
+
+};
+
+
 
 // LANGUAGE SCREEN: the player can choose a preferred language for the game text to be displayed
-let langState = {
+const langScreen = {
+
+    preload: function () {
+
+        document.body.style.cursor = "auto";
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
+
+        self = this;
+
+        // NOTHING TO LOAD HERE
+        langScreen.create();
+
+    },
 
     create: function () {
 
-        // Sets stage width back to default (if we are back from 'menu' state where it can be changed) 
-        if (this.game.world.width != defaultWidth) this.game.world.setBounds(0, 0, defaultWidth, this.game.world.height);
+        game.render.clear();
+
+        // Background color
+        game.add.graphic.rect(0, 0, 900, 600, colors.white, 0, colors.blueBckg, 1);
 
         // Parameters for the elements on the screen
-        const langs = {
+        langScreen.listOfFlags = [];
+
+        langScreen.langs = {
             text: ['FRAÇÕES  ', 'FRAZIONI  ', 'FRACTIONS  ', 'FRACCIONES  ', 'FRACTIONS  '], // Language names
             flag: ['flag_BR', 'flag_IT', 'flag_US', 'flag_PE', 'flag_FR'], // Icon names
             lang: ['pt_BR', 'it_IT', 'en_US', 'es_PE', 'fr_FR'], // Parameters sent for language object
             x: [-220, -220, -220, 200, 200],
             y: [-180, 0, 180, -100, 100]
-        }
+        };
 
         // Create elements on screen  
-        for (let i = 0, length = langs.lang.length; i < length; i++) {
+        for (let i in this.langs.flag) {
 
             // Add text for language names
-            const language = game.add.text(this.game.world.centerX + langs.x[i], this.game.world.centerY + langs.y[i], langs.text[i], textStyles.title2);
-            language.anchor.setTo(1, 0.5);
+            game.add.text(defaultWidth / 2 + this.langs.x[i], defaultHeight / 2 + this.langs.y[i], this.langs.text[i], textStyles.title2right);
 
             // Add icons for flags
-            const flag = game.add.sprite(this.game.world.centerX + langs.x[i] + 100, this.game.world.centerY + langs.y[i], langs.flag[i]);
-            flag.anchor.setTo(0.5, 0.5);
-            flag.inputEnabled = true;
-            flag.input.useHandCursor = true;
-            flag.events.onInputDown.add(this.func_setLang, { langs_lang: langs.lang[i] });
-            flag.events.onInputOver.add(function () { this.flag.scale.setTo(1.05) }, { flag: flag });
-            flag.events.onInputOut.add(function () { this.flag.scale.setTo(1) }, { flag: flag });
+            const flag = game.add.image(defaultWidth / 2 + this.langs.x[i] + 100, defaultHeight / 2 + this.langs.y[i], this.langs.flag[i]);
+            flag.anchor(0.5, 0.5);
 
+            this.listOfFlags.push(flag);
         }
 
+        game.event.add("click", this.func_onInputDown);
+        game.event.add("mousemove", this.func_onInputOver);
+
+        game.render.all();
+
+    },
+
+
+
+    /* EVENT HANDLER*/
+
+    func_onInputDown: function (mouseEvent) {
+
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+
+        langScreen.listOfFlags.forEach(cur => {
+
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+            if (valid) {
+                for (let i in langScreen.langs.flag) {
+                    if (langScreen.langs.flag[i] == cur.name) {
+                        langScreen.func_setLang(self.langs.lang[i]);
+                    }
+                }
+            }
+        });
     },
 
+    func_onInputOver: function (mouseEvent) {
+
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+        let flag = false;
+
+        langScreen.listOfFlags.forEach(cur => {
+
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+            if (valid) {
+                flag = true;
+                cur.scaleHeight = cur.scaleWidth = 1.05;
+            } else {
+                cur.scaleHeight = cur.scaleWidth = 1;
+            }
+        });
+
+        if (flag) document.body.style.cursor = "pointer";
+        else document.body.style.cursor = "auto";
+
+        game.render.all();
+
+    },
+
+
+
+    /* GAME FUNCTIONS */
+
     // Calls loading screen while loads language
-    func_setLang: function () {
+    func_setLang: function (selectedLang) {
         // Saves language name e.g 'pt_BR'
-        langString = this.langs_lang;
+        langString = selectedLang;
         // Calls loading screen
-        game.state.start('load');
+        loadLang.preload();
     }
 
 };
 
 
 
-
 // Loads selected language to be able to translate the game text
-let loadState = {
+const loadLang = {
 
     preload: function () {
 
-        // Progress bar
-        const progressBar = game.add.sprite(game.world.centerX, game.world.centerY, 'progressBar');
-        progressBar.anchor.setTo(0.5, 0.5);
-        game.load.setPreloadSprite(progressBar);
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
 
-        // Loads selected language
-        loadLangs('/Ifractions-web/assets/lang/' + langString);
+        self = this;
+
+        // LOADING MEDIA : selected language
+        game.load.lang('assets/lang/' + langString);
 
     },
 
@@ -91,9 +170,9 @@ let loadState = {
         // Make sure to only ask for player name on the first time oppening the game
         if (this.firstTime == undefined) {
             this.firstTime = false;
-            game.state.start('name'); // first time opening ifractions ('language' >> 'name' >> 'menu')
+            nameScreen.preload(); // first time opening ifractions ('language' >> 'name' >> 'menu')
         } else {
-            game.state.start('menu'); // if changing language during the game ('language' >>>> 'menu')         
+            menuScreen.preload(); // if changing language during the game ('language' >>>> 'menu')         
         }
 
     }
@@ -102,56 +181,126 @@ let loadState = {
 
 
 
-
 // NAME SCREEN: asks for player's name 
-let nameState = {
+const nameScreen = {
+
+    preload: function () {
+
+        document.body.style.cursor = "auto";
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
+
+        self = this;
+
+        // NOTHING TO LOAD HERE
+        nameScreen.create();
+
+    },
 
     create: function () {
 
+        game.render.clear();
+
+        // Background color
+        game.add.graphic.rect(0, 0, 900, 600, colors.white, 0, colors.blueBckg, 1);
+
         // Set title and warning text
 
-        const title = game.add.text(this.game.world.centerX, this.game.world.centerY - 100, lang.insert_name, textStyles.title1);
-        title.anchor.setTo(0.5);
+        game.add.text(defaultWidth / 2, defaultHeight / 2 - 100, game.lang.insert_name, textStyles.title1);
 
-        this.warningEmptyName = game.add.text(this.game.world.centerX, this.game.world.centerY - 70, "", textStyles.overtitle);
-        this.warningEmptyName.anchor.setTo(0.5);
+        this.warningEmptyName = game.add.text(defaultWidth / 2, defaultHeight / 2 - 70, "", textStyles.overtitle);
 
         // Set 'ok' button that gets player's information
-
-        const btn = game.add.graphics(this.game.world.centerX - 84, this.game.world.centerY + 70);
-        btn.beginFill(colors.teal);
-        btn.drawRect(0, 0, 168, 60);
-        btn.alpha = 0.5;
-        btn.endFill();
-        btn.inputEnabled = true;
-        btn.input.useHandCursor = true;
-        btn.events.onInputDown.add(this.func_checkEmptyName);
-        btn.events.onInputOver.add(function () { btn.alpha = 0.4 });
-        btn.events.onInputOut.add(function () { btn.alpha = 0.5 });
+        this.okBtn = game.add.graphic.rect(defaultWidth / 2 - 84, defaultHeight / 2 + 70, 168, 60, undefined, 0, colors.teal, 0.5);
 
         // Set button Text
-        const ready = game.add.text(this.game.world.centerX + 1, this.game.world.centerY + 102, lang.ready, textStyles.buttonLabel);
-        ready.anchor.setTo(0.5);
+        game.add.text(defaultWidth / 2 + 1, defaultHeight / 2 + 112, game.lang.ready, textStyles.buttonLabel);
 
         // Makes text field visible
         document.getElementById("text-field").style.visibility = "visible";
+        document.getElementById("text-field").style.top = "300px";
+        document.getElementById("text-field").style.marginLeft = "240px";
 
         // Does the same as the button click when the player presses "enter"
         document.getElementById("name_id").addEventListener('keypress', function (e) {
-            let keycode = e.keycode ? e.keycode : e.which;
-            if (keycode == 13) nameState.func_checkEmptyName();
+            const keycode = e.key || e.code;
+            if (keycode == 'Enter') {
+
+                if (self.func_checkEmptyName()) self.func_saveName();
+
+                game.render.all(); // can show empty name
+            }
         });
 
+        game.event.add("click", this.func_onInputDown);
+        game.event.add("mousemove", this.func_onInputOver);
+
+        game.render.all();
+
     },
 
+
+
+    /* EVENT HANDLER*/
+
+    func_onInputDown: function (mouseEvent) {
+
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+
+        const cur = self.okBtn;
+
+        const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+            (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+        if (valid) {
+
+            if (self.func_checkEmptyName()) {
+
+                self.func_saveName();
+
+            }
+
+        }
+
+        game.render.all();
+    },
+
+    func_onInputOver: function (mouseEvent) {
+
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+
+        const cur = self.okBtn;
+
+        const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+            (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+
+        if (valid) {
+            document.body.style.cursor = "pointer";
+            cur.alpha = 0.4;
+        } else {
+            document.body.style.cursor = "auto";
+            cur.alpha = 0.5;
+        }
+
+        game.render.all();
+
+    },
+
+
+
+    /* GAME FUNCTIONS */
+
     func_checkEmptyName: function () {
 
         // If text field is empty displays error message
         if (document.getElementById("name_id").value == "") {
-            nameState.warningEmptyName.setText(lang.empty_name);
-        } else { // If text field is NOT empty calls function that saves the player's name
-            nameState.func_saveName();
+            self.warningEmptyName.name = game.lang.empty_name;
+            return false;
         }
+        return true;
 
     },
 
@@ -164,12 +313,12 @@ let nameState = {
         document.getElementById("text-field").style.visibility = "hidden";
         document.getElementById("name_id").value = "";
 
-        if (audioStatus) sound.beepSound.play();
+        if (audioStatus) game.audio.beepSound.play();
 
         if (debugMode) console.log("Username: " + playerName);
 
         // Calls 'menu' state
-        game.state.start('menu');
+        menuScreen.preload();
 
     }
 

File diff suppressed because it is too large
+ 498 - 436
js/squareOne.js


+ 271 - 353
js/squareTwo.js

@@ -1,24 +1,7 @@
 /*
-    let gameSquareTwo = {
-        create: function(){},
-        update: function(){},
-        ---------------------------- end of phaser functions
-        func_overSquare: function(){},
-        func_outSquare: function(){},
-        func_clickSquare: function(){},
-
-            //func_setPlace: function(){},
-            //func_checkOverlap: function(){}
-        func_getRndDivisor: function(){}        
-            //func_viewHelp: function(){},
-        
-        func_updateCounter: function(){},
-        func_postScore: function(){},
-    };  
-
     GAME LEVELS - SQUARE III: fraction comparisson level
     
-    Name of game state : 'squareTwo' 
+    Name of game state : 'SquareTwo' 
     Shape : square
     Character : kid
     Theme : (not themed)
@@ -41,28 +24,55 @@
             bottom has more subdivisions
 */
 
-let gameSquareTwo = {
+const squareTwo = {
+
+    preload: function () {
+
+        document.body.style.cursor = "auto";
+        game.loop.stop();
+        game.event.clear();
+        game.animation.clear();
+
+        self = this;
+
+        // NOTHING TO LOAD HERE
+        squareTwo.create();
+
+    },
 
     create: function () {
 
+        game.render.clear();
+
         // CONTROL VARIABLES
 
-        self = this;
+        this.result = false;    // Check if selected blocks are correct
+        this.delay = 0;         // Counter for game dalays
+        this.endLevel = false;
 
-        this.numBlocksA = 0; // Subdivision of top figure (A)
-        this.numBlocksB = 0; // Subdivision of bottom figure (B)
-        this.selectedA = 0; // Number of selected blocks for A
-        this.selectedB = 0; // Number of selected blocks for B
-        this.hasClickedA = false; // Check if player clicked blocks from A
-        this.hasClickedB = false; // Check if player clicked blocks from B
-        this.animateA = false; // Animate blocks from A
-        this.animateB = false; // Animate blocks from B
-        this.result = false; // Check if selected blocks are correct
-        this.ending = null;
+        self.A = {
+            blocks: [],     // List of selection blocks
+            auxBlocks: [],  // List of shadow under selection blocks
+            fractions: [],  // fraction numbers
 
-        this.delay = 0; // Counter used in the animations 
-        this.endDelay = 60; // Maximum value for the counter
+            selected: 0,    // Number of selected blocks for A
+            hasClicked: false,  // Check if player clicked blocks from A
+            animate: false,     // Animate blocks from A
+            warningText: undefined,
+            label: undefined,
+        };
 
+        self.B = {
+            blocks: [],
+            auxBlocks: [],
+            fractions: [],
+
+            selected: 0,
+            hasClicked: false,
+            animate: false,
+            warningText: undefined,
+            label: undefined,
+        };
 
 
 
@@ -73,34 +83,19 @@ let gameSquareTwo = {
         // Add clouds
         game.add.image(300, 100, 'cloud');
         game.add.image(660, 80, 'cloud');
-        game.add.image(110, 85, 'cloud').scale.setTo(0.8);
+        game.add.image(110, 85, 'cloud', 0.8);
 
         // Add floor of grass
         for (let i = 0; i < 9; i++) { game.add.image(i * 100, 501, 'floor'); }
 
         // Calls function that loads navigation icons
-        iconSettings.func_addIcons(true, true,
-            true, true, false,
+        navigationIcons.func_addIcons(true, true, false,
             true, false,
-            'difficulty', false);
+            difficultyScreen, false);
 
         //Add kid
-        this.kid = game.add.sprite(100, 470, 'kid_lost');
-        this.kid.scale.setTo(0.8);
-        this.kid.anchor.setTo(0.5, 0.7);
-        this.kid.animations.add('front', [3, 4, 5]);
-        this.kid.animations.play('front', 6, false); // play kid animation once
-
-
-
-
-        // Group of blocks on A and B
-        this.blocksA = game.add.group();
-        this.blocksB = game.add.group();
-
-        // Group of shadow on bottom of A and B
-        this.auxBlocksA = game.add.group();
-        this.auxBlocksB = game.add.group();
+        this.kidAnimation = game.add.sprite(100, 470, 'kid_standing', 5, 0.8);
+        this.kidAnimation.anchor(0.5, 0.7);
 
         // Width and Height of A and B
         this.figureWidth = 400;
@@ -124,494 +119,417 @@ let gameSquareTwo = {
         const points = [2, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20];
 
         // Random index for 'points'
-        const randomIndex = game.rnd.integerInRange((levelDifficulty - 1) * 2 + 1, (levelDifficulty - 1) * 2 + 3);
+        const randomIndex = game.math.randomInRange((gameDifficulty - 1) * 2 + 1, (gameDifficulty - 1) * 2 + 3);
+
+
 
         // number of subdivisions of A and B (blocks)
-        this.numBlocksA = points[randomIndex];
-        this.numBlocksB = this.func_getRndDivisor(this.numBlocksA);
+        const totalBlocksA = points[randomIndex];
+        const totalBlocksB = game.math.randomDivisor(totalBlocksA);
 
         if (debugMode) {
             console.log("----------");
-            console.log("Difficulty " + levelDifficulty + ", ini " + ((levelDifficulty - 1) * 2 + 1) + ", end " + ((levelDifficulty - 1) * 2 + 3));
-            console.log("Rpoint " + randomIndex + ", val " + this.numBlocksA);
-            console.log("total blocks A " + this.numBlocksA + ", total blocks B ");
+            console.log("Difficulty " + gameDifficulty + ", ini " + ((gameDifficulty - 1) * 2 + 1) + ", end " + ((gameDifficulty - 1) * 2 + 3));
+            console.log("Rpoint " + randomIndex + ", val " + totalBlocksA);
+            console.log("total blocks A " + totalBlocksA + ", total blocks B ");
         }
 
 
 
-
         // CREATING TOP FIGURE (A)
 
-        let blockWidth = this.figureWidth / this.numBlocksA; // width of each block in A
+        let blockWidth = this.figureWidth / totalBlocksA; // width of each block in A
         let lineColor = colors.darkGreen;
         let fillColor = colors.lightGreen;
         let fillColorAux = colors.lighterGreen;
 
         // Create blocks
-        for (let i = 0; i < this.numBlocksA; i++) {
+        for (let i = 0; i < totalBlocksA; i++) {
 
             const x = xA + i * blockWidth;
 
             // Blocks
-            let block = game.add.graphics(x, yA);
-            block.anchor.setTo(0.5, 0.5);
-            block.lineStyle(2, lineColor);
-            block.beginFill(fillColor);
-            block.drawRect(0, 0, blockWidth, figureHeight);
-            block.alpha = 0.5;
-            block.endFill();
-
-            block.inputEnabled = true;
-            block.input.useHandCursor = true;
-            block.events.onInputDown.add(this.func_clickSquare, { figure: 'A', index: i, xA: xA, xB: xB });
-            block.events.onInputOver.add(this.func_overSquare, { figure: 'A', index: i, xA: xA, xB: xB });
-            block.events.onInputOut.add(this.func_outSquare, { figure: 'A', index: i });
-
-            this.blocksA.add(block);
+            const block = game.add.graphic.rect(x, yA, blockWidth, figureHeight, lineColor, 2, fillColor, 0.5);
+            block.figure = 'A';
+            block.index = i;
+            block.finalX = xA;
+            self.A.blocks.push(block);
 
             // Auxiliar blocks
+            const alpha = (sublevelType == 'A') ? 0.2 : 0;
             const yAux = yA + figureHeight + 10; // on the bottom of A
-
-            block = game.add.graphics(x, yAux);
-            block.anchor.setTo(0.5, 0.5);
-            block.lineStyle(1, lineColor);
-            block.beginFill(fillColorAux);
-            block.drawRect(0, 0, blockWidth, figureHeight);
-            block.alpha = (sublevelType == 'A') ? 0.2 : 0; // Only visible in sublevel A, but used as parameter is all
-
-            this.auxBlocksA.add(block);
+            const auxBlock = game.add.graphic.rect(x, yAux, blockWidth, figureHeight, lineColor, 1, fillColorAux, alpha);
+            self.A.auxBlocks.push(auxBlock);
 
         }
 
         // 'total blocks' label for A : on the side of A
         let xLabel = xA + this.figureWidth + 30;
         let yLabel = yA + figureHeight / 2;
-        this.labelA = game.add.text(xLabel, yLabel, this.numBlocksA, textStyles.valueLabelBlue2);
-        this.labelA.anchor.setTo(0.5, 0.41);
+
+        this.A.label = game.add.text(xLabel, yLabel, this.A.blocks.length, textStyles.valueLabelBlue2);
 
         // 'selected blocks/fraction' label for A : at the bottom of A
         yLabel = yA + figureHeight + 34;
-        this.fractionA = game.add.text(xLabel, yLabel, "", textStyles.valueLabelBlue2);
-        this.fractionA.anchor.setTo(0.5, 0.41);
-        this.fractionA.alpha = 0;
-        this.fractionLineA = game.add.sprite(xLabel, yLabel + 3, 'fractionLine');
-        this.fractionLineA.anchor.setTo(0.5, 0.5);
-        this.fractionLineA.alpha = 0;
 
+        self.A.fractions[0] = game.add.text(xLabel, yLabel, "", textStyles.valueLabelBlue2);
+        self.A.fractions[1] = game.add.text(xLabel, yLabel + 21, "", textStyles.valueLabelBlue2);
+        self.A.fractions[2] = game.add.text(xLabel, yLabel, "___", textStyles.valueLabelBlue2);
+        self.A.fractions[0].alpha = 0;
+        self.A.fractions[1].alpha = 0;
+        self.A.fractions[2].alpha = 0;
 
 
 
         // CREATING BOTTOM FIGURE (B)
 
-        blockWidth = this.figureWidth / this.numBlocksB; // width of each block in B
-        lineColor = colors.darkRed_;
+        blockWidth = this.figureWidth / totalBlocksB; // width of each block in B
+        lineColor = colors.darkRed;
         fillColor = colors.lightRed;
         fillColorAux = colors.lighterRed;
 
         // Blocks and auxiliar blocks
-        for (let i = 0; i < this.numBlocksB; i++) {
+        for (let i = 0; i < totalBlocksB; i++) {
 
             const x = xB + i * blockWidth;
 
             // Blocks
-            let block = game.add.graphics(x, yB);
-            block.anchor.setTo(0.5, 0.5);
-            block.lineStyle(2, lineColor);
-            block.beginFill(fillColor);
-            block.drawRect(0, 0, blockWidth, figureHeight);
-            block.endFill();
-
-            block.inputEnabled = true;
-            block.input.useHandCursor = true;
-            block.events.onInputDown.add(this.func_clickSquare, { figure: 'B', index: i, xA: xA, xB: xB });
-            block.events.onInputOver.add(this.func_overSquare, { figure: 'B', index: i, xA: xA, xB: xB });
-            block.events.onInputOut.add(this.func_outSquare, { figure: 'B', index: i });
 
-            this.blocksB.add(block);
+            const block = game.add.graphic.rect(x, yB, blockWidth, figureHeight, lineColor, 2, fillColor, 0.5);
+            block.figure = 'B';
+            block.index = i;
+            block.finalX = xB;
+            self.B.blocks.push(block);
 
             // Auxiliar blocks
-            let yAux = yB + figureHeight + 10; // on the bottom of B
-
-            block = game.add.graphics(x, yAux);
-            block.anchor.setTo(0.5, 0.5);
-            block.lineStyle(1, lineColor);
-            block.beginFill(fillColorAux);
-            block.drawRect(0, 0, blockWidth, figureHeight);
-            block.alpha = (sublevelType == 'A') ? 0.2 : 0; // Only visible in sublevel A, but used as parameter is all
-
-            this.auxBlocksB.add(block);
+            const alpha = (sublevelType == 'A') ? 0.2 : 0;
+            const yAux = yB + figureHeight + 10; // on the bottom of B
+            const auxBlock = game.add.graphic.rect(x, yAux, blockWidth, figureHeight, lineColor, 1, fillColorAux, alpha);
+            self.B.auxBlocks.push(auxBlock);
 
         }
 
         // Label block B
         xLabel = xB + this.figureWidth + 30;
         yLabel = yB + figureHeight / 2;
-        this.labelB = game.add.text(xLabel, yLabel, this.numBlocksB, textStyles.valueLabelBlue2);
-        this.labelB.anchor.setTo(0.5, 0.41);
+
+        this.B.label = game.add.text(xLabel, yLabel, this.B.blocks.length, textStyles.valueLabelBlue2);
 
         // Label fraction
         yLabel = yB + figureHeight + 34;
-        this.fractionB = game.add.text(xLabel, yLabel, "", textStyles.valueLabelBlue2);
-        this.fractionB.anchor.setTo(0.5, 0.41);
-        this.fractionB.alpha = 0;
-        this.fractionLineB = game.add.sprite(xLabel, yLabel + 3, 'fractionLine');
-        this.fractionLineB.anchor.setTo(0.5, 0.5);
-        this.fractionLineB.alpha = 0;
 
-
-
-
-        // OUTPUT ICONS AND TEXT
-
-        // Ok image
-        this.okImg = game.add.image(game.world.centerX, game.world.centerY, 'h_ok');
-        this.okImg.anchor.setTo(0.5);
-        this.okImg.visible = false;
-
-        // Error image
-        this.errorImg = game.add.image(game.world.centerX, game.world.centerY, 'h_error');
-        this.errorImg.anchor.setTo(0.5);
-        this.errorImg.visible = false;
+        self.B.fractions[0] = game.add.text(xLabel, yLabel, "", textStyles.valueLabelBlue2);
+        self.B.fractions[1] = game.add.text(xLabel, yLabel + 21, "", textStyles.valueLabelBlue2);
+        self.B.fractions[2] = game.add.text(xLabel, yLabel, "___", textStyles.valueLabelBlue2);
+        self.B.fractions[0].alpha = 0;
+        self.B.fractions[1].alpha = 0;
+        self.B.fractions[2].alpha = 0;
 
         // Invalid selection text
-        this.warningTextA = game.add.text(game.world.centerX, game.world.centerY - 225, "", textStyles.overtitle);
-        this.warningTextA.anchor.setTo(0.5, 0.5);
+        self.A.warningText = game.add.text(defaultWidth / 2, defaultHeight / 2 - 225, "", textStyles.overtitle);
+
+        self.B.warningText = game.add.text(defaultWidth / 2, defaultHeight / 2 - 45, "", textStyles.overtitle);
 
-        this.warningTextB = game.add.text(game.world.centerX, game.world.centerY - 45, "", textStyles.overtitle);
-        this.warningTextB.anchor.setTo(0.5, 0.5);
 
 
+        game.render.all();
 
+        game.timer.start(); // Set a timer for the current level (used in func_postScore)
 
-        // TIMER
+        game.event.add("click", squareTwo.func_onInputDown);
+        game.event.add("mousemove", squareTwo.func_onInputOver);
 
-        // Set a timer for the current level
-        this.totalTime = 0;
-        this.timer = game.time.create(false);
-        this.timer.loop(1000, this.func_updateCounter, this);
-        this.timer.start();
+        game.loop.start(this);
 
     },
 
     update: function () {
 
-        // If clicked A, animate A blocks
-        if (this.animateA) {
+        // Animate blocks
+        if (self.A.animate || self.B.animate) {
 
-            // Lower selected blocks
-            for (let i = 0; i < this.selectedA; i++) {
-                this.blocksA.children[i].y += 2;
-            }
+            ['A', 'B'].forEach(cur => {
 
-            // After fully lowering blocks, set fraction value
-            if (this.blocksA.children[0].y >= this.auxBlocksA.children[0].y) {
+                if (self[cur].animate) {
 
-                this.fractionA.alpha = 1;
-                this.fractionA.setText(this.selectedA + "\n" + this.numBlocksA);
-                this.fractionLineA.alpha = 1;
+                    // Lower selected blocks
+                    for (let i = 0; i < self[cur].selected; i++) {
+                        self[cur].blocks[i].y += 2;
+                    }
 
-                this.animateA = false;
-            }
-
-        }
-
-        // If clicked B, animate B blocks
-        if (this.animateB) {
-
-            // Lower selected blocks
-            for (let i = 0; i < this.selectedB; i++) {
-                this.blocksB.children[i].y += 2;
-            }
+                    // After fully lowering blocks, set fraction value
+                    if (self[cur].blocks[0].y >= self[cur].auxBlocks[0].y) {
+                        self[cur].fractions[0].name = self[cur].selected;
+                        self[cur].animate = false;
+                    }
 
-            // Sets fraction value
-            if (this.blocksB.children[0].y >= this.auxBlocksB.children[0].y) {
-                this.fractionB.alpha = 1;
-                this.fractionB.setText(this.selectedB + "\n" + this.numBlocksB);
-                this.fractionLineB.alpha = 1;
+                }
 
-                this.animateB = false;
-            }
+            });
 
         }
 
         // if A and B are already clicked
-        if (this.hasClickedA && this.hasClickedB && !this.ending) {
+        if (self.A.hasClicked && self.B.hasClicked && !self.endLevel) {
 
-            this.timer.stop();
+            game.timer.stop();
 
-            // Wait a bit before showing result
-            this.delay++;
+            self.delay++;
 
             // After delay is over, check result
-            if (this.delay > this.endDelay) {
+            if (self.delay > 50) {
 
-                // fractions are equivalent : correct
-                if ((this.selectedA / this.numBlocksA) == (this.selectedB / this.numBlocksB)) {
+                self.result = (self.A.selected / self.A.blocks.length) == (self.B.selected / self.B.blocks.length);
 
-                    if (audioStatus) sound.okSound.play();
+                // fractions are equivalent : CORRECT
+                if (self.result) {
 
-                    this.okImg.visible = true;
+                    if (audioStatus) game.audio.okSound.play();
 
-                    this.result = true; // player answer is correct
+                    game.add.image(defaultWidth / 2, defaultHeight / 2, 'ok').anchor(0.5, 0.5);
+
+                    mapMove = true; // allow character to move to next level in map state
 
-                    mapCanMove = true; // allow character to move to next level in map state
                     completedLevels++;
-                    if (debugMode) console.log("completedLevels = " + completedLevels);
 
+                    if (debugMode) console.log("completedLevels = " + completedLevels);
 
-                    // fractions are not equivalent : incorrect
+                    // fractions are not equivalent : INCORRECT
                 } else {
 
-                    if (audioStatus) sound.errorSound.play();
-
-                    this.errorImg.visible = true;
+                    if (audioStatus) game.audio.errorSound.play();
 
-                    this.result = false; // player answer is incorrect
+                    game.add.image(defaultWidth / 2, defaultHeight / 2, 'error').anchor(0.5, 0.5);
 
-                    mapCanMove = false; // doesnt allow character to move to next level in map state
+                    mapMove = false; // doesnt allow character to move to next level in map state
 
                 }
 
-                this.func_postScore();
-                this.hasClickedA = false;
-                this.hasClickedB = false;
+                self.func_postScore();
+
+                self.endLevel = true;
 
                 // reset delay values for next delay
-                this.delay = 0;
-                this.endDelay = 100;
-                this.ending = true;
+                self.delay = 0;
 
             }
 
         }
 
         // Wait a bit and go to map state
-        if (this.ending) {
+        if (self.endLevel) {
 
-            this.delay++;
+            self.delay++;
 
-            if (this.delay >= this.endDelay) {
-                game.state.start('map');
+            if (self.delay >= 80) {
+                mapScreen.preload();
             }
 
         }
 
+        game.render.all();
+
     },
 
-    func_overSquare: function () {
 
-        if (!self.hasClickedA && this.figure == "A") {
 
-            // If over fraction 'n/n' shows warning message not allowing it
-            if (this.index == self.numBlocksA - 1) {
+    /* EVENT HANDLER */
 
-                self.warningTextA.setText(lang.error_msg);
-                self.warningTextB.setText("");
+    func_onInputDown: function (mouseEvent) {
 
-            } else {
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
 
-                self.warningTextA.setText("");
-                self.warningTextB.setText("");
+        // click block in A
+        self.A.blocks.forEach(cur => {
 
-                // selected blocks become fully visible
-                for (let i = 0; i < self.numBlocksA; i++) {
-                    self.blocksA.children[i].alpha = (i <= this.index) ? 1 : 0.5;
-                }
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) && (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+            if (valid) self.func_clickSquare(cur);
+        });
 
-                self.fractionA.x = this.xA + ((this.index + 1) * (self.figureWidth / self.numBlocksA)) + 25;
-                self.fractionA.alpha = 1;
-                self.fractionA.setText(this.index + 1);
+        // click block in B
+        self.B.blocks.forEach(cur => {
 
-            }
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) && (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
+            if (valid) self.func_clickSquare(cur);
+        });
 
-        }
+        // click navigation icons
+        navigationIcons.func_onInputDown(x, y);
 
-        if (!self.hasClickedB && this.figure == "B") {
+        game.render.all();
 
-            // If over fraction 'n/n' shows warning message not allowing it
-            if (this.index == self.numBlocksB - 1) {
+    },
 
-                self.warningTextA.setText("");
-                self.warningTextB.setText(lang.error_msg);
+    func_onInputOver: function (mouseEvent) {
 
-            } else {
+        const x = mouseEvent.offsetX;
+        const y = mouseEvent.offsetY;
+        let flagA = false;
+        let flagB = false;
 
-                self.warningTextA.setText("");
-                self.warningTextB.setText("");
-
-                // selected blocks become fully visible
-                for (let i = 0; i < self.numBlocksB; i++) {
-                    self.blocksB.children[i].alpha = (i <= this.index) ? 1 : 0.5;
-                }
+        // mouse over A : show fraction
+        self.A.blocks.forEach(cur => {
 
-                self.fractionB.x = this.xB + ((this.index + 1) * (self.figureWidth / self.numBlocksB)) + 25;
-                self.fractionB.alpha = 1;
-                self.fractionB.setText(this.index + 1);
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
 
+            if (valid) {
+                flagA = true;
+                self.func_overSquare(cur);
             }
+        });
+        if (!flagA) self.func_outSquare('A');
 
-        }
-
-    },
+        // mouse over B : show fraction
+        self.B.blocks.forEach(cur => {
 
-    func_outSquare: function () {
+            const valid = y >= cur.yWithAnchor && y <= (cur.yWithAnchor + cur.height * cur.scaleHeight) &&
+                (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scaleWidth));
 
-        // On level type A
-        if (!self.hasClickedA && this.figure == "A") {
-
-            for (let i = 0; i <= this.index; i++) {
-                self.blocksA.children[i].alpha = 0.5;
+            if (valid) {
+                flagB = true;
+                self.func_overSquare(cur);
             }
-            self.fractionA.alpha = 0;
+        });
+        if (!flagB) self.func_outSquare('B');
 
-        }
+        if (!flagA && !flagB) document.body.style.cursor = "auto";
 
-        // On level type B
-        if (!self.hasClickedB && this.figure == "B") {
 
-            for (let i = 0; i <= this.index; i++) {
-                self.blocksB.children[i].alpha = 0.5;
-            }
-            self.fractionB.alpha = 0;
 
-        }
+        // mouse over navigation icons : show name
+        navigationIcons.func_onInputOver(x, y);
+
+        game.render.all();
 
     },
 
-    func_clickSquare: function () {
 
-        // On level type A 
-        if (!self.hasClickedA && this.figure == "A" && this.index != self.numBlocksA - 1) {
 
-            for (let i = 0; i < self.numBlocksA; i++) {
-                // desable block input
-                self.blocksA.children[i].inputEnabled = false;
-                // turn auxiliar blocks invisible
-                if (i > this.index) self.auxBlocksA.children[i].alpha = 0;
-            }
+    /* CALLED BY EVENT HANDLER */
 
-            // turn value label invisible
-            self.labelA.alpha = 0;
+    func_overSquare: function (curBlock) { // curBlock : self.A.blocks[i] || self.B.blocks[i]
 
-            if (audioStatus) sound.beepSound.play();
+        const curSet = curBlock.figure; // "A" || "B"
 
-            // Save number of selected blocks
-            self.selectedA = this.index + 1;
+        if (!self[curSet].hasClicked) { // self.A.hasClicked || self.B.hasClicked 
 
-            // set fraction x position
-            self.fractionA.x = this.xA + (self.selectedA * (self.figureWidth / self.numBlocksA)) + 25;
-            self.fractionLineA.x = self.fractionA.x
+            // If over fraction 'n/n' shows warning message not allowing it
+            if (curBlock.index == self[curSet].blocks.length - 1) {
 
-            self.hasClickedA = true;
-            self.animateA = true;
+                const otherSet = (curSet == "A") ? "B" : "A";
 
-        }
+                self[curSet].warningText.name = game.lang.error_msg;
+                self[otherSet].warningText.name = "";
 
-        // On level type B
-        if (!self.hasClickedB && this.figure == "B" && this.index != self.numBlocksB - 1) {
+                self.func_outSquare(curSet);
 
-            for (let i = 0; i < self.numBlocksB; i++) {
-                // desable block input
-                self.blocksB.children[i].inputEnabled = false;
-                // turn auxiliar blocks invisible
-                if (i > this.index) self.auxBlocksB.children[i].alpha = 0;
-            }
+            } else {
 
-            // turn value label invisible
-            self.labelB.alpha = 0;
+                document.body.style.cursor = "pointer";
 
-            if (audioStatus) sound.beepSound.play();
+                self.A.warningText.name = "";
+                self.B.warningText.name = "";
 
-            // Save number of selected blocks
-            self.selectedB = this.index + 1;
+                // selected blocks become fully visible
+                for (let i in self[curSet].blocks) {
+                    self[curSet].blocks[i].alpha = (i <= curBlock.index) ? 1 : 0.5;
+                }
+
+                self[curSet].fractions[0].name = curBlock.index + 1; // nominator : selected blocks
+                self[curSet].fractions[1].name = self[curSet].blocks.length; // denominator : total blocks
 
-            // Set fraction x position
-            self.fractionB.x = this.xB + (self.selectedB * (self.figureWidth / self.numBlocksB)) + 25;
-            self.fractionLineB.x = self.fractionB.x
+                const newX = curBlock.finalX + ((curBlock.index + 1) * (self.figureWidth / self[curSet].blocks.length)) + 25;;
+                self[curSet].fractions[0].x = newX;
+                self[curSet].fractions[1].x = newX;
+                self[curSet].fractions[2].x = newX;
 
-            self.hasClickedB = true;
-            self.animateB = true;
+                self[curSet].fractions[0].alpha = 1;
+
+            }
 
         }
 
     },
 
-    func_getRndDivisor: function (number) { //Get random divisor for a number
+    func_outSquare: function (curSet) { // curSet : self.A || self.B
 
-        let div = []; //Divisors found
-        let p = 0;    //current dividor index
+        if (!self[curSet].hasClicked) {
+
+            self[curSet].fractions[0].alpha = 0;
+            self[curSet].fractions[1].alpha = 0;
+            self[curSet].fractions[2].alpha = 0;
+
+            self[curSet].blocks.forEach(cur => {
+                cur.alpha = 0.5;
+            });
 
-        for (let i = 2; i < number; i++) {
-            if (number % i == 0) {
-                div[p] = i;
-                p++;
-            }
         }
-        let x = game.rnd.integerInRange(0, p - 1);
-        return div[x];
 
     },
 
-    func_getRndDivisor: function (number) { //Get random divisor for a number
+    func_clickSquare: function (curBlock) { // curBlock : self.A.blocks[i] || self.B.blocks[i]
 
-        let validDivs = []; // Divisors found
+        const curSet = curBlock.figure; // "A" || "B"
 
-        for (let div = 2; div < number; div++) {
+        if (!self[curSet].hasClicked && curBlock.index != self[curSet].blocks.length - 1) {
 
-            // if 'number' can be divided by 'div', add to list of 'validDivs'
-            if (number % div == 0) validDivs.push(div);
+            document.body.style.cursor = "auto";
 
-        }
+            // turn auxiliar blocks invisible
+            for (let i in self[curSet].blocks) {
+                if (i > curBlock.index) self[curSet].auxBlocks[i].alpha = 0;
+            }
 
-        const randIndex = game.rnd.integerInRange(0, validDivs.length - 1);
+            // turn value label invisible
+            self[curSet].label.alpha = 0;
 
-        return validDivs[randIndex];
+            if (audioStatus) game.audio.beepSound.play();
 
-    },
+            // Save number of selected blocks
+            self[curSet].selected = curBlock.index + 1;
 
-    // Game information
+            // set fraction x position
+            const newX = curBlock.finalX + (self[curSet].selected * (self.figureWidth / self[curSet].blocks.length)) + 25;
+            self[curSet].fractions[0].x = newX;
+            self[curSet].fractions[1].x = newX;
+            self[curSet].fractions[2].x = newX;
+
+            self[curSet].fractions[1].alpha = 1;
+            self[curSet].fractions[2].alpha = 1;
+
+            self[curSet].hasClicked = true; // inform player have clicked in current block set
+            self[curSet].animate = true; // let it initiate animation
+
+        }
+
+        game.render.all();
 
-    func_updateCounter: function () {
-        this.totalTime++;
     },
 
-    func_postScore: function () {
 
-        let abst = "numBlocksA: " + this.numBlocksA
-            + ", valueA: " + this.selectedA
-            + ", numBlocksB: " + this.numBlocksB
-            + ", valueB: " + this.selectedB;
 
-        let hr = new XMLHttpRequest();
+    /* METADATA FOR GAME */
+
+    func_postScore: function () {
 
         // Create some variables we need to send to our PHP file
-        let url = "php/save.php";
-        let vars = "s_ip=" + hip
-            + "&s_name=" + playerName
-            + "&s_lang=" + langString
-            + "&s_game=" + levelShape
-            + "&s_mode=" + levelType;
-        vars += "&s_oper=Equal"
-            + "&s_leve=" + levelDifficulty
+        const data = "&s_game=" + gameShape
+            + "&s_mode=" + levelType
+            + "&s_oper=Equal"
+            + "&s_leve=" + gameDifficulty
             + "&s_posi=" + mapPosition
-            + "&s_resu=" + this.result
-            + "&s_time=" + this.totalTime
-            + "&s_deta=" + abst;
-
-        hr.open("POST", url, true);
-        hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
-        hr.onreadystatechange = function () {
-            if (debugMode) console.log(hr);
-
-            if (hr.readyState == 4 && hr.status == 200) {
-                let return_data = hr.responseText;
-                if (debugMode) console.log(return_data);
-            }
-        }
-        // Send the data to PHP now... and wait for response to update the status div
-        hr.send(vars); // Actually execute the request
-        if (debugMode) console.log("processing...");
-        if (debugMode) console.log(vars);
+            + "&s_resu=" + self.result
+            + "&s_time=" + game.timer.elapsed
+            + "&s_deta="
+            + "numBlocksA: " + self.A.blocks.length
+            + ", valueA: " + self.A.selected
+            + ", numBlocksB: " + self.B.blocks.length
+            + ", valueB: " + self.B.selected;;
+
+        postScore(data);
+
     }
 
 };

+ 7 - 6
php/save.php

@@ -9,6 +9,7 @@
 /// @see js/circleOne.js
 /// @see js/squareOne.js
 /// @see js/squareTwo.js
+/// @see js/globals.js
 
 function remove_accents ($stripAccents) {
   /*
@@ -18,7 +19,7 @@ function remove_accents ($stripAccents) {
   $stripAccents = preg_replace('/[^\x20-\x7E]/','', $stripAccents);
   */
   return $stripAccents;
-  }
+}
 
 // Monta vetor [0,1] de dados da m<E1>quina cliente
 function ipMaquina0 () {
@@ -31,7 +32,7 @@ function ipMaquina0 () {
   $resp[0] = $ip;
   $resp[1] = gethostbyaddr($ip);
   return $resp;
-  }
+}
 
 // Monta vetor [0,1] de dados da m<E1>quina cliente
 function ipMaquina () {
@@ -45,9 +46,9 @@ function ipMaquina () {
   $resp = gethostbyaddr($ip);
   if (isset($resp) && strlen($resp)>0) {
     $strIP .= "; " . $resp;
-    }
-  return $strIP;
   }
+  return $strIP;
+}
 
 
 $servername = "localhost";
@@ -60,7 +61,7 @@ $conn = new mysqli($servername, $username, $password, $dbname);
 // Check connection
 if ($conn->connect_error) {
   die("Connection failed: " . $conn->connect_error);
-  }
+}
 
 
 // $ip = $_REQUEST["s_ip"];
@@ -108,7 +109,7 @@ if ($conn->query($sql) === TRUE) {
 } else {
   print "Error: " . $sql . "<br>" . $conn->error;
   $result = "Erro: " . $conn->error;
-  }
+}
 
 
 //DEBUG