Browse Source

📝 Add documentation to Tween, GameObject, GameHandler and AssetHandler (4/30)

- Also fix some bugs, typos and order of the methods on some of these files.
Pedro Schneider 3 years ago
parent
commit
c47ba7a59b

+ 179 - 11
pandora/game_objects/GameObject.js

@@ -19,32 +19,66 @@
  * along with Pandora.  If not, see <https://www.gnu.org/licenses/>.
  *************************************************************************/
 
+/**
+ * The {@code GameObject} class represents a minimal structure for any object in the
+ * game. All objects added to the tree, either as a root or a child of an object
+ * on the tree must be or inherit from GameObject.
+ * 
+ * ! All GameObjects need to be inside the tree to do anything (can be added as a child
+ * ! of another GameObject on the tree or as a root).
+ * 
+ * @author Pedro Schneider
+ * 
+ * @class
+ */
 class GameObject
 {
+    /**
+     * @constructor
+     * Creates an empty GameObject, with default properties.
+     * 
+     * @param {String} name name of the new GameObject.
+     */
     constructor(name)
     {
-        this.id = 0;
+        this.id = 0; // Global unique indentifier for the object.
 
-        this.name = name;
+        this.name = name; // Set the name for the object.
 
-        this.children = [];
-        this.parented = false;
-        this.parent = null;
-        this.isOnTree = false;
-        this.isRoot = false;
+        this.children = []; // List of children.
+        this.parented = false; // Does this GameObject have a parent?
+        this.parent = null; // Who is the parent? null if orphan.
+        this.isOnTree = false; // Is this GameObject on the tree?
+        this.isRoot = false; // Is this GameObject a root object?
 
-        this.signals = [];
+        this.signals = []; // List of signals.
         this.initSignals();
 
         GameHandler.instanceGameObject(this);
     }
 
-    // Getters
+    /**
+     * Returns the list of children of this GameObject.
+     * @returns Array containing a reference to all of this GameObject's
+     *          children.
+     */
     getChildren()
     {
         return this.children;
     }
 
+    /**
+     * Query for a child of this GameObject with the child's index.
+     * 
+     * ! The index refers to the order you added the children to this
+     * ! GameObject, starting at 0.
+     * 
+     * @param {String} idx  index of the desired child on the GameObject's
+     *                      children list.
+     * 
+     * @returns a reference to the child with the given index, or null if
+     *          no child has that index. 
+     */
     getChildByIndex(idx)
     {
         if (idx >= 0 && idx < this.children.length)
@@ -52,6 +86,15 @@ class GameObject
         return null;
     }
 
+    /**
+     * Query for a child of this GameObject with the child's id.
+     * 
+     * @param {String} id  id of the desired child on the GameObject's
+     *                      children list.
+     * 
+     * @returns a reference to the child with the given id, or null if
+     *          no child has that id. 
+     */
     getChildById(id)
     {
         for (let i = 0; i < this.children.length; i++)
@@ -62,6 +105,14 @@ class GameObject
         return null;
     }
 
+    /**
+     * Query for a child of this GameObject with the child's name.
+     * 
+     * @param {String} name name of the desired child.
+     *  
+     * @returns a reference to the child with the given name, or null
+     *          if no child has that name. 
+     */
     getChildByName(name)
     {
         for (let i = 0; i < this.children.length; i++)
@@ -69,18 +120,37 @@ class GameObject
         return null;
     }
 
+    /**
+     * Get a reference to this GameObject's parent.
+     * 
+     * @returns a reference to this GameObject's parent if it exists, null
+     *          if it doesn't.
+     */
     getParent()
     {
         if (!this.parented) return null;
         return this.parent;
     }
 
-    // Methods
+    /**
+     * Add a new signal to this GameObject.
+     * 
+     * @param {String} name name for the new signal. 
+     */
     addSignal(name)
     {
         this.signals.push(new Signal(name));
     }
 
+    /**
+     * Connect another GameObject to one of this GameObject's signals.
+     *  
+     * @param {String} signalName   name of the signal to be connected. 
+     * @param {GameObject} target   reference to the GameObject that wants
+     *                              to be connected to this signal.
+     * @param {String} callback     name of the method to be called every
+     *                              time this signal is emited. 
+     */
     connect(signalName, target, callback)
     {
         for (let i = 0; i < this.signals.length; i++)
@@ -94,6 +164,13 @@ class GameObject
         }
     }
 
