Jelajahi Sumber

finished converting tab to spaces
changes main menu icons
changed back to previous indentation style
changed name of global function postScore to sendToDB to differentiate from local postScore
updated readme from /php

laira 3 tahun lalu
induk
melakukan
e736b6227e
14 mengubah file dengan 2102 tambahan dan 2121 penghapusan
  1. TEMPAT SAMPAH
      assets/img/levels/circleOne.png
  2. TEMPAT SAMPAH
      assets/img/levels/squareOne.png
  3. TEMPAT SAMPAH
      assets/img/levels/squareTwo.png
  4. 90 91
      index.html
  5. 64 63
      js/circleOne.js
  6. 1027 1027
      js/gameMechanics.js
  7. 50 51
      js/globals.js
  8. 272 272
      js/map.js
  9. 421 421
      js/menu.js
  10. 37 39
      js/preMenu.js
  11. 77 88
      js/squareOne.js
  12. 41 45
      js/squareTwo.js
  13. 16 16
      php/README.md
  14. 7 8
      php/save.php

TEMPAT SAMPAH
assets/img/levels/circleOne.png


TEMPAT SAMPAH
assets/img/levels/squareOne.png


TEMPAT SAMPAH
assets/img/levels/squareTwo.png


+ 90 - 91
index.html

@@ -8,107 +8,106 @@ www.usp.br/line
 
 <head>
 
- <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, private data" />
- <link rel="shortcut icon" href="assets/img/scene/flag.png">
- <title> iFractions by LInE-IME-USP</title>
- <link rel="stylesheet" href="css/bootstrap.min.css">
-
- <style>
-  #iFractions-canvas {
-   padding: 0 auto 0 auto;
-   margin-left: auto;
-   margin-right: auto;
-   display: block;
-  }
-
-  #textbox {
-   position: absolute;
-   margin-left: auto;
-   margin-right: auto;
-   top: 300px;
-   left: 0;
-   right: 0;
-   text-align: center;
-   visibility: hidden;
-  }
-  input[type=text] {
-   background-color: #fff;
-   padding: 15px 40px;
-   box-sizing: border-box;
-   border: 3px solid #ccc;
-   font-size: 44px;
-   font-family: Arial;
-   color: #000;
-   text-align: center;
-  }
-  input:focus {
-   outline: 3px solid #85accc;
-  }
- </style>
+  <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, private data" />
+  <link rel="shortcut icon" href="assets/img/scene/flag.png">
+  <title> iFractions by LInE-IME-USP</title>
+  <link rel="stylesheet" href="css/bootstrap.min.css">
+
+  <style>
+    #iFractions-canvas {
+      padding: 0 auto 0 auto;
+      margin-left: auto;
+      margin-right: auto;
+      display: block;
+    }
+    #textbox {
+      position: absolute;
+      margin-left: auto;
+      margin-right: auto;
+      top: 300px;
+      left: 0;
+      right: 0;
+      text-align: center;
+      visibility: hidden;
+    }
+    input[type=text] {
+      background-color: #fff;
+      padding: 15px 40px;
+      box-sizing: border-box;
+      border: 3px solid #ccc;
+      font-size: 44px;
+      font-family: Arial;
+      color: #000;
+      text-align: center;
+    }
+    input:focus {
+      outline: 3px solid #85accc;
+    }
+  </style>
 
 </head>
 
 <body>
 
- <div class="container">
+  <div class="container">
 
-  <div class="clearfix"></div>
+    <div class="clearfix"></div>
 
-  <div class="panel panel-primary">
-  <div class="panel-heading">iFractions game :: by LInE</div>
-   <div class="panel-body">
-    <canvas id="iFractions-canvas"></canvas> <!-- iFractions game -->
-    <div id="textbox" onsubmit="return false"> <!-- Textbox to get player name -->
-     <input type="text" id="textbox-content" value="" size="13" maxlength="36">
+    <div class="panel panel-primary">
+      <div class="panel-heading">iFractions game :: by LInE</div>
+      <div class="panel-body">
+        <canvas id="iFractions-canvas"></canvas> <!-- iFractions game -->
+        <div id="textbox" onsubmit="return false"> <!-- Textbox to get player name -->
+          <input type="text" id="textbox-content" value="" size="13" maxlength="36">
+        </div>
+      </div>
     </div>
-   </div>
+
+    <div id="display-fps"><!-- Display fps in debugmode --></div>
+
   </div>
 
-  <div id="display-fps"><!-- Display fps in debugmode --></div>
-
- </div>
-
- <!-- Load all js files -->
- <script src="js/preMenu.js"></script>
- <script src="js/menu.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/gameMechanics.js"></script>
- <script src="js/globals.js"></script>
- <script>  
-  const displayFps = document.getElementById("display-fps");
-
-  const canvas = document.getElementById("iFractions-canvas");
-  canvas.width = defaultWidth; 
-  canvas.height = defaultHeight;
-
-  const context = canvas.getContext("2d");
-  
-  info.start();
-
-  // CREATING GAME STATES
-  game.state.add('boot', bootState);
-  game.state.add('lang', langState);
-  game.state.add('loadLang', loadLangState);
-  game.state.add('name', nameState);
-
-  game.state.add('menu', menuState);
-  game.state.add('customMenu', customMenuState);
-
-  game.state.add('map', mapState);
-  game.state.add('end', endState);
-
-  game.state.add('squareOne', squareOne);
-  game.state.add('circleOne', circleOne);
-  game.state.add('squareTwo', squareTwo);
-
-  // CALLING FIRST GAME STATE
-  game.state.start('boot');
- </script>
+  <!-- Load all js files -->
+  <script src="js/preMenu.js"></script>
+  <script src="js/menu.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/gameMechanics.js"></script>
+  <script src="js/globals.js"></script>
+  <script>
+    const displayFps = document.getElementById("display-fps");
+
+    const canvas = document.getElementById("iFractions-canvas");
+    canvas.width = defaultWidth;
+    canvas.height = defaultHeight;
+
+    const context = canvas.getContext("2d");
+
+    info.start();
+
+    // CREATING GAME STATES
+    game.state.add('boot', bootState);
+    game.state.add('lang', langState);
+    game.state.add('loadLang', loadLangState);
+    game.state.add('name', nameState);
+
+    game.state.add('menu', menuState);
+    game.state.add('customMenu', customMenuState);
+
+    game.state.add('map', mapState);
+    game.state.add('end', endState);
+
+    game.state.add('squareOne', squareOne);
+    game.state.add('circleOne', circleOne);
+    game.state.add('squareTwo', squareTwo);
+
+    // CALLING FIRST GAME STATE
+    game.state.start('boot');
+  </script>
 
 </body>
 

+ 64 - 63
js/circleOne.js

@@ -77,7 +77,7 @@ const circleOne = {
     for (let i = 0; i <= 5; i++) {
       game.add.image(66 + i * distanceBetweenPoints, 526, 'place_off', 0.3).anchor(0.5, 0.5);
       game.add.text(66 + i * distanceBetweenPoints, 560, i, textStyles.h2_blue);
-      }
+    }
 
     this.trace = game.add.graphic.rect(startX - 1, 526, 1, 1, undefined, 1);
     this.trace.alpha = 0;
@@ -87,7 +87,7 @@ const circleOne = {
       true, true, true, // Left buttons
       true, false,      // Right buttons
       'customMenu', this.func_viewHelp
-      );
+    );
 
     // CIRCLES AND FRACTIONS
     this.circles = {
@@ -102,7 +102,7 @@ const circleOne = {
       lineColor: [], // Circle line colors (also used for tracing on floor)
 
       direc: [],     // Can be : 1 or -1 : will be multiplied to values to easily change object direction when needed
-      };
+    };
 
     this.balloonPlace = defaultWidth / 2; // Balloon place
 
@@ -137,7 +137,7 @@ const circleOne = {
           if (i < this.numberOfPlusFractions) direction = 'Right';
           else direction = 'Left';
           break;
-        }
+      }
       this.circles.direction[i] = direction;
 
       // Set each circle color
@@ -147,11 +147,11 @@ const circleOne = {
         lineColor = colors.darkBlue;
         this.circles.direc[i] = 1;
         anticlockwise = true;
-        } else {
+      } else {
         lineColor = colors.red;
         this.circles.direc[i] = -1;
         anticlockwise = false;
-        }
+      }
       this.circles.lineColor[i] = lineColor;
 
       // Draw circles 
@@ -168,9 +168,8 @@ const circleOne = {
         if (fractionLabel) {
           label[0] = game.add.text(x, 490 - i * this.circles.diameter, divisor, textStyles.h2_blue);
           this.circles.label.push(label);
-          }
         }
-      else {
+      } else {
         let degree = 360 / divisor;
 
         if (direction == 'Right') degree = 360 - degree; // Anticlockwise equivalent
@@ -186,8 +185,8 @@ const circleOne = {
           label[1] = game.add.text(x, 488 - i * this.circles.diameter, '1', textStyles.h4_blue);
           label[2] = game.add.text(x, 488 - i * this.circles.diameter, '___', textStyles.h4_blue);
           this.circles.label.push(label);
-          }
         }
+      }
 
       circle.rotate = 90;
 
@@ -195,12 +194,12 @@ const circleOne = {
       if (levelType == 'B') {
         circle.alpha = 0.5;
         circle.index = i;
-        }
+      }
       this.circles.distance.push(Math.floor(distanceBetweenPoints / divisor));
       this.circles.all.push(circle);
 
       this.correctX += Math.floor(distanceBetweenPoints / divisor) * this.circles.direc[i];
-      }
+    }
 
     // Calculate next circle
     this.nextX = startX + this.circles.distance[0] * this.circles.direc[0];
@@ -211,7 +210,7 @@ const circleOne = {
     // If top circle position is out of bounds (when on the ground) or game doesnt have base difficulty, restart
     if (this.correctX < 66 || this.correctX > 66 + 3 * 260 || !hasBaseDifficulty) {
       this.restart = true;
-      }
+    }
 
     // If game is type B, selectiong a random balloon place
     if (levelType == 'B') {
@@ -220,13 +219,13 @@ const circleOne = {
 
       for (let i = 0; i < this.endIndex; i++) {
         this.balloonPlace += this.circles.distance[i] * this.circles.direc[i];
-        }
+      }
 
       // If balloon position is out of bounds, restart
       if (this.balloonPlace < 66 || this.balloonPlace > 66 + 5 * distanceBetweenPoints) {
         this.restart = true;
-        }
       }
+    }
 
     // KID 
     this.availableAnimations['Right'] = ['Right', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 4];
@@ -237,9 +236,9 @@ const circleOne = {
     if (sublevelType == 'Minus') {
       this.kid.animation = this.availableAnimations['Left'];
       this.kid.curFrame = 23;
-      } else {
+    } else {
       this.kid.animation = this.availableAnimations['Right'];
-      }
+    }
 
     // BALLOON
     this.balloon = game.add.image(this.balloonPlace, 350, 'balloon', 1, 0.5);
@@ -258,8 +257,8 @@ const circleOne = {
       game.timer.start(); // Set a timer for the current level (used in postScore())
       game.event.add('click', this.func_onInputDown);
       game.event.add('mousemove', this.func_onInputOver);
-      }
-    },
+    }
+  },
 
   /**
    * Game loop
@@ -279,7 +278,7 @@ const circleOne = {
         // Move circles
         for (let i in self.circles.all) {
           self.circles.all[i].x += 2 * DIREC;
-          }
+        }
 
         // Manage line on the floor
         self.trace.width += 2 * DIREC;
@@ -293,7 +292,7 @@ const circleOne = {
         let lowerCircles;
         if (self.circles.direction[cur] == 'Right') {
           lowerCircles = self.circles.all[cur].x >= self.nextX;
-          }
+        }
         else if (self.circles.direction[cur] == 'Left') {
 
           lowerCircles = self.circles.all[cur].x <= self.nextX;
@@ -301,8 +300,8 @@ const circleOne = {
           // If just changed from 'right' to 'left' inform to change direction of kid animation
           if (self.changeAnimationFrames == undefined && cur > 0 && self.circles.direction[cur - 1] == 'Right') {
             self.changeAnimationFrames = true;
-            }
           }
+        }
 
         // Change direction of kid animation
         if (self.changeAnimationFrames) {
@@ -314,13 +313,13 @@ const circleOne = {
           self.kid.curFrame = 23;
 
           game.animation.play(self.kid.animation[0]);
-          }
+        }
 
         if (lowerCircles) {
           self.circles.all[cur].alpha = 0; // Cicle disappear
           self.circles.all.forEach(cur => {
             cur.y += self.circles.diameter; // Lower circles             
-            });
+          });
           self.kid.y += self.circles.diameter; // Lower kid
 
           self.circles.cur++; // Update current circle
@@ -329,15 +328,15 @@ const circleOne = {
           DIREC = self.circles.direc[cur];
 
           self.nextX += self.circles.distance[cur] * DIREC; // Update next position
-          }
+        }
 
         // When finish all circles (final position)
         if (cur == self.circles.all.length || self.circles.all[cur].alpha == 0) {
           self.animate = false;
           self.checkAnswer = true;
-          }
         }
       }
+    }
 
     // Check if kid is inside the basket
     if (self.checkAnswer) {
@@ -352,11 +351,11 @@ const circleOne = {
         game.add.image(defaultWidth / 2, defaultHeight / 2, 'ok').anchor(0.5, 0.5);
         completedLevels++;
         if (debugMode) console.log('completedLevels = ' + completedLevels);
-        } else {
+      } else {
         self.result = false; // Answer is incorrect
         if (audioStatus) game.audio.errorSound.play();
         game.add.image(defaultWidth / 2, defaultHeight / 2, 'error').anchor(0.5, 0.5);
-        }
+      }
 
       self.postScore();
 
@@ -364,7 +363,7 @@ const circleOne = {
       self.checkAnswer = false;
 
       self.count = 0;
-      }
+    }
 
     // Balloon flying animation
     if (self.animateEnding) {
@@ -378,11 +377,11 @@ const circleOne = {
         else mapMove = false;
 
         game.state.start('map');
-        }
       }
+    }
 
     game.render.all();
-    },
+  },
 
 
   /* EVENT HANDLER */
@@ -402,20 +401,20 @@ const circleOne = {
 
       const valid = y > 60 && (x >= cur.xWithAnchor && x <= (cur.xWithAnchor + cur.width * cur.scale));
       if (valid) self.func_clicked(x);
-      }
+    }
 
     // LEVEL B : click circle
     if (levelType == 'B') {
       self.circles.all.forEach(cur => {
         const valid = game.math.distanceToPointer(x, cur.xWithAnchor, y, cur.yWithAnchor) <= (cur.diameter / 2) * cur.scale;
         if (valid) self.func_clicked(cur);
-        });
-      }
+      });
+    }
 
     navigationIcons.func_onInputDown(x, y);
 
     game.render.all();
-    },
+  },
 
   /**
    * Called by mouse move event
@@ -432,10 +431,10 @@ const circleOne = {
       if (game.math.distanceToPointer(x, self.balloon.x, y, self.balloon.y) > 8) {
         self.balloon.x = x;
         self.basket.x = x;
-        }
+      }
 
       document.body.style.cursor = 'auto';
-      }
+    }
 
     // LEVEL B : hover circle
     if (levelType == 'B' && !self.hasClicked) {
@@ -444,15 +443,15 @@ const circleOne = {
         if (valid) {
           self.func_overCircle(cur);
           flag = true;
-          }
-        });
+        }
+      });
       if (!flag) self.func_outCircle();
-      }
+    }
 
     navigationIcons.func_onInputOver(x, y);
 
     game.render.all();
-    },
+  },
 
   /* CALLED BY EVENT HANDLER */
 
@@ -468,9 +467,9 @@ const circleOne = {
       document.body.style.cursor = 'pointer';
       for (let i in self.circles.all) {
         self.circles.all[i].alpha = (i <= cur.index) ? 1 : 0.5;
-        }
       }
-    },
+    }
+  },
 
   /**
    * (in levelType 'B')
@@ -482,9 +481,9 @@ const circleOne = {
       document.body.style.cursor = 'auto';
       self.circles.all.forEach(cur => {
         cur.alpha = 0.5;
-        });
-      }
-    },
+      });
+    }
+  },
 
   /**
    * (in levelType 'B')
@@ -501,7 +500,7 @@ const circleOne = {
         self.balloon.x = cur;
         self.basket.x = cur;
         // On levelType B
-        }
+      }
       else if (levelType == 'B') {
 
         document.body.style.cursor = 'auto';
@@ -510,12 +509,12 @@ const circleOne = {
           if (i <= cur.index) {
             self.circles.all[i].alpha = 1; // Keep selected circle
             self.fractionIndex = cur.index;
-            } else {
+          } else {
             self.circles.all[i].alpha = 0;   // Hide unselected circle
             self.kid.y += self.circles.diameter;  // Lower kid to selected circle
-            }
           }
         }
+      }
 
       if (audioStatus) game.audio.beepSound.play();
 
@@ -523,8 +522,8 @@ const circleOne = {
       if (fractionLabel) {
         self.circles.label.forEach(cur => {
           cur.forEach(cur => { cur.alpha = 0; });
-          });
-        }
+        });
+      }
 
       // Hide solution pointer
       if (self.help != undefined) self.help.alpha = 0;
@@ -536,8 +535,8 @@ const circleOne = {
       self.animate = true;
 
       game.animation.play(this.kid.animation[0]);
-      }
-    },
+    }
+  },
 
   /* GAME FUNCTIONS */
 
@@ -555,7 +554,7 @@ const circleOne = {
     // Consider it comming from both sides
     if (Math.abs(xA - xB) > 14) return false;
     else return true;
-    },
+  },
 
   /**
    * Display correct answer
@@ -567,22 +566,24 @@ const circleOne = {
         self.help.x = self.correctX;
         self.help.y = 490;
         // On levelType B
-        }
-      else {
+      } else {
         self.help.x = self.circles.all[self.endIndex - 1].x;
         self.help.y = self.circles.all[self.endIndex - 1].y - self.circles.diameter / 2;
-        }
-      self.help.alpha = 0.7;
       }
-    },
+      self.help.alpha = 0.7;
+    }
+  },
 
   /* METADATA FOR GAME */
 
   /**
-   * Saves players data after level
+   * Saves players data after level ends - to be sent to database
+   * 
+   * Attention: the "line_" prefix data table must be compatible to data table fields (MySQL server)
+   * @see /php/squareOne.js
    */
   postScore: function () {
-    // Saves player data to send to the database
+    // Creates string that is going to be sent to db
     const data = '&line_game=' + gameShape
       + '&line_mode=' + levelType
       + '&line_oper=' + sublevelType
@@ -595,6 +596,6 @@ const circleOne = {
       + ', valCircles: ' + self.divisorsList
       + ' balloonX: ' + self.basket.x
       + ', selIndex: ' + self.fractionIndex;
-    postScore(data);
-    }
-  };
+    sendToDB(data);
+  }
+};

File diff ditekan karena terlalu besar
+ 1027 - 1027
js/gameMechanics.js


+ 50 - 51
js/globals.js

@@ -7,12 +7,12 @@ LInE - Free Education, Private Data
 ........One..........Two.............One............ }
 ......./...\..........|............./...\........... 
 ......A.....B.........C............A.....B.......... } level (levelType)
-.(floor)..(stack)..(equal).....(floor).(circle)..... } 
+.(floor)..(stack)..(equal).....(floor).(stack)...... } 
 .......\./............|..............\./............ 
 ........|.............|...............|............. 
-......./.\........../.|.\.........../.|.\........... 
-...Plus...Minus....A..B..C.....Plus.Minus.Mixed..... } sublevel (sublevelType)
-.......\./..........\.|./...........\.|./........... 
+......./.\.........../.\............/.|.\........... 
+...Plus...Minus.....B...C.......Plus.Minus.Mixed.... } sublevel (sublevelType)
+.......\./...........\./............\.|./........... 
 ........|.............|...............|............. 
 ......1,2,3.......1,2,3,4,5.......1,2,3,4,5......... } difficulty (gameDifficulty)
 .................................................... 
@@ -62,7 +62,7 @@ const info = {
     levelTypeUrl: ['level0', 'level1'],
     sublevelType: ['Plus', 'Minus'],
     gameDifficulty: 3
-    },
+  },
 
   circleOne: {
     gameShape: 'circle',
@@ -72,7 +72,7 @@ const info = {
     levelTypeUrl: ['level2', 'level3'],
     sublevelType: ['Plus', 'Minus', 'Mixed'],
     gameDifficulty: 5
-    },
+  },
 
   squareTwo: {
     gameShape: 'square',
@@ -82,7 +82,7 @@ const info = {
     levelTypeUrl: [],
     sublevelType: [/*'A',*/ 'B', 'C'],
     gameDifficulty: 5
-    },
+  },
 
   gameShape: [],
   gameType: [],
@@ -101,19 +101,19 @@ const info = {
       info.squareOne.gameShape,
       info.circleOne.gameShape,
       info.squareTwo.gameShape
-      ];
+    ];
 
     info.gameType = [
       info.squareOne.gameType,
       info.circleOne.gameType,
       info.squareTwo.gameType
-      ];
+    ];
 
     info.gameTypeUrl = [
       info.squareOne.gameTypeUrl,
       info.circleOne.gameTypeUrl,
       info.squareTwo.gameTypeUrl
-      ];
+    ];
 
     info.levelType = info.squareOne.levelType.concat(info.circleOne.levelType, info.squareTwo.levelType);
 