+    /**
+     * Emits one of this GameObject's signals.
+     * 
+     * @param {String} signalName   name of the signal to be emited. 
+     * @param  {...any} params      parameters the connected callbacks
+     *                              should receive.
+     */
     emitSignal(signalName, ...params)
     {
         for (let i = 0; i < this.signals.length; i++)
@@ -107,6 +184,12 @@ class GameObject
         }
     }
 
+    /**
+     * Add the GameObject as a child of this GameObject.
+     * 
+     * @param {GameObject} child    reference to the GameObject to be
+     *                              added as a child. 
+     */
     addChild(child)
     {
         child.parent = this;
@@ -116,12 +199,31 @@ class GameObject
         if (this.isOnTree) child.setup();
     }
 
+    /**
+     * Remove a child of this GameObject by its index. This action does not
+     * delete the child GameObject; if this is the functionality you want, 
+     * freeing a game object from memory automatically removes it from its
+     * parent.
+     * 
+     * ! The index refers to the order you added the children to this
+     * ! GameObject, starting at 0.
+     * 
+     * @param {number} idx  index of the child to be removed.
+     */
     removeChildByIndex(idx)
     {
         if (idx >= 0 && idx < this.children.length)
             this.children.splice(idx, 1);
     }
 
+    /**
+     * Remove a child of this GameObject by its id. This action does not
+     * delete the child GameObject; if this is the functionality you want, 
+     * freeing a game object from memory automatically removes it from its
+     * parent.
+     * 
+     * @param {number} id   id of the child to be removed.
+     */
     removeChildById(id)
     {
         for (let i = 0; i < this.children.length; i++)
@@ -134,6 +236,14 @@ class GameObject
         }
     }
 
+    /**
+     * Remove a child of this GameObject by its name. This action does not
+     * delete the child GameObject; if this is the functionality you want, 
+     * freeing a game object from memory automatically removes it from its
+     * parent.
+     * 
+     * @param {String} name name of the child to be removed.
+     */
     removeChildByName(name)
     {
         for (let i = 0; i < this.children.length; i++)
@@ -146,6 +256,11 @@ class GameObject
         }
     }
 
+    /**
+     * De-parents the GameObject from its parent, or removes it from the root of the
+     * tree if orphan, and recursively marks this GameObject's and all of its children's
+     * memory for garbage collection.
+     */
     free()
     {
         if (this.parented)
@@ -156,6 +271,10 @@ class GameObject
         this.destroy();
     }
 
+    /**
+     * Recursively marks this GameObject's and all of its children's
+     * memory for garbage collection.
+     */
     destroy()
     {
         for (let i = 0; i < this.children.length; i++)
@@ -165,11 +284,18 @@ class GameObject
             this[prop] = null;
     }
 
+    /**
+     * Caller for the _initSignals() callback
+     */
     initSignals()
     {
         this._initSignals();
     }
 
+    /**
+     * Caller for the _setup() callback. Recursively calls itself for all
+     * of this GameObject's children.
+     */
     setup()
     {
         this.isOnTree = true;
@@ -180,6 +306,12 @@ class GameObject
         }
     }
 
+    /**
+     * Caller for the _update(delta) callback. Recrusively calls itself for
+     * all of this GameOject's children.
+     * 
+     * @param {number} delta    ellapsed seconds since the last frame. 
+     */
     update(delta)
     {
         this._update(delta);
@@ -187,6 +319,13 @@ class GameObject
             this.children[i].update(delta);
     }
 
+    /**
+     * Caller for the _draw(delta, db) callback. Recursively calls itself for
+     * all of this GameObject's children.
+     * 
+     * @param {number} delta    ellapsed seconds since the last frame. 
+     * @param {p5.Graphics} db  secondary buffer to draw on. 
+     */
     draw(delta, db)
     {
         this._draw(delta, db);
@@ -194,22 +333,51 @@ class GameObject
             this.children[i].draw(delta, db);
     }
 
-    // Callbacks
+    /**
+     * @callback
+     * ! This function should be overriden, it provides no default functionality.
+     * This function is called once when the GameObject is created and should declare
+     * any and all signals the user wants for the GameObject.
+     */
     _initSignals()
     {
 
     }
 
+    /**
+     * @callback
+     * ! This function should be overriden, it provides no default functionality.
+     * This function is called once when the GameObject is added to the tree (as a child
+     * of another GameObject or as a root).
+     */
     _setup()
     {
 
     }
 
+    /**
+     * @callback
+     * ! This function should be overriden, it provides no default functionality.
+     * This function is called once at the start of every frame and should be used for
+     * any logic that doesn't have anything to do with drawing graphics to the screen buffer.
+     * 
+     * @param {number} delta    ellapsed seconds since the last frame. 
+     */
     _update(delta)
     {
 
     }
 