@@ -125,9 +125,9 @@ const info = {
       info.squareOne.gameDifficulty,
       info.circleOne.gameDifficulty,
       info.squareTwo.gameDifficulty
-      ];
-    }
-  };
+    ];
+  }
+};
 
 // Colors
 const colors = {
@@ -155,7 +155,7 @@ const colors = {
   gray: '#708090',
   black: '#000',
   yellow: '#ffef1f'
-  };
+};
 
 // Text styles
 const textStyles = {
@@ -175,7 +175,7 @@ const textStyles = {
   h2_blue: { font: '26px Arial,sans-serif', fill: colors.darkBlue, align: 'center' }, // Fractions
   h4_blue: { font: '20px Arial,sans-serif', fill: colors.darkBlue, align: 'center' }, // Fractions
   p_blue: { font: '14px Arial,sans-serif', fill: colors.darkBlue, align: 'center' } // Fractions
-  };
+};
 
 // List of media URL
 const url = {
@@ -218,7 +218,7 @@ const url = {
       ['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],
@@ -226,14 +226,14 @@ const url = {
       ['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: {
     image: [
       // Game
@@ -252,33 +252,33 @@ const url = {
       ['sublevel_mixed', medSrc + 'levels/sublevel_mixed.png'], // Circle I : mixed
       ['sublevel_top', medSrc + 'levels/sublevel_top.png'], // Square II : top
       ['sublevel_bottom', medSrc + 'levels/sublevel_bottom.png']  // Square II : bottom
-      ],
+    ],
     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: {
@@ -289,14 +289,14 @@ const url = {
       // 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: []
-    },
-  };
+  },
+};
 
 // Navigation icons on the top of the screen
 const navigationIcons = {
@@ -332,19 +332,19 @@ const navigationIcons = {
       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 (leftIcon1) { // Return to main menu screen
       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 (leftIcon2) { // In some levels, shows solution to the game
       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
 
@@ -353,14 +353,14 @@ const navigationIcons = {
       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 (rightIcon1) { // Return to select language screen
       icon_world = game.add.image(right_x, 10, 'language');
       this.iconsList.push(icon_world);
       right_x -= 50; // Offsets value of x for next icon
-      }
-    },
+    }
+  },
 
   /**
    * When back icon is clicked go this state
@@ -372,7 +372,7 @@ const navigationIcons = {
 
     game.event.clear(self);
     game.state.start(state);
-    },
+  },
 
   /**
    * Called by mouse click event 
@@ -398,14 +398,14 @@ const navigationIcons = {
               audioStatus = true;
               if (audioStatus) game.audio.beepSound.play();
               navigationIcons.icon_audio.curFrame = 0;
-              }
+            }
             game.render.all();
             break;
           default: console.log('Game error: error in navigation icon');
-          }
         }
-      });
-    },
+      }
+    });
+  },
 
   /**
    * Called by mouse move event
@@ -427,25 +427,24 @@ const navigationIcons = {
 
         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;
-        }
-      });
+      }
+    });
 
     if (!flag) {
       navigationIcons.left_text.name = '';
       navigationIcons.right_text.name = '';
-      }
-    else {
+    } else {
       document.body.style.cursor = 'pointer';
-      }
     }
-  };
+  }
+};
 
 /**
  * Sends game information to database
  *  
  * @param {string} extraData player information for the current game
  */
-const postScore = function (extraData) {
+const sendToDB = function (extraData) {
 
   // Create some variables we need to send to our PHP file
   // Attention: this names must be compactible to data table (MySQL server)
@@ -467,14 +466,14 @@ const postScore = function (extraData) {
     if (debugMode) console.log(hr);
     if (hr.readyState == 4 && hr.status == 200) {
       if (debugMode) console.log(hr.responseText);
-      }
     }
+  }
 
   hr.send(data); // Actually execute the request
 
   if (debugMode) {
     console.log('processing...');
     console.log(data);
-    }
+  }
 
-  };
+};

+ 272 - 272
js/map.js

@@ -5,201 +5,201 @@
  */
 const mapState = {
 
-    /**
-     * Main code
-     */
-    create: function () {
-
-        // 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
-        navigationIcons.func_addIcons(true, true, false, // Left icons
-            false, false, // Right icons
-            'customMenu', false);
-
-        // Progress bar
-        const percentText = 4 * 25;
-
-        if (completedLevels == 4) game.add.graphic.rect(660, 10, completedLevels * 37.5, 35, undefined, 0, colors.intenseGreen, 0.5);
-        else game.add.graphic.rect(660, 10, completedLevels * 37.5, 35, undefined, 0, colors.yellow, 0.9);
-
-        game.add.graphic.rect(661, 11, 149, 34, colors.blue, 3, undefined, 1);
-        game.add.text(820, 38, percentText + '%', textStyles.h2_blue, 'left');
-        game.add.text(650, 38, game.lang.difficulty + ' ' + gameDifficulty, textStyles.h2_blue, 'right');
-
-        // Map positions
-        this.points = {
-            x: [90, 204, 318, 432, 546, 660],
-            y: [486, 422, 358, 294, 230, 166]
-        };
-
-        if (gameTypeString == 'squareOne') {
-            // Garage
-            game.add.image(this.points.x[0], this.points.y[0], 'garage', 0.4).anchor(0.5, 1);
-            // Farm
-            game.add.image(this.points.x[5], this.points.y[5], 'farm', 0.6).anchor(0.1, 0.7);
-        } else {
-            // House
-            game.add.image(this.points.x[0], this.points.y[0], 'house', 0.7).anchor(0.7, 0.8);
-            // School
-            game.add.image(this.points.x[5], this.points.y[5], 'school', 0.35).anchor(0.2, 0.7);
-        }
-
-        // Rocks and bushes
-        const rocks = {
-            x: [156, 275, 276, 441, 452, 590, 712],
-            y: [309, 543, 259, 156, 419, 136, 316],
-            type: [1, 1, 2, 1, 2, 2, 2]
-        };
-
-        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);
-            }
+  /**
+   * Main code
+   */
+  create: function () {
+
+    // 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
+    navigationIcons.func_addIcons(true, true, false, // Left icons
+      false, false, // Right icons
+      'customMenu', false);
+
+    // Progress bar
+    const percentText = 4 * 25;
+
+    if (completedLevels == 4) game.add.graphic.rect(660, 10, completedLevels * 37.5, 35, undefined, 0, colors.intenseGreen, 0.5);
+    else game.add.graphic.rect(660, 10, completedLevels * 37.5, 35, undefined, 0, colors.yellow, 0.9);
+
+    game.add.graphic.rect(661, 11, 149, 34, colors.blue, 3, undefined, 1);
+    game.add.text(820, 38, percentText + '%', textStyles.h2_blue, 'left');
+    game.add.text(650, 38, game.lang.difficulty + ' ' + gameDifficulty, textStyles.h2_blue, 'right');
+
+    // Map positions
+    this.points = {
+      x: [90, 204, 318, 432, 546, 660],
+      y: [486, 422, 358, 294, 230, 166]
+    };
+
+    if (gameTypeString == 'squareOne') {
+      // Garage
+      game.add.image(this.points.x[0], this.points.y[0], 'garage', 0.4).anchor(0.5, 1);
+      // Farm
+      game.add.image(this.points.x[5], this.points.y[5], 'farm', 0.6).anchor(0.1, 0.7);
+    } else {
+      // House
+      game.add.image(this.points.x[0], this.points.y[0], 'house', 0.7).anchor(0.7, 0.8);
+      // School
+      game.add.image(this.points.x[5], this.points.y[5], 'school', 0.35).anchor(0.2, 0.7);
+    }
+
+    // Rocks and bushes
+    const rocks = {
+      x: [156, 275, 276, 441, 452, 590, 712],
+      y: [309, 543, 259, 156, 419, 136, 316],
+      type: [1, 1, 2, 1, 2, 2, 2]
+    };
+
+    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],
+      type: [2, 4, 3, 4, 1, 2, 4, 4]
+    };
+
+    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 i = 1; i < this.points.x.length - 1; i++) {
+
+      const aux = (i < mapPosition || (mapMove && i == mapPosition)) ? 'place_on' : 'place_off';
+
+      // 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.h2_white);
+
+    }
+
+    // Game Character 
+    if (gameTypeString == 'squareOne') {
+
+      if (sublevelType == 'Plus') {
+        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 = 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.rotate = -30; // 25 anticlock
+
+    } else {
+
+      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(0.5, 1);
+    game.animation.play(this.character.animation[0]);
+
+    this.count = 0;
+
+    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', this.func_onInputDown);
+    game.event.add('mousemove', this.func_onInputOver);
+
+  },
+
+  /**
+   * Game loop
+   */
+  update: function () {
+
+    let endUpdate = false;
+
+    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
         }
+      }
 
-        // Trees
-        const trees = {
-            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]
-        };
+      if (!mapMove) {
+        endUpdate = true;
+      }
 
-        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 i = 1; i < this.points.x.length - 1; i++) {
 
-            const aux = (i < mapPosition || (mapMove && i == mapPosition)) ? 'place_on' : 'place_off';
+    }
 
-            // Map road positions
-            game.add.image(this.points.x[i], this.points.y[i], aux, 0.3).anchor(0.5, 0.5);
+    game.render.all();
 
-            // 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.h2_white);
+    if (endUpdate) {
+      game.animation.stop(self.character.animation[0]);
+      self.func_loadGame();
+    }
 
-        }
+  },
 
-        // Game Character 
-        if (gameTypeString == 'squareOne') {
 
-            if (sublevelType == 'Plus') {
-                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 = 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.rotate = -30; // 25 anticlock
-
-        } else {
-
-            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];
-
-        }
+  /* EVENT HANDLER */
 
-        this.character.anchor(0.5, 1);
-        game.animation.play(this.character.animation[0]);
+  /**
+   * Called by mouse click event
+   * 
+   * @param {object} mouseEvent contains the mouse click coordinates
+   */
+  func_onInputDown: function (mouseEvent) {
+    navigationIcons.func_onInputDown(mouseEvent.offsetX, mouseEvent.offsetY);
+  },
 
-        this.count = 0;
+  /**
+   * Called by mouse move event
+   * 
+   * @param {object} mouseEvent contains the mouse move coordinates
+   */
+  func_onInputOver: function (mouseEvent) {
+    navigationIcons.func_onInputOver(mouseEvent.offsetX, mouseEvent.offsetY);
+  },
 
-        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', this.func_onInputDown);
-        game.event.add('mousemove', this.func_onInputOver);
 
-    },
+  /* GAME FUNCTIONS */
 
-    /**
-     * Game loop
-     */
-    update: function () {
+  /**
+   * Calls game state
+   */
+  func_loadGame: function () {
 
-        let endUpdate = false;
-
-        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 (!mapMove) {
-                endUpdate = true;
-            }
-
-
-        }
-
-        game.render.all();
-
-        if (endUpdate) {
-            game.animation.stop(self.character.animation[0]);
-            self.func_loadGame();
-        }
+    if (audioStatus) game.audio.beepSound.play();
 
-    },
+    if (mapPosition <= 4) game.state.start('' + gameTypeString + '');
+    else game.state.start('end');
 
-
-
-    /* EVENT HANDLER */
-
-    /**
-     * Called by mouse click event
-     * 
-     * @param {object} mouseEvent contains the mouse click coordinates
-     */
-    func_onInputDown: function (mouseEvent) {
-        navigationIcons.func_onInputDown(mouseEvent.offsetX, mouseEvent.offsetY);
-    },
-
-    /**
-     * Called by mouse move event
-     * 
-     * @param {object} mouseEvent contains the mouse move coordinates
-     */
-    func_onInputOver: function (mouseEvent) {
-        navigationIcons.func_onInputOver(mouseEvent.offsetX, mouseEvent.offsetY);
-    },
-
-
-
-    /* GAME FUNCTIONS */
-
-    /**
-     * Calls game state
-     */
-    func_loadGame: function () {
-
-        if (audioStatus) game.audio.beepSound.play();
-
-        if (mapPosition <= 4) game.state.start('' + gameTypeString + '');
-        else game.state.start('end');
-
-    },
+  },
 
 };
 
@@ -210,146 +210,146 @@ const mapState = {
  */
 const endState = {
 
-    /**
-     * Main code
-     */
-    create: function () {
+  /**
+   * Main code
+   */
+  create: function () {
 
-        self.preAnimate = false;
-        self.animate = true;
+    self.preAnimate = false;
+    self.animate = true;
 
-        // Background color
-        game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
+    // Background color
+    game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
 
-        // Background
-        game.add.image(0, 0, 'bgimage');
+    // 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', 0.8);
+    // Clouds
+    game.add.image(300, 100, 'cloud');
+    game.add.image(660, 80, 'cloud');
+    game.add.image(110, 85, 'cloud', 0.8);
 
-        // Floor
-        for (let i = 0; i < 9; i++) { game.add.image(i * 100, 501, 'floor'); }
+    // Floor
+    for (let i = 0; i < 9; i++) { game.add.image(i * 100, 501, 'floor'); }
 
-        // Progress bar
-        game.add.graphic.rect(660, 10, 4 * 37.5, 35, undefined, 0, colors.intenseGreen, 0.5); // Progress
-        game.add.graphic.rect(661, 11, 149, 34, colors.blue, 3, undefined, 1); // Box
-        game.add.text(820, 38, '100%', textStyles.h2_blue, 'left');
-        game.add.text(650, 38, game.lang.difficulty + ' ' + gameDifficulty, textStyles.h2_blue, 'right');
+    // Progress bar
+    game.add.graphic.rect(660, 10, 4 * 37.5, 35, undefined, 0, colors.intenseGreen, 0.5); // Progress
+    game.add.graphic.rect(661, 11, 149, 34, colors.blue, 3, undefined, 1); // Box
+    game.add.text(820, 38, '100%', textStyles.h2_blue, 'left');
+    game.add.text(650, 38, game.lang.difficulty + ' ' + gameDifficulty, textStyles.h2_blue, 'right');
 
-        game.add.image(360, 545, 'tree4', 0.7).anchor(0, 1);
+    game.add.image(360, 545, 'tree4', 0.7).anchor(0, 1);
 
-        // Level character
-        switch (gameTypeString) {
+    // Level character
+    switch (gameTypeString) {
 
-            case 'circleOne':
+      case 'circleOne':
 
-                this.preAnimate = true;
-                this.animate = false;
+        this.preAnimate = true;
+        this.animate = false;
 
-                // School
-                game.add.image(600, 222, 'school', 0.7);
+        // 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];
+        // 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);
+        // 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);
+        this.basket = game.add.image(0, -150, 'balloon_basket');
+        this.basket.anchor(0.5, 0.5);
 
-                break;
+        break;
 
-            case 'squareTwo':
+      case 'squareTwo':
 
-                // School
-                game.add.image(600, 222, 'school', 0.7);
+        // 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];
+        // 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;
+        break;
 
-            case 'squareOne':
+      case 'squareOne':
 
-                // Farm
-                game.add.image(650, 260, 'farm', 1.1);
+        // 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];
-                }
+        // 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;
+        break;
 
-        }
+    }
 
-        if (this.animate) game.animation.play(this.character.animation[0]);
+    if (this.animate) game.animation.play(this.character.animation[0]);
 
-        game.add.image(30, 585, 'tree4', 0.85).anchor(0, 1);
+    game.add.image(30, 585, 'tree4', 0.85).anchor(0, 1);
 
-    },
+  },
 
-    /**
-     * Game loop
-     */
-    update: function () {
+  /**
+   * Game loop
+   */
+  update: function () {
 
-        // Balloon falling
-        if (self.preAnimate) {
+    // Balloon falling
+    if (self.preAnimate) {
 
-            if (self.character.y < 460) {
+      if (self.character.y < 460) {
 
-                self.balloon.y += 2;
-                self.basket.y += 2;
-                self.character.y += 2;
+        self.balloon.y += 2;
+        self.basket.y += 2;
+        self.character.y += 2;
 
-                self.balloon.x++;
-                self.basket.x++;
-                self.character.x++;
+        self.balloon.x++;
+        self.basket.x++;
+        self.character.x++;
 
-            } else {
+      } else {
 
-                self.preAnimate = false;
-                self.animate = true;
-                game.animation.play(self.character.animation[0]);
+        self.preAnimate = false;
+        self.animate = true;
+        game.animation.play(self.character.animation[0]);
 
-            }
+      }
 
-        }
+    }
 
-        // Character running
-        if (self.animate) {
+    // Character running
+    if (self.animate) {
 
-            if (self.character.x <= 700) {
+      if (self.character.x <= 700) {
 
-                self.character.x += 2;
+        self.character.x += 2;
 
-            } else {
+      } else {
 
-                animate = false;
-                completedLevels = 0;
-                game.animation.stop(self.character.animation[0]);
-                game.state.start('menu');
+        animate = false;
+        completedLevels = 0;
+        game.animation.stop(self.character.animation[0]);
+        game.state.start('menu');
 
-            }
+      }
 
-        }
+    }
 
-        game.render.all();
+    game.render.all();
 
-    },
+  },
 
 };

+ 421 - 421
js/menu.js

@@ -5,190 +5,190 @@
  */
 const menuState = {
 
-    /**
-     * Preloads media for current state
-     */
-    preload: function () {
+  /**
+   * Preloads media for current state
+   */
+  preload: function () {
 
-        // LOADING MEDIA
-        game.load.image(url.menu.image);
+    // LOADING MEDIA
+    game.load.image(url.menu.image);
 
-    },
+  },
 
-    /**
-     * Main code
-     */
-    create: function () {
+  /**
+   * Main code
+   */
+  create: function () {
 
-        // BACKGROUND
+    // BACKGROUND
 
-        game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
+    game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
 
-        for (let i = 0; i < defaultWidth / 100; i++) {
-            game.add.image(i * 100, 501, 'floor');
-        }
+    for (let i = 0; i < defaultWidth / 100; i++) {
+      game.add.image(i * 100, 501, 'floor');
+    }
 
-        // LABELS
+    // LABELS
 
-        // Overtitle: Welcome, <player name>!
-        game.add.text(defaultWidth / 2, 40, game.lang.welcome + ', ' + playerName + '!', textStyles.h4_brown);
+    // Overtitle: Welcome, <player name>!
+    game.add.text(defaultWidth / 2, 40, game.lang.welcome + ', ' + playerName + '!', textStyles.h4_brown);
 
-        // Title : Select a game
-        game.add.text(defaultWidth / 2, 80, game.lang.menu_title, textStyles.h1_green);
+    // Title : Select a game
+    game.add.text(defaultWidth / 2, 80, game.lang.menu_title, textStyles.h1_green);
 
-        // Subtitle : <game mode> 
-        this.lbl_game = game.add.text(defaultWidth / 2, 110, '', textStyles.h2_blue_2);
+    // Subtitle : <game mode> 
+    this.lbl_game = game.add.text(defaultWidth / 2, 110, '', textStyles.h2_blue_2);
 
-        // NAVIGATION ICONS
+    // NAVIGATION ICONS
 
-        // Loads navigation icons
-        navigationIcons.func_addIcons(
-            false, false, false,
-            true, true,
-            false, false);
+    // Loads navigation icons
+    navigationIcons.func_addIcons(
+      false, false, false,
+      true, true,
+      false, false);
 
-        // -------------------- GAME ICONS 
-        this.menuIcons = [];
+    // -------------------- GAME ICONS 
+    this.menuIcons = [];
 
-        const offset = defaultWidth / (info.gameType.length + 1);
+    const offset = defaultWidth / (info.gameType.length + 1);
 
-        for (let i = 0, x = offset; i < info.gameType.length; i++, x += offset) {
+    for (let i = 0, x = offset; i < info.gameType.length; i++, x += offset) {
 
-            const icon = game.add.image(x, defaultHeight / 2 - 70, info.gameTypeUrl[i], 1);
-            icon.anchor(0.5, 0.5);
+      const icon = game.add.image(x, defaultHeight / 2 - 70, info.gameTypeUrl[i], 1);
+      icon.anchor(0.5, 0.5);
 
-            icon.gameShape = info.gameShape[i];
-            icon.gameType = info.gameType[i];
+      icon.gameShape = info.gameShape[i];
+      icon.gameType = info.gameType[i];
 
-            this.menuIcons.push(icon);
+      this.menuIcons.push(icon);
 
-        }
+    }
 
-        // EVENTS
+    // EVENTS
 
-        game.event.add('click', this.func_onInputDown);
-        game.event.add('mousemove', this.func_onInputOver);
+    game.event.add('click', this.func_onInputDown);
+    game.event.add('mousemove', this.func_onInputOver);
 
-    },
+  },
 
 
 
-    /* EVENTS */
+  /* EVENTS */
 
-    /**
-     * Called by mouse click event
-     * 
-     * @param {object} mouseEvent contains the mouse click coordinates
-     */
-    func_onInputDown: function (mouseEvent) {
-        const x = mouseEvent.offsetX, y = mouseEvent.offsetY;
+  /**
+   * Called by mouse click event
+   * 
+   * @param {object} mouseEvent contains the mouse click coordinates
+   */
+  func_onInputDown: function (mouseEvent) {
+    const x = mouseEvent.offsetX, y = mouseEvent.offsetY;
 
-        // Check menu icons
-        for (let i in self.menuIcons) {
-            // If mouse is within the bounds of an icon
-            if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
-                // Click first valid icon
-                self.func_load(self.menuIcons[i]);
-                break;
-            }
-        }
+    // Check menu icons
+    for (let i in self.menuIcons) {
+      // If mouse is within the bounds of an icon
+      if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
+        // Click first valid icon
+        self.func_load(self.menuIcons[i]);
+        break;
+      }
+    }
 
-        // Check navigation icons
-        navigationIcons.func_onInputDown(x, y);
-    },
-
-    /**
-     * Called by mouse move event
-     * 
-     * @param {object} mouseEvent contains the mouse move coordinates
-     */
-    func_onInputOver: function (mouseEvent) {
-        const x = mouseEvent.offsetX, y = mouseEvent.offsetY;
-        let flag = false;
-
-        // Check menu icons
-        self.menuIcons.forEach(cur => {
-            if (game.math.isOverIcon(x, y, cur)) {
-                cur.scale = 1.08;
-                self.func_showTitle(cur);
-                flag = true;
-            } else {
-                cur.scale = 1;
-            }
-        });
-
-        if (flag) {
-            document.body.style.cursor = 'pointer';
-        } else {
-            self.func_clearTitle();
-            document.body.style.cursor = 'auto';
-        }
+    // Check navigation icons
+    navigationIcons.func_onInputDown(x, y);
+  },
 
-        // Check navigation icons
-        navigationIcons.func_onInputOver(x, y);
+  /**
+   * Called by mouse move event
+   * 
+   * @param {object} mouseEvent contains the mouse move coordinates
+   */
+  func_onInputOver: function (mouseEvent) {
+    const x = mouseEvent.offsetX, y = mouseEvent.offsetY;
+    let flag = false;
 
-        game.render.all();
-    },
+    // Check menu icons
+    self.menuIcons.forEach(cur => {
+      if (game.math.isOverIcon(x, y, cur)) {
+        cur.scale = 1.08;
+        self.func_showTitle(cur);
+        flag = true;
+      } else {
+        cur.scale = 1;
+      }
+    });
 
+    if (flag) {
+      document.body.style.cursor = 'pointer';
+    } else {
+      self.func_clearTitle();
+      document.body.style.cursor = 'auto';
+    }
 
+    // Check navigation icons
+    navigationIcons.func_onInputOver(x, y);
 
-    /* GAME FUNCTIONS */
+    game.render.all();
+  },
 
-    /**
-     * Saves info from selected game and goes to next state
-     * 
-     * @param {object} icon clicked icon
-     */
-    func_load: function (icon) {
 
-        if (audioStatus) game.audio.beepSound.play();
 
-        gameShape = icon.gameShape;
-        gameTypeString = icon.gameType;
-        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');
-        }
+  /* GAME FUNCTIONS */
 
-        self.menuIcons = self.lbl_game.name;
+  /**
+   * Saves info from selected game and goes to next state
+   * 
+   * @param {object} icon clicked icon
+   */
+  func_load: function (icon) {
 
-        game.state.start('customMenu');
+    if (audioStatus) game.audio.beepSound.play();
 
-    },
+    gameShape = icon.gameShape;
+    gameTypeString = icon.gameType;
+    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');
+    }
 
-    /**
-     * Display the name of the game on screen
-     * 
-     * @param {object} icon icon for the game
-     */
-    func_showTitle: function (icon) {
+    self.menuIcons = self.lbl_game.name;
 
-        let title;
+    game.state.start('customMenu');
 
-        switch (icon.gameShape) {
-            case 'circle': title = game.lang.circle_name; break;
-            case 'square': title = game.lang.square_name; break;
-        }
+  },
 
-        const type = icon.gameType.substring(icon.gameType.length - 3);
+  /**
+   * Display the name of the game on screen
+   * 
+   * @param {object} icon icon for the game
+   */
+  func_showTitle: function (icon) {
 
-        switch (type) {
-            case 'One': title += ' I'; break;
-            case 'Two': title += ' II'; break;
-        }
-
-        self.lbl_game.name = title;
-
-    },
-
-    /**
-     * Remove the name of the game from screen
-     */
-    func_clearTitle: function () {
-        self.lbl_game.name = '';
-    },
+    let title;
+
+    switch (icon.gameShape) {
+      case 'circle': title = game.lang.circle_name; break;
+      case 'square': title = game.lang.square_name; break;
+    }
+
+    const type = icon.gameType.substring(icon.gameType.length - 3);
+
+    switch (type) {
+      case 'One': title += ' I'; break;
+      case 'Two': title += ' II'; break;
+    }
+
+    self.lbl_game.name = title;
+
+  },
+
+  /**
+   * Remove the name of the game from screen
+   */
+  func_clearTitle: function () {
+    self.lbl_game.name = '';
+  },
 
 };
 