+    /**
+     * @callback
+     * ! This function should be overriden, it provides no default functionality.
+     * This function is called once at the start of every frame after all update() calls
+     * have been completed and should be used for any logic that results in something
+     * beeing drawn to the screen buffer.
+     * 
+     * @param {number} delta    ellapsed seconds since the last frame. 
+     * @param {p5.Graphics} db  secondary buffer to draw on. 
+     */
     _draw(delta, db)
     {
 

+ 195 - 18
pandora/game_objects/Tween.js

@@ -19,13 +19,40 @@
  * along with Pandora.  If not, see <https://www.gnu.org/licenses/>.
  *************************************************************************/
 
+/**'
+ * The {@code TweenData} class represents the data that a Tween GameObject needs to
+ * interpolate a given property.
+ * 
+ * @author Pedro Schneider
+ * 
+ * @class
+ */
 class TweenData
 {
+    /**
+     * @constructor
+     * Creates a TweenData Object with the specified parameters.
+     * 
+     * @param {Object} target                   Object that has the property to be interpolated.
+     * @param {String} property                 name of the property of target to be interpolated.
+     *                                          target[property] should be number, Vector2 or Color. 
+     * @param {PROPERTY_TYPE} propertyType      type of the property to be interpolated. 
+     * @param {number, Vector2, Color} initVal  initial value for the interpolation.
+     *                                          Should be the same type as target[property].
+     * @param {number, Vector2, Color} finalVal final value for the interpolation.
+     *                                          Should be the same type as target[property].
+     * @param {number} duration                 duration in seconds of the interpolation. 
+     * @param {TRANS_TYPE} transType            transition type of the interpolation. 
+     * @param {EASE_TYPE} easeType              easing type of the interpolation.
+     * @param {number} delay                    delay in seconds for the interpolation to start. 
+     */
     constructor(target, property, propertyType, initVal, finalVal, duration, transType, easeType, delay)
     {
-        this.target = target;
-        this.property = property;
-        this.propertyType = propertyType;
+        this.target = target; // Object that has the property to be interpolated.
+        this.property = property; // Name of the property to be interpolated.
+        this.propertyType = propertyType; // Type of the property to be interpolated.
+
+        // Initializes new objects for final value and initial value depending on the type.
         switch (this.propertyType)
         {
             case PROPERTY_TYPE.COLOR:
@@ -41,15 +68,16 @@ class TweenData
                 this.finalVal = finalVal;
                 break;
         }
-        this.duration = duration;
-        this.transType = transType;
-        this.easeType = easeType;
 
-        this.t = -delay;
-        this.playing = false;
-        this.done = false;
+        this.duration = duration; // Duration in seconds of the interpolation
+        this.transType = transType; // Type of the transition.
+        this.easeType = easeType; // Type of the easing.
 
-        this.p = [];
+        this.t = -delay; // Current time of the interpolation.
+        this.playing = false; // Is the interpolation playing?
+        this.done = false; // Is the interpolation done?
+
+        this.p = []; // List of sub-properties to be interpolated depending on the type.
         switch (this.propertyType)
         {
             case PROPERTY_TYPE.COLOR:
@@ -65,7 +93,7 @@ class TweenData
                 break;
         }
 
-        this.trans = "";
+        this.trans = ""; // String for the transition type.
         switch (this.transType)
         {
             case TRANS_TYPE.LINEAR:
@@ -103,7 +131,7 @@ class TweenData
                 break;
         }
 
-        this.ease = "";
+        this.ease = ""; // String for the easing type.
         if (this.transType == TRANS_TYPE.LINEAR) this.ease = "ease";
         else
         {
@@ -123,8 +151,23 @@ class TweenData
     }
 }
 
+/**
+ * The {@code Tween} class represents a Tween GameObject that has functionality to
+ * interpolate any property of another GameObject if the properties are of the type
+ * number, Vector2 or Color.
+ * 
+ * @author Pedro Schneider
+ * 
+ * @class
+ */
 class Tween extends GameObject
 {
+    /**
+     * @constructor
+     * Creates an empty Tween GameObject.
+     * 
+     * @param {String} name name of the Tween GameObject. 
+     */
     constructor(name)
     {
         super(name);
@@ -134,12 +177,40 @@ class Tween extends GameObject
         this.done = false;
     }
 
+    /**
+     * Add a new TweenData Object to this Tween with the necessary information to interpolate
+     * the target's property.
+     * 
+     * @param {Object} target                   Object that has the property to be interpolated.
+     * @param {String} property                 name of the property of target to be interpolated.
+     *                                          target[property] should be number, Vector2 or Color. 
+     * @param {PROPERTY_TYPE} propertyType      type of the property to be interpolated. 
+     * @param {number, Vector2, Color} initVal  initial value for the interpolation.
+     *                                          Should be the same type as target[property].
+     * @param {number, Vector2, Color} finalVal final value for the interpolation.
+     *                                          Should be the same type as target[property].
+     * @param {number} duration                 duration in seconds of the interpolation. 
+     * @param {TRANS_TYPE} transType            transition type of the interpolation.
+     *                                          Default is TRANS_TYPE.LINEAR.
+     * @param {EASE_TYPE} easeType              easing type of the interpolation.
+     *                                          Default is EASY_TYPE.IN_OUT.
+     * @param {number} delay                    delay in seconds for the interpolation to start.
+     *                                          Default is 0. 
+     */
     interpolateProperty(target, property, propertyType, initVal, finalVal, duration, transType = 1, easeType = 3, delay = 0)
     {
-        this.done = false;
+        this.done = false; // Are all TweenData on this Tween done?
+
+        // Adding a new TweenData.
         this.tweenData.push(new TweenData(target, property, propertyType, initVal, finalVal, duration, transType, easeType, delay));
     }
 
+    /**
+     * Given a TweenData, sets its interpolation's target's property to the appropriate value for
+     * the current time of the interpolation.
+     * 
+     * @param {TweenData} td    reference to the TweenData Object. 
+     */
     interpolate(td)
     {
         if (td.propertyType == PROPERTY_TYPE.NUMBER)
@@ -151,42 +222,81 @@ class Tween extends GameObject
         }
     }
 
-    start()
+    /**
+     * Starts interpolating all TweenData Objectcs currently added to this Tween.
+     */
+    startAll()
     {
         for (let i = 0; i < this.tweenData.length; i++)
             this.tweenData[i].playing = true;
     }
 
+    /**
+     * Starts interpolating a specific TweenData Object based on its index.
+     * 
+     * ! Since TwennData are not GameObjects, this is the only way to query
+     * ! for them. The index refera to the order you added the TweenData to
+     * ! this Tween, starting at 0.
+     * 
+     * @param {number} idx  index of the desired TweenData to start.
+     */
     startByIndex(idx)
     {
         if (idx < 0 && idx >= this.tweenData.length) return;
         this.tweenData[idx].playing = true;
     }
 
+    /**
+     * Stops interpolating all TweenData Objects currently added to this Tween.
+     */
     stopAll()
     {
         for (let i = 0; i < this.tweenData.length; i++)
             this.tweenData[i].playing = false;
     }
 
+    /**
+     * Stops interpolating a specific TweenData Object based on its index.
+     * 
+     * ! Since TwennData are not GameObjects, this is the only way to query
+     * ! for them. The index refera to the order you added the TweenData to
+     * ! this Tween, starting at 0.
+     * 
+     * @param {number} idx  index of the desired TweenData to stop.
+     */
     stopByIndex(idx)
     {
         if (idx < 0 && idx >= this.tweenData.length) return;
         this.tweenData[idx].playing = false;
     }
 
+    /**
+     * Resumes interpolating all TweenData currently added to this Tween.
+     */
     resumeAll()
     {
         for (let i = 0; i < this.tweenData.length; i++)
             this.tweenData[i].playing = true;
     }
 
+    /**
+     * Resumes interpolating a specific TweenData Object based on its index.
+     * 
+     * ! Since TwennData are not GameObjects, this is the only way to query
+     * ! for them. The index refera to the order you added the TweenData to
+     * ! this Tween, starting at 0.
+     * 
+     * @param {number} idx  index of the desired TweenData to resume.
+     */
     resumeByIndex(idx)
     {
         if (idx < 0 && idx >= this.tweenData.length) return;
         this.tweenData[idx].playing = true;
     }
 
+    /**
+     * Resets all TweenData currently added to this Tween.
+     */
     resetAll()
     {
         this.doneTweens = 0;
@@ -198,6 +308,15 @@ class Tween extends GameObject
         }
     }
 
+    /**
+     * Resets a specific TweenData Object based on its index.
+     * 
+     * ! Since TwennData are not GameObjects, this is the only way to query
+     * ! for them. The index refera to the order you added the TweenData to
+     * ! this Tween, starting at 0.
+     * 
+     * @param {number} idx  index of the desired TweenData to reset.
+     */
     resetByIndex(idx)
     {
         if (idx < 0 && idx >= this.tweenData.length) return;
@@ -207,18 +326,36 @@ class Tween extends GameObject
         this.tweenData[idx].done = false;
     }
 
+    /**
+     * Removes all TweenData currently added to this Tween.
+     */
     removeAll()
     {
         while (this.tweenData.length > 0)
             this.tweenData.pop();
     }
 
+    /**
+     * Removes a specific TweenData Object based on its index.
+     * 
+     * ! Since TwennData are not GameObjects, this is the only way to query
+     * ! for them. The index refera to the order you added the TweenData to
+     * ! this Tween, starting at 0.
+     * 
+     * @param {number} idx  index of the desired TweenData to remove.
+     */
     removeByIndex(idx)
     {
         if (idx < 0 && idx >= this.tweenData.length) return;
         this.tweenData.splice(idx, 1);
     }
 
+    /**
+     * Sets the current time of all TweenData currently added to this Tween
+     * to the specified time.
+     * 
+     * @param {number} time time in seconds to seek all TweenData on this Tween. 
+     */
     seekAll(time)
     {
         if (time < 0) return;
@@ -226,18 +363,47 @@ class Tween extends GameObject
             this.tweenData[i].t = min(time, this.tweenData[i].duration);
     }
 
+    /**
+     * Sets the current time of a specific TweenData Object, based on its index,
+     * to the specified time. 
+     * 
+     * ! Since TwennData are not GameObjects, this is the only way to query
+     * ! for them. The index refera to the order you added the TweenData to
+     * ! this Tween, starting at 0.
+     * 
+     * @param {number} idx  index of the TweenData to seek to the time.
+     * @param {number} time time in seconds to seek the specified TweenData
+     */
     seekByIndex(idx, time)
     {
         if (idx < 0 && idx >= this.tweenData.length) return;
         this.tweenData[idx].t = min(time, this.tweenData[idx].duration);
     }
 
+    /**
+     * Called once every time all TweenData on this Tween are completed.
+     * Emits the tweenDataAllCompleted signal.
+     */
     allDone()
     {
         this.emitSignal("tweenAllCompleted");
         this.done = true;
     }
 
+    /**
+     * @override
+     * Adds default signals for the Tween GameObject and serves as a caller
+     * to the _initSignals() callback.
+     * 
+     * @signal tweenAllCompleted    Emited once when all TweenData on this Tween
+     *                              are done.
+     * @signal tweenCompleted       Emited once when one TweenData on this Tween
+     *                              is done. Passes the completed TweenData as a
+     *                              parameter.
+     * @signal tweenStarted         Emited once when one TweenData on this Tween
+     *                              starts. Passes the started TweenData as a 
+     *                              parameter.
+     */
     initSignals()
     {
         this.addSignal("tweenAllCompleted");
@@ -246,23 +412,34 @@ class Tween extends GameObject
         this._initSignals();
     }
 
+    /**
+     * @override
+     * Updates all TweenData added to this Tween and recursively calls the _update(delta)
+     * callback for this GameObject and all of it's children.
+     * @param {*} delta 
+     */
     update(delta)
     {
+        // Checks if all TweenData are done.
         if (!this.done && this.doneTweens == this.tweenData.length) this.allDone();
 
         for (let i = 0; i < this.tweenData.length; i++)
         {
+            // Ignores TweenData that aren't playing.
             if (!this.tweenData[i].playing) continue;
-
+            
+            // Interpolates TweenData that are out of the delay.
             if (this.tweenData[i].t >= 0)
-            {
                 this.interpolate(this.tweenData[i]);
-            }
 
-            if (this.tweenData[i].t < 0 && this.tweenData[i].t + delta >= 0)
+            // Checks if the TweenData just went out of the delay (just started).
+            if (this.tweenData[i].t <= 0 && this.tweenData[i].t + delta >= 0)
                 this.emitSignal("tweenStarted", this.tweenData[i]);
+            
+            // Updates TweenData's current time.
             this.tweenData[i].t = min(this.tweenData[i].t + delta, this.tweenData[i].duration);
 
+            // Checks if the TweenData is done.
             if (!this.tweenData[i].done && this.tweenData[i].t == this.tweenData[i].duration)
             {
                 this.emitSignal("tweenDone", this.tweenData[i]);

+ 89 - 3
pandora/handlers/AssetHandler.js

@@ -19,11 +19,28 @@
  * along with Pandora.  If not, see <https://www.gnu.org/licenses/>.
  *************************************************************************/
 
+/**
+ * This {@code AssetHandler} singleton provides an interface for the user
+ * to load various types of assets to memory.
+ * 
+ * @author Pedro Schneider
+ * 
+ * @namespace
+ */
 const AssetHandler = {
-    cachedTextures: [],
-    cachedAudio: [],
-    cachedFonts: [],
+    cachedTextures: [], // Cache for TextureRes.
+    cachedAudio: [], // Cache for AudioRes.
+    cachedFonts: [], // Cache for FontRes.
 
+    /**
+     * Loads an image to cache as a TextureRes. Can be loaded from a request to a server
+     * or from a local path to a file. The recomended place to call this function is
+     * inside preload for static loading, but it can also be called dynamically inside
+     * the game.
+     * 
+     * @param {String} name name for the TextureRes to be saved as.
+     * @param {String} link link to load the image file from (server or local).
+     */
     loadTexture: function(name, link)
     {
         let textRes = new TextureRes(name, null);
@@ -34,6 +51,14 @@ const AssetHandler = {
         });
     },
 
+    /**
+     * Query a TextureRes by its name.
+     * 
+     * @param {String} name name of the requested TextureRes.
+     * 
+     * @returns reference to the first loaded TextureRes whose name matches
+     *          the parameter, or null if no TextureRes matches the name.
+     */
     getTextureByName: function(name)
     {
         for (let i = 0; i < this.cachedTextures.length; i++)
@@ -46,6 +71,15 @@ const AssetHandler = {
         return null;
     },
 
+    /**
+     * Query a p5.Image by the name of the TextureRes it was loaded as.
+     * 
+     * @param {String} name name of the TextureRes that holds the desired
+     *                      p5.Image.
+     * 
+     * @returns p5.Image held by the first loaded TextureRes whose name
+     *          matches the parameter, or null if no TextureRes matches the name.
+     */
     getP5ImageByName: function(name)
     {
         for (let i = 0; i < this.cachedTextures.length; i++)
@@ -58,12 +92,29 @@ const AssetHandler = {
         return null;
     },
 
+    /**
+     * Loads an audio to cache as an AudioRes. Can be loaded from a request to a server
+     * or from a local path to a file. The recomended place to call this function is
+     * inside preload for static loading, but it can also be called dynamically inside
+     * the game.
+     * 
+     * @param {String} name name for the AudioRes to be saved as.
+     * @param {String} link link to load the audio file from (server or local).
+     */
     loadAudio: function(name, link)
     {
         let audio = createAudio(link);
         this.cachedAudio.push(new AudioRes(name, audio));
     },
 
+    /**
+     * Query an AudioRes by its name.
+     * 
+     * @param {String} name name of the requested AudioRes.
+     * 
+     * @returns reference to the first loaded AudioRes whose name matches
+     *          the parameter, or null if no AudioRes matches the name.
+     */
     getAudioByName: function(name)
     {
         for (let i = 0; i < this.cachedAudio.length; i++)
@@ -76,6 +127,15 @@ const AssetHandler = {
         return null;
     },
 
+    /**
+     * Query a p5.Audio by the name of the AudioRes it was loaded as.
+     * 
+     * @param {String} name name of the AudioRes that holds the desired
+     *                      p5.Audio.
+     * 
+     * @returns p5.Audio held by the first loaded AudioRes whose name
+     *          matches the parameter, or null if no AudioRes matches the name.
+     */
     getP5AudioByName: function(name)
     {
         for (let i = 0; i < this.cachedAudio.length; i++)
@@ -88,6 +148,15 @@ const AssetHandler = {
         return null;
     },
 
+    /**
+     * Loads a font to cache as FontRes. Can be loaded from a request to a server
+     * or from a local path to a file. The recomended place to call this function is
+     * inside preload for static loading, but it can also be called dynamically inside
+     * the game.
+     * 
+     * @param {String} name name for the FontRes to be saved as.
+     * @param {String} link link to load the font file from (server or local).
+     */
     loadFont: function(name, link)
     {
         let fontRes = new FontRes(name, null);
@@ -98,6 +167,14 @@ const AssetHandler = {
         })
     },
 
+    /**
+     * Query a FontRes by its name.
+     * 
+     * @param {String} name name of the requested FontRes.
+     * 
+     * @returns reference to the first loaded FontRes whose name matches
+     *          the parameter, or null if no FontRes matches the name.
+     */
     getFontByName: function(name)
     {
         for (let i = 0; i < this.cachedFonts.length; i++)
@@ -110,6 +187,15 @@ const AssetHandler = {
         return null;
     },
 
+    /**
+     * Query a p5.Font by the name of the FontRes it was loaded as.
+     * 
+     * @param {String} name name of the FontRes that holds the desired
+     *                      p5.Font.
+     * 
+     * @returns p5.Font held by the first loaded FontRes whose name
+     *          matches the parameter, or null if no FontRes matches the name.
+     */
     getP5FontByName: function(name)
     {
         for (let i = 0; i < this.cachedFonts.length; i++)

+ 108 - 17
pandora/handlers/GameHandler.js

@@ -19,56 +19,101 @@
  * along with Pandora.  If not, see <https://www.gnu.org/licenses/>.
  *************************************************************************/
 
+/**
+ * This {@code GameHandler} singleton provides an interface for the user
+ * to manipulate various parameters of the game, instance objects, and more.
+ * 
+ * @author Pedro Schneider
+ * 
+ * @namespace
+ */
 const GameHandler = {
-    nextId: 0,
-    rootObjects: [],
+    nextId: 0, // ID to be given to the next object added to the tree.
+    rootObjects: [], // List of objects on the root of the tree.
 
-    renderMode: null,
+    renderMode: RENDER_MODES.P2D, // Can be RENDER_MODES.P2D or RENDER_MODES.WEBGL.
 
-    bDrawDebugFPS: false,
-    debugFpsLabel: null,
+    bDrawDebugFPS: false, // Should fps be drawn (for debug only).
+    debugFpsLabel: null, // Object that drwas fps.
 
-    prevMillis: 0,
-    delta: 0,
+    prevMillis: 0, // Milliseconds ellapsed since the begining of the application.
+    delta: 0, // Milliseconds ellapsed since the last frame.
 
-    db: null,
-    dbWidth: 1920,
-    dbHeight: 1080,
+    db: null, // Object to hold the secondary buffer.
+    dbWidth: 1920, // Width of the secondary buffer.
+    dbHeight: 1080, // Height of the secondary buffer.
 
+    isMobile: null, // True if the device is a mobile device (tablet of phone).
+    pixelDen: 1, // Pixel density for the canvas on destop devices.
+    pixelDenMobile: 2, // Pixel denisty for the canvas on mobile devices.
+
+    /**
+     * Sets the initial game render mode.
+     * 
+     * @param {RENDER_MODES} mode   RENDER_MODES.P2D for default P5Js render or 
+     *                              RENDER_MODES.WEBGL for webgl (not recomended for mobile).
+     */
     setRenderMode: function(mode)
     {
         this.renderMode = mode;
     },
 
+    /**
+     * Sets the width and height in pixels to initialize the secondary buffer.
+     * 
+     * @param {number} w    width in pixels to initialize the secondary buffer.
+     * @param {number} h    height in pixels to initialize the secondary buffer.
+     */
     setDoubleBufferSize: function(w, h)
     {
         this.dbWidth = w;
         this.dbHeight = h;
     },
 
-    pixelDen: 1,
+    /**
+     * Sets the pixel density for the canvas to be initialized with on desktop
+     * devices.
+     * 
+     * @param {number} val  pixel density for the canvas on desktop devices.
+     */
     setPixelDensity: function(val)
     {
         this.pixelDen = val;
     },
 
-    pixelDenMobile: 2,
+    /**
+     * Sets the pixel density for the canvas to be initialized with on desktop
+     * devices.
+     * 
+     * @param {number} val  pixel density for the canvas on desktop devices.
+     */
     setPixelDensityMobile: function(val)
     {
         this.pixelDenMobile = val;
     },
 
+    /**
+     * Sets the flag to draw the debug fps.
+     * 
+     * @param {boolean} val true if debug fps should be drawn, false if not.
+     */
     drawDebugFPS(val)
     {
         this.bDrawDebugFPS = val;
     },
 
-    isMobile: null,
+    /**
+     * Initializes the game, creating the canvas, secondary buffer, and creates the
+     * debug fps label if necessary.
+     * 
+     * @param {number} fps  target fps for the game (default if 60).
+     */
     init: function(fps = 60)
     {
+        // Sets the mobile flag.
         this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
 
-        if (!this.renderMode) this.renderMode = RENDER_MODES.P2D;
+        // Creates the main canvas and the secondary buffer with the specified size and render mode.
         switch (this.renderMode)
         {
             case RENDER_MODES.P2D:
@@ -80,9 +125,9 @@ const GameHandler = {
                 this.db = createGraphics(this.dbWidth, this.dbHeight, WEBGL);
                 this.db.smooth();
                 break;
-
         }
 
+        // Sets framerate and pixel density accordingly.
         frameRate(fps);
         if (this.isMobile)
             pixelDensity(this.pixelDenMobile);
@@ -90,12 +135,15 @@ const GameHandler = {
             pixelDensity(this.pixelDen);
         smooth();
 
+        // Translates the canvas to the middle if render mode is webgl to maintain
+        // consistency on the coordinate system.
         if (this.renderMode == RENDER_MODES.WEBGL)
         {
             translate(-windowWidth / 2, -windowHeight / 2);
             db.translate(-this.dbWidth / 2, -this.dbHeight / 2);
         }
 
+        // Creates the debug fps label.
         if (this.bDrawDebugFPS)
         {
             this.debugFpsLabel = new Label("debugFps", `FPS: ${frameRate()}`);
@@ -103,12 +151,23 @@ const GameHandler = {
         }
     },
 
+    /**
+     * Instances a GameObject, meaning to give it an ID. This function is only called on the
+     * constructor of GameObject, and probably shouldn't be used for anything else.
+     * 
+     * @param {GameObject} obj  GameObject to be instanced. 
+     */
     instanceGameObject: function(obj)
     {
         obj.id = this.nextId;
         this.nextId++;
     },
 
+    /**
+     * Adds a GameObject to the root of the tree. There should be as little root objects as possible.
+     * 
+     * @param {GameObject} obj  GameObject to be added as a root of the tree. 
+     */
     addRootObject: function(obj)
     {
         this.rootObjects.push(obj);
@@ -116,6 +175,13 @@ const GameHandler = {
         obj.setup();
     },
 
+    /**
+     * Removes a GameObject from the root of the tree. This function is called automatically when a root object
+     * is freed from memory, and probably shoudn't be used for anything else. DOES NOT DELETE THE OBJECT, ONLY
+     * REMOVES IT FROM THE TREE.
+     * 
+     * @param {number} id   object id of the GameObject that should be removed from the tree.
+     */
     removeRootObjectById: function(id)
     {
         for (let i = 0; i < this.rootObjects.length; i++)
@@ -125,10 +191,14 @@ const GameHandler = {
         }
     },
 
-    upframecount: 0,
-    upframenum: 20,
+    upframecount: 0, // Frame count to be displayed.
+    upframenum: 20, // Delay in frames to update the frame count.
+    /**
+     * Updates all of the GameObjects on the tree.
+     */
     update: function()
     {
+        // Updates the debug fps label if it existis.
         if (this.bDrawDebugFPS)
         {
             if (frameCount % this.upframenum == 0)
@@ -141,23 +211,37 @@ const GameHandler = {
             else
                 this.upframecount = max(this.upframecount, frameRate());
         }
+
+        // Updates the delta.
         this.delta = (millis() - this.prevMillis) / 1000;
+        
+        // Updates all game objects on the tree.
         for (let i = 0; i < this.rootObjects.length; i++)
             this.rootObjects[i].update(this.delta);
     },
 
+    /**
+     * Draws all of the GameObjects on the tree.
+     */
     draw: function()
     {
+        // Clear the secondary buffer.
         this.db.clear();
+
+        // Draw all game objects.
         for (let i = 0; i < this.rootObjects.length; i++)
             this.rootObjects[i].draw(this.delta, this.db);
 
+        // Draw a rectangle to visualize the secondary buffer.
+        // TODO: remove this
         this.db.push();
         this.db.strokeWeight(5);
         this.db.noFill();
         this.db.rect(0, 0, this.dbWidth, this.dbHeight);
         this.db.pop();
 
+        // Centers the image and calculates the dimensions of the secondary
+        // buffer to best fit the size of the window.
         imageMode(CENTER);
         if (windowWidth / windowHeight < this.dbWidth / this.dbHeight)
         {
@@ -170,12 +254,19 @@ const GameHandler = {
             this.db.screenWidth = windowHeight * (this.dbWidth / this.dbHeight);
         }
 
+        // Draws the secondary buffer to the main canvas.
         image(this.db, windowWidth / 2, windowHeight / 2, this.db.screenWidth, this.db.screenHeight);
 
+        // Updates the delta
         this.prevMillis = millis();
     }
 }
 
+/**
+ * @callback
+ * This function is called once every time the browser window is resized. Here, its used to make the game
+ * always ocupy the entire browser window.
+ */
 function windowResized()
 {
     resizeCanvas(windowWidth, windowHeight);