@@ -199,344 +199,344 @@ const menuState = {
  */
 const customMenuState = {
 
-    /**
-     * Preloads media for current state
-     */
-    preload: function () {
+  /**
+   * Preloads media for current state
+   */
+  preload: function () {
 
-        // LOADING MEDIA
-        game.load.sprite(url[gameTypeString].sprite);
-        game.load.image(url[gameTypeString].image);
+    // LOADING MEDIA
+    game.load.sprite(url[gameTypeString].sprite);
+    game.load.image(url[gameTypeString].image);
 
-    },
+  },
 
-    /**
-     * Main code
-     */
-    create: function () {
+  /**
+   * Main code
+   */
+  create: function () {
 
-        let x, y, width, height, offsetH, offsetW;
-        const iconScale = 0.5;
+    let x, y, width, height, offsetH, offsetW;
+    const iconScale = 0.5;
 
-        // Background color
-        game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
+    // Background color
+    game.add.graphic.rect(0, 0, 900, 600, undefined, 0, colors.blueBckg, 1);
 
-        // Floor
-        for (let i = 0; i < defaultWidth / 100; i++) { game.add.image(i * 100, 501, 'floor'); }
+    // Floor
+    for (let i = 0; i < defaultWidth / 100; i++) { game.add.image(i * 100, 501, 'floor'); }
 
-        // LABELS
+    // LABELS
 
-        // Add Title : Select a game
-        game.add.text(defaultWidth / 2, 80, game.lang.custom_game, textStyles.h1_green);
+    // Add Title : Select a game
+    game.add.text(defaultWidth / 2, 80, game.lang.custom_game, textStyles.h1_green);
 
-        // Selected game
-        game.add.text(defaultWidth / 2, 40, menuState.menuIcons, textStyles.h4_brown);
+    // Selected game
+    game.add.text(defaultWidth / 2, 40, menuState.menuIcons, textStyles.h4_brown);
 
-        // Loads animation icons
-        navigationIcons.func_addIcons(
-            true, false, false,
-            true, true,
-            'menu', false);
+    // Loads animation icons
+    navigationIcons.func_addIcons(
+      true, false, false,
+      true, true,
+      'menu', false);
 
 
-        this.menuIcons = [];
+    this.menuIcons = [];
 
-        offsetW = 600 / 6;
-        x = 150;
-        y = 200;
-        height = 280;
-        width = 5;
+    offsetW = 600 / 6;
+    x = 150;
+    y = 200;
+    height = 280;
+    width = 5;
 
-        // Label 'Level'
-        game.add.text(x + offsetW, y, game.lang.level, textStyles.h2_blue_2);
-        // Label 'Sublevel'
-        const sublevelLabel = game.add.text(x + 3 * offsetW, y, game.lang.sublevel, textStyles.h2_blue_2);
-        // Label 'Difficulty'
-        game.add.text(x + 5 * offsetW, y, game.lang.difficulty, textStyles.h2_blue_2);
+    // Label 'Level'
+    game.add.text(x + offsetW, y, game.lang.level, textStyles.h2_blue_2);
+    // Label 'Sublevel'
+    const sublevelLabel = game.add.text(x + 3 * offsetW, y, game.lang.sublevel, textStyles.h2_blue_2);
+    // Label 'Difficulty'
+    game.add.text(x + 5 * offsetW, y, game.lang.difficulty, textStyles.h2_blue_2);
 
-        // Horizontal line
-        game.add.graphic.rect(x, y + 10, 600, width, undefined, 0, colors.blueMenuLine).anchor(0, 0.5);
+    // Horizontal line
+    game.add.graphic.rect(x, y + 10, 600, width, undefined, 0, colors.blueMenuLine).anchor(0, 0.5);
 
-        // Vertical line
-        game.add.graphic.rect(x + 2 * offsetW, y - 25, width, height, undefined, 0, colors.blueMenuLine).anchor(0.5, 0);
-        game.add.graphic.rect(x + 4 * offsetW, y - 25, width, height, undefined, 0, colors.blueMenuLine).anchor(0.5, 0);
+    // Vertical line
+    game.add.graphic.rect(x + 2 * offsetW, y - 25, width, height, undefined, 0, colors.blueMenuLine).anchor(0.5, 0);
+    game.add.graphic.rect(x + 4 * offsetW, y - 25, width, height, undefined, 0, colors.blueMenuLine).anchor(0.5, 0);
 
-        // --------------------------- TURN ON/OFF FRACTION LABELS
+    // --------------------------- TURN ON/OFF FRACTION LABELS
 
-        if (gameTypeString == 'squareTwo') {
+    if (gameTypeString == 'squareTwo') {
 
-            sublevelLabel.alpha = 0.3;
+      sublevelLabel.alpha = 0.3;
 
-        } else {
+    } else {
 
-            // Horizontal line
-            game.add.graphic.rect(x + 4 * offsetW, y + 136, 200, width, undefined, 0, colors.blueMenuLine).anchor(0, 0.5);
+      // Horizontal line
+      game.add.graphic.rect(x + 4 * offsetW, y + 136, 200, width, undefined, 0, colors.blueMenuLine).anchor(0, 0.5);
 
-            // Label 'Show Fractions'
-            game.add.text(x + 5 * offsetW, y + 102, game.lang.show, textStyles.h4_blue_2);
-            game.add.text(x + 5 * offsetW, y + 102 + 24, game.lang.title, textStyles.h2_blue_2);
+      // Label 'Show Fractions'
+      game.add.text(x + 5 * offsetW, y + 102, game.lang.show, textStyles.h4_blue_2);
+      game.add.text(x + 5 * offsetW, y + 102 + 24, game.lang.title, textStyles.h2_blue_2);
 
-            const frame = (fractionLabel) ? 1 : 0;
+      const frame = (fractionLabel) ? 1 : 0;
 
-            // Selection box
-            y += 40;
-            const selectionBox = game.add.sprite(x + 5 * offsetW, y + 102 + 24 - 2, 'select', frame, 0.1);
-            selectionBox.anchor(0.5, 0.5);
-            selectionBox.iconType = 'selectionBox';
-            selectionBox.originalScale = 0.1;
-            this.menuIcons.push(selectionBox);
-        }
+      // Selection box
+      y += 40;
+      const selectionBox = game.add.sprite(x + 5 * offsetW, y + 102 + 24 - 2, 'select', frame, 0.1);
+      selectionBox.anchor(0.5, 0.5);
+      selectionBox.iconType = 'selectionBox';
+      selectionBox.originalScale = 0.1;
+      this.menuIcons.push(selectionBox);
+    }
 
-        // ---------------------------- LEVEL ICONS
+    // ---------------------------- LEVEL ICONS
 
-        offsetH = this.func_getOffset(height, info[gameTypeString].levelType.length);
+    offsetH = this.func_getOffset(height, info[gameTypeString].levelType.length);
 
-        x = 150 + offsetW;
-        y = 270;
+    x = 150 + offsetW;
+    y = 270;
 
-        for (let i = 0; i < info[gameTypeString].levelTypeUrl.length; i++, y += offsetH) {
+    for (let i = 0; i < info[gameTypeString].levelTypeUrl.length; i++, y += offsetH) {
 
-            const icon = game.add.image(x, y, info[gameTypeString].levelTypeUrl[i], iconScale, 1);
-            icon.anchor(0.5, 0.5);
+      const icon = game.add.image(x, y, info[gameTypeString].levelTypeUrl[i], iconScale, 1);
+      icon.anchor(0.5, 0.5);
 
-            icon.levelType = info[gameTypeString].levelType[i];
-            icon.iconType = 'level';
-            icon.originalScale = iconScale;
-            if (i == 0) {
-                levelType = icon.levelType;
-                icon.shadow = true;
-            }
+      icon.levelType = info[gameTypeString].levelType[i];
+      icon.iconType = 'level';
+      icon.originalScale = iconScale;
+      if (i == 0) {
+        levelType = icon.levelType;
+        icon.shadow = true;
+      }
 
-            this.menuIcons.push(icon);
+      this.menuIcons.push(icon);
 
-        }
+    }
 
-        // ---------------------------- SUBLEVEL ICONS
-
-        offsetH = this.func_getOffset(height, info[gameTypeString].sublevelType.length);
-
-        if (gameTypeString != 'squareTwo') x += 2 * offsetW;
-        y = 270;
-
-        let icon;
-        let aux = [];
-        aux['squareOne'] = [
-            ['sublevel_right', 'Plus'],
-            ['sublevel_left', 'Minus']
-        ];
-        aux['circleOne'] = [
-            ['sublevel_right', 'Plus'],
-            ['sublevel_left', 'Minus'],
-            ['sublevel_mixed', 'Mixed']
-        ];
-        aux['squareTwo'] = [
-            // ['sublevel_top', 'A'],
-            ['sublevel_bottom', 'B'],
-            ['sublevel_top', 'C'],
-        ];
-        // Placing sublevel icons
-        for (let i = 0; i < aux[gameTypeString].length; i++, y += offsetH) {
-
-            icon = game.add.image(x, y, aux[gameTypeString][i][0], iconScale);
-            icon.anchor(0.5, 0.5);
-            icon.alpha = 1;
-
-            icon.sublevelType = aux[gameTypeString][i][1];
-            icon.iconType = 'sublevel';
-            icon.originalScale = iconScale;
-
-            if (i == 0) {
-                sublevelType = icon.sublevelType;
-                icon.shadow = true;
-            }
-
-            this.menuIcons.push(icon);
+    // ---------------------------- SUBLEVEL ICONS
 
-        }
+    offsetH = this.func_getOffset(height, info[gameTypeString].sublevelType.length);
 
-        // --------------------------- DIFFICULTY ICONS
+    if (gameTypeString != 'squareTwo') x += 2 * offsetW;
+    y = 270;
 
-        x = (gameTypeString == 'squareOne') ? 600 : 570;
-        y = 235;
+    let icon;
+    let aux = [];
+    aux['squareOne'] = [
+      ['sublevel_right', 'Plus'],
+      ['sublevel_left', 'Minus']
+    ];
+    aux['circleOne'] = [
+      ['sublevel_right', 'Plus'],
+      ['sublevel_left', 'Minus'],
+      ['sublevel_mixed', 'Mixed']
+    ];
+    aux['squareTwo'] = [
+      // ['sublevel_top', 'A'],
+      ['sublevel_bottom', 'B'],
+      ['sublevel_top', 'C'],
+    ];
+    // Placing sublevel icons
+    for (let i = 0; i < aux[gameTypeString].length; i++, y += offsetH) {
 
-        for (let i = 0; i < info[gameTypeString].gameDifficulty; i++) {
+      icon = game.add.image(x, y, aux[gameTypeString][i][0], iconScale);
+      icon.anchor(0.5, 0.5);
+      icon.alpha = 1;
 
-            // Parameters
-            const curX = x + (30 + 10) * i;
+      icon.sublevelType = aux[gameTypeString][i][1];
+      icon.iconType = 'sublevel';
+      icon.originalScale = iconScale;
 
-            // Difficulty menuIcons
-            const icon = game.add.graphic.rect(curX, y, 30, 30, undefined, 0, colors.green, 1);
-            icon.anchor(0.5, 0.5);
-            icon.difficulty = i + 1;
-            icon.iconType = 'difficulty';
-            icon.originalScale = 1;
+      if (i == 0) {
+        sublevelType = icon.sublevelType;
+        icon.shadow = true;
+      }
 
-            if (i == 0) {
-                gameDifficulty = icon.difficulty;
-                icon.shadow = true;
-            }
-            this.menuIcons.push(icon);
+      this.menuIcons.push(icon);
 
-            // Difficulty numbers
-            game.add.text(curX, y + 7, i + 1, textStyles.h4_white);
+    }
 
-        }
+    // --------------------------- DIFFICULTY ICONS
 
-        // -------------- ENTER ICON
-
-        x = defaultWidth - 100;
-        y = defaultHeight - 110;
-
-        const enterIcon = game.add.image(x, y, 'bush');
-        enterIcon.anchor(0.5, 0.5);
-        enterIcon.iconType = 'enter';
-        enterIcon.originalScale = 0.9;
-
-        this.menuIcons.push(enterIcon);
-
-        game.add.text(x, y, game.lang.continue.toUpperCase(), textStyles.p_white);
-
-        // EVENTS
-
-        game.event.add('click', this.func_onInputDown);
-        game.event.add('mousemove', this.func_onInputOver);
-
-    },
-
-    /* GAME FUNCTIONS */
-
-    /**
-     * Saves information selected by the player 
-     * 
-     * @param {object} icon selected icon
-     */
-    func_load: function (icon) {
-
-        if (audioStatus) game.audio.beepSound.play();
-
-        const type = icon.iconType;
-        switch (type) {
-            case 'level': levelType = icon.levelType; break;
-            case 'sublevel': sublevelType = icon.sublevelType; break;
-            case 'difficulty': gameDifficulty = icon.difficulty; break;
-            case 'selectionBox':
-                if (icon.curFrame == 0) {
-                    icon.curFrame = 1;
-                    fractionLabel = true;
-                } else {
-                    icon.curFrame = 0;
-                    fractionLabel = false;
-                }
-                game.render.all();
-                break;
-            case 'enter':
-                if (debugMode) console.log('Game State: ' + gameTypeString + ', ' + levelType);
-                mapPosition = 0;      // Map position
-                mapMove = true;       // Move no next point
-                completedLevels = 0;  // Reset the game progress when entering a new level
-                game.state.start('map');
-                break;
-        }
+    x = (gameTypeString == 'squareOne') ? 600 : 570;
+    y = 235;
 
-    },
-
-    /**
-     * Calculate spacing for icons on the menu screen
-     * 
-     * @param {number} width width of the available part of the screen
-     * @param {number} numberOfIcons number or icons to be put on the screen
-     * @returns {number}
-     */
-    func_getOffset: function (width, numberOfIcons) {
-        return width / (numberOfIcons + 1);
-    },
-
-    /* EVENTS */
-
-    /**
-     * Called by mouse click event
-     * 
-     * @param {object} mouseEvent contains the mouse click coordinates
-     */
-    func_onInputDown: function (mouseEvent) {
-        const x = mouseEvent.offsetX, y = mouseEvent.offsetY;
-        let overIcon;
-
-        // Check if clicked on an icon
-        for (let i in self.menuIcons) {
-            if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
-                overIcon = i;
-                break;
-            }
-        }
+    for (let i = 0; i < info[gameTypeString].gameDifficulty; i++) {
 
-        // Update gui
-        if (overIcon) {
+      // Parameters
+      const curX = x + (30 + 10) * i;
 
-            document.body.style.cursor = 'pointer';
+      // Difficulty menuIcons
+      const icon = game.add.graphic.rect(curX, y, 30, 30, undefined, 0, colors.green, 1);
+      icon.anchor(0.5, 0.5);
+      icon.difficulty = i + 1;
+      icon.iconType = 'difficulty';
+      icon.originalScale = 1;
 
-            self.menuIcons.forEach(cur => {
-                if (cur.iconType == self.menuIcons[overIcon].iconType) {
-                    if (cur == self.menuIcons[overIcon]) {
-                        cur.shadow = true;
-                    } else {
-                        cur.shadow = false;
-                    }
-                }
-            });
+      if (i == 0) {
+        gameDifficulty = icon.difficulty;
+        icon.shadow = true;
+      }
+      this.menuIcons.push(icon);
 
-            self.func_load(self.menuIcons[overIcon]);
+      // Difficulty numbers
+      game.add.text(curX, y + 7, i + 1, textStyles.h4_white);
 
-        } else document.body.style.cursor = 'auto';
+    }
 
-        navigationIcons.func_onInputDown(x, y);
+    // -------------- ENTER ICON
 
-        game.render.all();
+    x = defaultWidth - 100;
+    y = defaultHeight - 110;
 
-    },
-
-    /**
-     * Called by mouse move event
-     * 
-     * @param {object} mouseEvent contains the mouse move coordinates
-     */
-    func_onInputOver: function (mouseEvent) {
-        const x = mouseEvent.offsetX, y = mouseEvent.offsetY;
-        let overIcon;
-
-        // Check if pointer is over an icon
-        for (let i in self.menuIcons) {
-            if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
-                overIcon = i;
-                break;
-            }
-        }
+    const enterIcon = game.add.image(x, y, 'bush');
+    enterIcon.anchor(0.5, 0.5);
+    enterIcon.iconType = 'enter';
+    enterIcon.originalScale = 0.9;
+
+    this.menuIcons.push(enterIcon);
+
+    game.add.text(x, y, game.lang.continue.toUpperCase(), textStyles.p_white);
+
+    // EVENTS
+
+    game.event.add('click', this.func_onInputDown);
+    game.event.add('mousemove', this.func_onInputOver);
 
-        // Update gui
-        if (overIcon) {
-            document.body.style.cursor = 'pointer';
-
-            self.menuIcons.forEach(cur => {
-                if (cur.iconType == self.menuIcons[overIcon].iconType) {
-                    if (cur == self.menuIcons[overIcon]) {
-                        cur.scale = cur.originalScale * 1.1;
-                    } else {
-                        cur.scale = cur.originalScale;
-                    }
-                }
-            });
+  },
+
+  /* GAME FUNCTIONS */
+
+  /**
+   * Saves information selected by the player 
+   * 
+   * @param {object} icon selected icon
+   */
+  func_load: function (icon) {
+
+    if (audioStatus) game.audio.beepSound.play();
+
+    const type = icon.iconType;
+    switch (type) {
+      case 'level': levelType = icon.levelType; break;
+      case 'sublevel': sublevelType = icon.sublevelType; break;
+      case 'difficulty': gameDifficulty = icon.difficulty; break;
+      case 'selectionBox':
+        if (icon.curFrame == 0) {
+          icon.curFrame = 1;
+          fractionLabel = true;
         } else {
-            self.menuIcons.forEach(cur => {
-                cur.scale = cur.originalScale;
-            });
-            document.body.style.cursor = 'auto';
+          icon.curFrame = 0;
+          fractionLabel = false;
         }
+        game.render.all();
+        break;
+      case 'enter':
+        if (debugMode) console.log('Game State: ' + gameTypeString + ', ' + levelType);
+        mapPosition = 0;      // Map position
+        mapMove = true;       // Move no next point
+        completedLevels = 0;  // Reset the game progress when entering a new level
+        game.state.start('map');
+        break;
+    }
+
+  },
+
+  /**
+   * Calculate spacing for icons on the menu screen
+   * 
+   * @param {number} width width of the available part of the screen
+   * @param {number} numberOfIcons number or icons to be put on the screen
+   * @returns {number}
+   */
+  func_getOffset: function (width, numberOfIcons) {
+    return width / (numberOfIcons + 1);
+  },
+
+  /* EVENTS */
+
+  /**
+   * Called by mouse click event
+   * 
+   * @param {object} mouseEvent contains the mouse click coordinates
+   */
+  func_onInputDown: function (mouseEvent) {
+    const x = mouseEvent.offsetX, y = mouseEvent.offsetY;
+    let overIcon;
+
+    // Check if clicked on an icon
+    for (let i in self.menuIcons) {
+      if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
+        overIcon = i;
+        break;
+      }
+    }
+
+    // Update gui
+    if (overIcon) {
+
+      document.body.style.cursor = 'pointer';
+
+      self.menuIcons.forEach(cur => {
+        if (cur.iconType == self.menuIcons[overIcon].iconType) {
+          if (cur == self.menuIcons[overIcon]) {
+            cur.shadow = true;
+          } else {
+            cur.shadow = false;
+          }
+        }
+      });
+
+      self.func_load(self.menuIcons[overIcon]);
+
+    } else document.body.style.cursor = 'auto';
+
+    navigationIcons.func_onInputDown(x, y);
+
+    game.render.all();
+
+  },
+
+  /**
+   * Called by mouse move event
+   * 
+   * @param {object} mouseEvent contains the mouse move coordinates
+   */
+  func_onInputOver: function (mouseEvent) {
+    const x = mouseEvent.offsetX, y = mouseEvent.offsetY;
+    let overIcon;
+
+    // Check if pointer is over an icon
+    for (let i in self.menuIcons) {
+      if (game.math.isOverIcon(x, y, self.menuIcons[i])) {
+        overIcon = i;
+        break;
+      }
+    }
+
+    // Update gui
+    if (overIcon) {
+      document.body.style.cursor = 'pointer';
+
+      self.menuIcons.forEach(cur => {
+        if (cur.iconType == self.menuIcons[overIcon].iconType) {
+          if (cur == self.menuIcons[overIcon]) {
+            cur.scale = cur.originalScale * 1.1;
+          } else {
+            cur.scale = cur.originalScale;
+          }
+        }
+      });
+    } else {
+      self.menuIcons.forEach(cur => {
+        cur.scale = cur.originalScale;
+      });
+      document.body.style.cursor = 'auto';
+    }
 
-        // Check navigation icons
-        navigationIcons.func_onInputOver(x, y);
+    // Check navigation icons
+    navigationIcons.func_onInputOver(x, y);
 
-        game.render.all();
+    game.render.all();
 
-    },
+  },
 
 }

+ 37 - 39
js/preMenu.js

@@ -16,7 +16,7 @@ const bootState = {
     game.load.audio(url.boot.audio);
     game.load.image(url.boot.image);
     game.load.sprite(url.boot.sprite);
-    },
+  },
 
   /**
    * Main code
@@ -24,8 +24,8 @@ const bootState = {
   create: function () {
     // Calls first screen seen by the player
     game.state.start('lang');
-    }
-  };
+  }
+};
 
 
 /**
@@ -51,7 +51,7 @@ const langState = {
       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 in this.langs.flag) {
@@ -63,11 +63,11 @@ const langState = {
       flag.anchor(0.5, 0.5);
 
       this.listOfFlags.push(flag);
-      }
+    }
 
     game.event.add('click', this.func_onInputDown);
     game.event.add('mousemove', this.func_onInputOver);
-    },
+  },
 
 
   /* EVENT HANDLER*/
@@ -83,15 +83,15 @@ const langState = {
 
     self.listOfFlags.forEach(cur => {
       if (game.math.isOverIcon(x, y, cur)) {
-       for (let i in self.langs.flag) {
-         if (self.langs.flag[i] == cur.name) {
-           self.func_setLang(self.langs.lang[i]);
-           break;
-           }
-         }
-       }
-      });
-    },
+        for (let i in self.langs.flag) {
+          if (self.langs.flag[i] == cur.name) {
+            self.func_setLang(self.langs.lang[i]);
+            break;
+          }
+        }
+      }
+    });
+  },
 
   /**
    * Called by mouse move event
@@ -107,17 +107,16 @@ const langState = {
       if (game.math.isOverIcon(x, y, cur)) {
         flag = true;
         cur.scale = cur.scale = 1.05;
-        }
-      else {
-          cur.scale = cur.scale = 1;
-        }
-      });
+      } else {
+        cur.scale = cur.scale = 1;
+      }
+    });
 
     if (flag) document.body.style.cursor = 'pointer';
     else document.body.style.cursor = 'auto';
 
     game.render.all();
-    },
+  },
 
 
 
@@ -133,8 +132,8 @@ const langState = {
     langString = selectedLang;
     // Calls loading screen
     game.state.start('loadLang');
-    }
-  };
+  }
+};
 
 
 /**
@@ -150,7 +149,7 @@ const loadLangState = {
   preload: function () {
     // LOADING MEDIA : selected language
     game.load.lang('assets/lang/' + langString);
-    },
+  },
 
   /**
    * Main code
@@ -164,9 +163,9 @@ const loadLangState = {
       game.state.start('name'); // First time opening ifractions ('language' >> 'name' >> 'menu')
     } else {
       game.state.start('menu'); // If changing language during the game ('language' >> >> 'menu')         
-      }
     }
-  };
+  }
+};
 
 
 
@@ -206,13 +205,13 @@ const nameState = {
       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);
 
-    },
+  },
 
 
   /* EVENT HANDLER*/
@@ -230,10 +229,10 @@ const nameState = {
     if (game.math.isOverIcon(x, y, cur)) {
       if (self.func_checkEmptyName()) {
         self.func_saveName();
-        }
       }
+    }
     game.render.all();
-    },
+  },
 
   /**
    * Called by mouse move event
@@ -248,14 +247,13 @@ const nameState = {
     if (game.math.isOverIcon(x, y, cur)) {
       document.body.style.cursor = 'pointer';
       cur.alpha = 0.4;
-      }
-    else {
+    } else {
       document.body.style.cursor = 'auto';
       cur.alpha = 0.6;
-      }
+    }
 
     game.render.all();
-    },
+  },
 
 
   /* GAME FUNCTIONS */
@@ -270,9 +268,9 @@ const nameState = {
     if (document.getElementById('textbox-content').value == '') {
       self.warningEmptyName.name = game.lang.empty_name;
       return false;
-      }
+    }
     return true;
-    },
+  },
 
   /**
    * Saves player name and calls next state
@@ -290,6 +288,6 @@ const nameState = {
 
     // Calls 'menu' state
     game.state.start('menu');
-    }
+  }
 
-  };
+};

+ 77 - 88
js/squareOne.js

@@ -80,12 +80,11 @@ const squareOne = {
     if (sublevelType == 'Plus') {
       this.tractor.anchor(1, 0.5);
       this.tractor.animation = ['move', [0, 1, 2, 3, 4], 4];
-      }
-    else {
+    } else {
       this.tractor.anchor(0, 0.5);
       this.tractor.animation = ['move', [5, 6, 7, 8, 9], 4];
       this.tractor.curFrame = 5;
-      }
+    }
 
     // STACKED BLOCKS variables
     this.stck = {
@@ -100,7 +99,7 @@ const squareOne = {
 
       // Correct values
       correctIndex: undefined, // (levelType 'B') index of the CORRECT 'stacked' block
-      };
+    };
 
     // FLOOR BLOCKS variables
     this.floor = {
@@ -115,7 +114,7 @@ const squareOne = {
       correctX: undefined,  // 'x' coordinate of CORRECT 'floor' block
       correctXA: undefined, // Temporary variable 
       correctXB: undefined, // Temporary variable
-      };
+    };
 
     // CREATING STACKED BLOCKS
     this.restart = this.func_createStckBlocks();
@@ -129,7 +128,7 @@ const squareOne = {
       this.arrow = game.add.image(this.startX + this.defaultBlockWidth * this.DIREC_LEVEL, 480, 'arrow_down');
       this.arrow.anchor(0.5, 0.5);
       this.arrow.alpha = 0.5;
-      }
+    }
 
     // Help pointer
     this.help = game.add.image(0, 0, 'help_pointer', 0.5);
@@ -140,8 +139,8 @@ const squareOne = {
       game.timer.start(); // Set a timer for the current level (used in postScore())
       game.event.add('click', this.func_onInputDown);
       game.event.add('mousemove', this.func_onInputOver);
-      }
-    },
+    }
+  },
 
   /**
    * Game loop
@@ -162,7 +161,7 @@ const squareOne = {
       // Move 'stacked blocks'
       for (let i in stck.blocks) {
         stck.blocks[i].x += self.animationSpeed;
-        }
+      }
 
       // MANAGE BLOCKS AND FLOOR GAPS
       // If block is 1/n (not 1/1) there's an extra block space to go through before the start of next block
@@ -187,12 +186,11 @@ const squareOne = {
           // (B) selected stacked index doesnt fit last floor gap (fixed) AKA TOO MANY STACKED BLOCKS (DOESNT CHECK NOT ENOUGH)
           if ((sublevelType == 'Plus' && curEnd > selectedEnd) || (sublevelType == 'Minus' && curEnd < selectedEnd)) {
             lowerBlock = false;
-            }
           }
-        else {
+        } else {
           // Update to next block end
           stck.curBlockEnd += stck.blocks[stck.curIndex + 1].width * self.DIREC_LEVEL;
-          }
+        }
 
         // Fill floor gap
         if (lowerBlock) {
@@ -203,23 +201,23 @@ const squareOne = {
             if ((sublevelType == 'Plus' && floor.blocks[i].x < curEnd) || (sublevelType == 'Minus' && floor.blocks[i].x > curEnd)) {
               floor.blocks[i].alpha = 0.2;
               floor.curIndex = i;
-              }
             }
+          }
 
           // Lower
           stck.blocks[stck.curIndex].alpha = 0;
           stck.blocks.forEach(cur => { cur.y += self.defaultBlockHeight - 2; }); // Lower stacked blocks
-          }
+        }
 
         stck.curIndex++;
-        }
+      }
 
       // WHEN REACHED END POSITION
       if (stck.curIndex > stck.index || floor.curIndex == floor.index) {
         self.animate = false;
         self.checkAnswer = true;
-        }
       }
+    }
 
     // When animation ends check answer
     if (self.checkAnswer) {
@@ -229,10 +227,9 @@ const squareOne = {
 
       if (levelType == 'A') {
         self.result = self.floor.index == self.floor.correctIndex;
-        }
-      else {
+      } else {
         self.result = self.stck.index == self.stck.correctIndex;
-        }
+      }
 
       // Give feedback to player and turns on sprite animation
       if (self.result) { // Correct answer
@@ -244,19 +241,18 @@ const squareOne = {
 
         completedLevels++; // Increases number os passed levels
         if (debugMode) console.log('completedLevels = ' + completedLevels);
-        }
-      else { // Incorrect answer
+      } else { // Incorrect answer
         // Displays feedback image and sound
         game.add.image(defaultWidth / 2, defaultHeight / 2, 'error').anchor(0.5, 0.5);
         if (audioStatus) game.audio.errorSound.play();
-        }
+      }
 
       self.postScore();
 
       // AFTER CHECK ANSWER
       self.checkAnswer = false;
       self.animateEnding = true;
-      }
+    }
 
     // Starts 'ending' tractor moving animation
     if (self.animateEnding) {
@@ -274,10 +270,10 @@ const squareOne = {
         else mapMove = false;
 
         game.state.start('map');
-        }
       }
+    }
     game.render.all();
-    },
+  },
 
 
   /* EVENT HANDLER */
@@ -294,18 +290,17 @@ const squareOne = {
     if (levelType == 'A') {
       self.floor.blocks.forEach(cur => {
         if (game.math.isOverIcon(x, y, cur)) self.func_clickSquare(cur);
-        });
-      }
-    else {
+      });
+    } else {
       self.stck.blocks.forEach(cur => {
         if (game.math.isOverIcon(x, y, cur)) self.func_clickSquare(cur);
-        });
-      }
+      });
+    }
 
     navigationIcons.func_onInputDown(x, y);
 
     game.render.all();
-    },
+  },
 
   /**
    * Called by mouse move event
@@ -323,34 +318,34 @@ const squareOne = {
       if (!self.hasClicked && !self.animateEnding) {
         if (game.math.distanceToPointer(self.arrow.x, x, self.arrow.y, y) > 8) {
           self.arrow.x = (x < 250) ? 250 : x; // Limits the arrow left position to 250
-          }
         }
+      }
 
       self.floor.blocks.forEach(cur => {
         if (game.math.isOverIcon(x, y, cur)) {
           flagA = true;
           self.func_overSquare(cur);
-          }
-        });
+        }
+      });
 
       if (!flagA) self.func_outSquare('A');
-      }
+    }
 
     if (levelType == 'B') {
       self.stck.blocks.forEach(cur => {
         if (game.math.isOverIcon(x, y, cur)) {
           flagB = true;
           self.func_overSquare(cur);
-          }
-        });
+        }
+      });
 
       if (!flagB) self.func_outSquare('B');
-      }
+    }
 
     navigationIcons.func_onInputOver(x, y);
 
     game.render.all();
-    },
+  },
 
 
   /* CALLED BY EVENT HANDLER */
@@ -368,23 +363,22 @@ const squareOne = {
       if (levelType == 'A') {
         for (let i in self.floor.blocks) {
           self.floor.blocks[i].alpha = (i <= cur.index) ? 1 : 0.5;
-          }
+        }
 
         // Saves the index of the selected 'floor' block
         self.floor.index = cur.index;
 
         // On leveltype B
-        }
-      else {
+      } else {
         for (let i in self.stck.blocks) {
           self.stck.blocks[i].alpha = (i <= cur.index) ? 0.5 : 0.2;
-          }
+        }
 
         // Saves the index of the selected 'stack' block
         self.stck.index = cur.index;
-        }
       }
-    },
+    }
+  },
 
   /**
    * Function called when cursos is out of a valid rectangle
@@ -397,20 +391,19 @@ const squareOne = {
       if (levelType == 'A') {
         for (let i in self.floor.blocks) {
           self.floor.blocks[i].alpha = 0.5; // Back to normal
-          }
+        }
 
         self.floor.index = -1;
         // On level type B
-        }
-      else {
+      } else {
         for (let i in self.stck.blocks) {
           self.stck.blocks[i].alpha = 0.5; // Back to normal
-          }
+        }
 
         self.stck.index = -1;
-        }
       }
-    },
+    }
+  },
 
   /**
    * Function called when player clicks on a valid rectangle
@@ -428,24 +421,23 @@ const squareOne = {
         for (let i in self.floor.blocks) {
           // (SELECTION : self.FLOOR.index)
           if (i > self.floor.index) self.floor.blocks[i].alpha = 0; // Make unselected 'floor' blocks invisible
-          }
+        }
 
         // (FIXED : self.STCK.index) save the 'stacked' blocks index
         self.stck.index = self.stck.blocks.length - 1;
         // On leveltype B
-        }
-      else {
+      } else {
         for (let i in self.stck.blocks) {
           // (FIXED : self.STCK.index)
           if (i > self.stck.index) self.stck.blocks[i].alpha = 0; // Make unselected 'stacked' blocks invisible
-          }
+        }
 
         // (SELECTION : self.FLOOR.index) save the 'floor' blocks index to compare to the stacked index in update
         self.floor.index = self.floor.blocks.length - 1;
 
         // Save the updated total stacked blocks to compare in update
         self.stck.blocks.length = self.stck.index + 1;
-        }
+      }
 
       // Play beep sound
       if (audioStatus) game.audio.beepSound.play();
@@ -454,8 +446,8 @@ const squareOne = {
       if (fractionLabel) {
         self.stck.labels.forEach(cur => {
           cur.forEach(cur => { cur.alpha = 0; });
-          });
-        }
+        });
+      }
       // Hide solution pointer
       if (self.help != undefined) self.help.alpha = 0;
 
@@ -464,8 +456,8 @@ const squareOne = {
 
       self.hasClicked = true;
       self.animate = true;
-      }
-    },
+    }
+  },
 
 
   /* GAME FUNCTIONS */
@@ -511,7 +503,7 @@ const squareOne = {
       if (levelType == 'B') {
         block.alpha = 0.5;
         block.index = i;
-        }
+      }
 
       self.stck.blocks.push(block);
 
@@ -524,16 +516,15 @@ const squareOne = {
 
         if (divisor == 1) {
           label[0] = game.add.text(x, 488 - i * y, divisor, textStyles.h2_blue);
-          }
-        else {
+        } else {
           label[0] = game.add.text(x, 479 - i * y + 16, divisor, textStyles.p_blue);
           label[1] = game.add.text(x, 479 - i * y, '1', textStyles.p_blue);
           label[2] = game.add.text(x, 479 - i * y, '_', textStyles.p_blue);
-          }
+        }
         // Add current label to group of labels
         self.stck.labels.push(label);
-        }
       }
+    }
 
     // Will be used as a counter in update, adding in the width of each stacked block to check if the end matches the floor selected position
     self.stck.curBlockEnd = self.startX + self.stck.blocks[0].width * self.DIREC_LEVEL;
@@ -548,12 +539,12 @@ const squareOne = {
         self.floor.correctXA > (self.startX - self.defaultBlockWidth)))
     ) {
       restart = true; // If any error is found restart the level
-      }
+    }
 
     if (debugMode) console.log('Stacked blocks: ' + total + ' (min: ' + (mapPosition + 2) + ', max: ' + max + ')');
 
     return restart;
-    },
+  },
 
   /**
    * Create floor blocks for the level (called in create())
@@ -573,8 +564,8 @@ const squareOne = {
 
       for (let i = 0; i <= self.stck.correctIndex; i++) {
         self.floor.correctXB += self.stck.blocks[i].width * self.DIREC_LEVEL; // Equivalent x position on the floor
-        }
       }
+    }
 
     let flag = true;
 
@@ -583,18 +574,18 @@ const squareOne = {
       const x = self.startX + (self.defaultBlockWidth + i * blockWidth) * self.DIREC_LEVEL;
 
       if (flag && levelType == 'A') {
-        if ( (sublevelType == 'Plus' && x >= self.floor.correctXA) || (sublevelType == 'Minus' && x <= self.floor.correctXA) ) {
+        if ((sublevelType == 'Plus' && x >= self.floor.correctXA) || (sublevelType == 'Minus' && x <= self.floor.correctXA)) {
           self.floor.correctIndex = i - 1; // Set index of correct floor block
           flag = false;
-          }
         }
+      }
 
       if (levelType == 'B') {
-        if ( (sublevelType == 'Plus' && x >= self.floor.correctXB) || (sublevelType == 'Minus' && x <= self.floor.correctXB) ) {
+        if ((sublevelType == 'Plus' && x >= self.floor.correctXB) || (sublevelType == 'Minus' && x <= self.floor.correctXB)) {
           total = i;
           break;
-          }
         }
+      }
 
       // Create floor block
       const lineSize = 0.9;
@@ -614,11 +605,11 @@ const squareOne = {
       if (levelType == 'A') {
         block.alpha = 0.5;
         block.index = i;
-        }
+      }
 
       // Add current label to group of labels
       self.floor.blocks.push(block);
-      }
+    }
 
     if (levelType == 'A') self.floor.correctX = self.floor.correctXA;
     else if (levelType == 'B') self.floor.correctX = self.floor.correctXB;
@@ -627,8 +618,8 @@ const squareOne = {
     for (let i = 1; i < 10; i++) {
       const x = self.startX + (i * self.defaultBlockWidth * self.DIREC_LEVEL);
       game.add.text(x, 462 + self.defaultBlockHeight + 58, i - 1, textStyles.h2_blue);
-      }
-    },
+    }
+  },
 
   /**
    * Display correct answer
@@ -641,29 +632,28 @@ const squareOne = {
         self.help.x = self.floor.correctX - aux.width / 2 * self.DIREC_LEVEL;
         self.help.y = 501;
         // On levelType B
-        }
-      else {
+      } else {
         const aux = self.stck.blocks[self.stck.correctIndex];
         self.help.x = aux.x + aux.width / 2 * self.DIREC_LEVEL;
         self.help.y = aux.y;
-        }
+      }
 
       self.help.alpha = 0.7;
-      }
-    },
+    }
+  },
 
 
 
   /* METADATA FOR GAME */
 
   /**
-   * Saves players data after level
+   * Saves players data after level ends - to be sent to database
    *
    * Attention: the "line_" prefix data table must be compatible to data table fields (MySQL server)
-   * @see ./php/save.php
+   * @see /php/save.php
    */
   postScore: function () {
-    // Saves player data to send to the database
+    // Creates string that is going to be sent to db
     const data = '&line_game=' + gameShape
       + '&line_mode=' + levelType
       + '&line_oper=' + sublevelType
@@ -676,8 +666,7 @@ const squareOne = {
       + ', valBlocks: ' + self.divisorsList // Ends in ','
       + ' blockIndex: ' + self.stck.index
       + ', floorIndex: ' + self.floor.index;
+    sendToDB(data);
+  },
 
-    postScore(data);
-    },
-
-  };
+};

+ 41 - 45
js/squareTwo.js

@@ -49,7 +49,7 @@ const squareTwo = {
       animate: false,     // Animate blocks from A
       warningText: undefined,
       label: undefined,
-      };
+    };
 
     this.B = {
       blocks: [],
@@ -60,7 +60,7 @@ const squareTwo = {
       animate: false,
       warningText: undefined,
       label: undefined,
-      };
+    };
 
     // BACKGROUND AND KID
     // Add background image
@@ -94,13 +94,12 @@ const squareTwo = {
       yA = 90;
       xB = xA;
       yB = yA + 3 * figureHeight + 30;
-      }
-    else { // More subdivisions on A
+    } else { // More subdivisions on A
       xB = 230;
       yB = 90;
       xA = xB;
       yA = yB + 3 * figureHeight + 30;
-      }
+    }
 
     // Possible points for A
     const points = [2, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20];
@@ -117,7 +116,7 @@ const squareTwo = {
       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 / totalBlocksA; // Width of each block in A
@@ -140,7 +139,7 @@ const squareTwo = {
       const yAux = yA + figureHeight + 10; // On the bottom of A
       const auxBlock = game.add.graphic.rect(x, yAux, blockWidth, figureHeight, lineColor, 1, fillColor, alpha);
       this.A.auxBlocks.push(auxBlock);
-      }
+    }
 
     // 'total blocks' label for A : on the side of A
     let xLabel = xA + this.figureWidth + 30;
@@ -179,7 +178,7 @@ const squareTwo = {
       const yAux = yB + figureHeight + 10; // On the bottom of B
       const auxBlock = game.add.graphic.rect(x, yAux, blockWidth, figureHeight, lineColor, 1, fillColor, alpha);
       this.B.auxBlocks.push(auxBlock);
-      }
+    }
 
     // Label block B
     xLabel = xB + this.figureWidth + 30;
@@ -205,7 +204,7 @@ const squareTwo = {
 
     game.event.add('click', this.func_onInputDown);
     game.event.add('mousemove', this.func_onInputOver);
-    },
+  },
 
   /**
    * Game loop
@@ -218,16 +217,16 @@ const squareTwo = {
           // Lower selected blocks
           for (let i = 0; i < self[cur].selected; i++) {
             self[cur].blocks[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;
-            }
           }
-        });
-      }
+        }
+      });
+    }
 
     // If A and B are already clicked
     if (self.A.hasClicked && self.B.hasClicked && !self.endLevel) {
@@ -249,20 +248,19 @@ const squareTwo = {
           if (debugMode) console.log('completedLevels = ' + completedLevels);
 
           // Fractions are not equivalent : INCORRECT
-          }
-        else {
+        } else {
           if (audioStatus) game.audio.errorSound.play();
           game.add.image(defaultWidth / 2, defaultHeight / 2, 'error').anchor(0.5, 0.5);
           mapMove = false; // Doesnt allow character to move to next level in map state
-          }
+        }
 
         self.postScore();
         self.endLevel = true;
 
         // Reset delay values for next delay
         self.delay = 0;
-        }
       }
+    }
 
     // Wait a bit and go to map state
     if (self.endLevel) {
@@ -270,11 +268,11 @@ const squareTwo = {
 
       if (self.delay >= 80) {
         game.state.start('map');
-        }
       }
+    }
 
     game.render.all();
-    },
+  },
 
 
   /* EVENT HANDLER */
@@ -291,18 +289,18 @@ const squareTwo = {
     // Click block in A
     self.A.blocks.forEach(cur => {
       if (game.math.isOverIcon(x, y, cur)) self.func_clickSquare(cur);
-      });
+    });
 
     // Click block in B
     self.B.blocks.forEach(cur => {
       if (game.math.isOverIcon(x, y, cur)) self.func_clickSquare(cur);
-      });
+    });
 
     // Click navigation icons
     navigationIcons.func_onInputDown(x, y);
 
     game.render.all();
-    },
+  },
 
   /**
    * Called by mouse move event
@@ -320,8 +318,8 @@ const squareTwo = {
       if (game.math.isOverIcon(x, y, cur)) {
         flagA = true;
         self.func_overSquare(cur);
-        }
-      });
+      }
+    });
     if (!flagA) self.func_outSquare('A');
 
     // Mouse over B : show fraction
@@ -329,8 +327,8 @@ const squareTwo = {
       if (game.math.isOverIcon(x, y, cur)) {
         flagB = true;
         self.func_overSquare(cur);
-        }
-      });
+      }
+    });
     if (!flagB) self.func_outSquare('B');
 
     if (!flagA && !flagB) document.body.style.cursor = 'auto';
@@ -339,7 +337,7 @@ const squareTwo = {
     navigationIcons.func_onInputOver(x, y);
 
     game.render.all();
-    },
+  },
 
 
   /* CALLED BY EVENT HANDLER */
@@ -361,8 +359,7 @@ const squareTwo = {
         self[otherSet].warningText.name = '';
 
         self.func_outSquare(curSet);
-        }
-      else {
+      } else {
         document.body.style.cursor = 'pointer';
 
         self.A.warningText.name = '';
@@ -371,7 +368,7 @@ const squareTwo = {
         // 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
@@ -382,9 +379,9 @@ const squareTwo = {
         self[curSet].fractions[2].x = newX;
 
         self[curSet].fractions[0].alpha = 1;
-        }
       }
-    },
+    }
+  },
 
   /**
    * Function called when cursor is out of a valid rectangle
@@ -399,9 +396,9 @@ const squareTwo = {
 
       self[curSet].blocks.forEach(cur => {
         cur.alpha = 0.5;
-        });
-      }
-    },
+      });
+    }
+  },
 
   /**
    * Function called when player clicked a valid rectangle
@@ -417,7 +414,7 @@ const squareTwo = {
       // Turn auxiliar blocks invisible
       for (let i in self[curSet].blocks) {
         if (i > curBlock.index) self[curSet].auxBlocks[i].alpha = 0;
-        }
+      }
 
       // Turn value label invisible
       self[curSet].label.alpha = 0;
@@ -438,22 +435,22 @@ const squareTwo = {
 
       self[curSet].hasClicked = true; // Inform player have clicked in current block set
       self[curSet].animate = true; // Let it initiate animation
-      }
+    }
 
     game.render.all();
-    },
+  },
 
 
   /* METADATA FOR GAME */
 
   /**
-   * Saves players data after level
+   * Saves players data after level ends - to be sent to database
    *
    * Attention: the "line_" prefix data table must be compatible to data table fields (MySQL server)
-   * @see ./php/save.php
+   * @see /php/save.php
    */
   postScore: function () {
-    // Saves player data to send to the database
+    // Creates string that is going to be sent to db
     const data = '&line_game=' + gameShape
       + '&line_mode=' + levelType
       + '&line_oper=Equal'
@@ -466,8 +463,7 @@ const squareTwo = {
       + ', valueA: ' + self.A.selected
       + ', numBlocksB: ' + self.B.blocks.length
       + ', valueB: ' + self.B.selected;
+    sendToDB(data);
+  }
 
-    postScore(data);
-    }
-
-  };
+};

+ 16 - 16
php/README.md

@@ -1,18 +1,18 @@
 #  save.php
 
-iFractions is developed to run mainly on the client side. However, it communicates with a database using MySQL to save the player information after each level. The file **save.php** manages the connection between the game and the database.
+iFractions is developed to run mainly on the client side. However, it communicates with a MySQL database to save info about the player's progress after each level. There's a PHP file called **save.php** that manages the connection between the game and the database. Also, the asynchronous communication is stablished using **XMLHTTPRequest**.
 
 # How to set up the database connection correctly
 
-In order for iFractions to successfully establish a connection to the database you must:
+First you'll need a MySQL database installed on the server (more info in https://www.mysql.com).
 
-1. set up a MySQL database.
+Now, in order for iFractions to successfully establish a connection to the database you must:
+
+1. create and set up the database for the game.
 2. update /php/save.php 
 3. update /js/globals.js
 
-## 1) Creating the MySQL database for iFractions
-
-You must have MySQL installed on the server. 
+## 1) Creating the database for iFractions
 
 Considering the database name to be **db_ifractins** and the table to be **ifractions**, you can setup the MySQL database as follows:
 
@@ -37,11 +37,13 @@ Considering the database name to be **db_ifractins** and the table to be **ifrac
 		PRIMARY KEY (line_id)
 	) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = latin1;
 
+Note that each column has the prefix **line_**.
+
 ## 2) /php/save.php
 
 You have to set values for the following variables in **/php/save.php** to match the database's:
 
-	$servername = "localhost"; 	// INSERT MYSQL server name
+	$servername = "localhost"; 	// INSERT MySQL server
 	$username = "put_username";	// INSERT MySQL user name
 	$password = "put_password";	// INSERT MySQL password
 	$dbname = "db_ifractions";	// INSERT database name (default=db_ifractions) 
@@ -49,7 +51,7 @@ You have to set values for the following variables in **/php/save.php** to match
 
 ## 3) /js/globals.js
 
-There is a global function **postScore()** inside /js/globals.js. When the information is collected on the current game file, it is sent as a parameter to this function. Here is where all the information collecting is completed, the data is sent to /php/save.php and the connection to the database done.
+Inside **/js/globals.js** there's a global function called **sendToDB()**. When the player's information is collected after each game, the game file sends it as a parameter to **sendToDB()**. It makes an asynchronous call to **/php/save.php**, that executes the connection to the database.
 
 	const data = 'line_ip='// INSERT the IP of the machine where the MySQL was set up
 		+ '&line_name=' + //player's name
@@ -59,12 +61,12 @@ There is a global function **postScore()** inside /js/globals.js. When the infor
 
 # Where do we use the database in the code?
 
-There is also a function **postScore()** in every game file:
-* /js/gameSquareOne.js
-* /js/gameSquareTwo.js
-* /js/gameCircleOne.js
+There is a function **postScore()** in every game file:
+* /js/squareOne.js
+* /js/squareTwo.js
+* /js/circleOne.js
 
-After each level is completed, information about the player's progress is sent do the database through the function **postScore()**. The data collected in the game is structured as a string that is going to be sent to the database (as can be seen below).
+After each level is completed (with the player's answer being correct or not), before going back to the level map, the function **postScore()**, is called. It joins all the player's progress information into a string (as can be seen below), that is sent as a parameter to **sendToDB()**, from **/js/globals.js**, that sends it to the database.
 
 	const data = '&line_game=' + // collect game shape
 	+ '&line_mode=' + // collect level type
@@ -73,6 +75,4 @@ After each level is completed, information about the player's progress is sent d
 	+ '&line_posi=' + // collect the players position on the map
 	+ '&line_resu=' + // collect status for players answer (correct or incorrect)
 	+ '&line_time=' + // collect time spent finishing the game
-	+ '&line_deta=' + // collect extra details specific to current game
-
-The variable **data** is then sent as a parameter to the global function **postScore()** in **/js/globals.js**, that completes the string and sends the information to the database using /php/save.php.
+	+ '&line_deta=' + // collect extra details specific to current game

+ 7 - 8
php/save.php

@@ -11,7 +11,7 @@
 // @see js/squareTwo.js
 
 // Change these values according to your database settings
-$servername = "localhost";  // INSERT MySQL name (e.g "line.ime.usp.br")
+$servername = "localhost";  // INSERT MySQL server (e.g "line.ime.usp.br")
 $username = "put_username"; // INSERT MySQL user name
 $password = "put_password"; // INSERT MySQL password
 $dbname = "db_ifractions";  // INSERT database name (default="db_ifractions")
@@ -21,7 +21,7 @@ $tablename = "ifractions";  // INSERT table name (default="ifractions")
 function remove_accents ($stripAccents) {
   // $stripAccents = preg_replace('/[^\x20-\x7E]/','', $stripAccents); // remove all special characters - if necessary, uncomment it
   return $stripAccents;
-  }
+}
 
 // Get some information about the client IP
 function clientIP () {
@@ -35,9 +35,9 @@ function clientIP () {
   $resp = gethostbyaddr($ip);
   if (isset($resp) && strlen($resp)>0) {
     $strIP .= "; " . $resp;
-    }
-  return $strIP;
   }
+  return $strIP;
+}
 
 // Create connection
 $conn = new mysqli($servername, $username, $password, $dbname);
@@ -45,7 +45,7 @@ $conn = new mysqli($servername, $username, $password, $dbname);
 // Check connection
 if ($conn->connect_error) {
   die("Connection failed: " . $conn->connect_error);
-  }
+}
 
 $ip = clientIP();
 
@@ -80,11 +80,10 @@ VALUES
 if ($conn->query($sql) === TRUE) {
   print "Saved.";
   $result = "OK";
-  }
-else {
+  } else {
   print "Error: " . $sql . "<br>" . $conn->error;
   $result = "Error: " . $conn->error;
-  }
+}
 
 // DEBUG
 $date = date('Y_m_d_H_i_s');