Example #1
0
export const Engine = (function() {

  /**
   * canvas
   * @type {Object}
   */
  const canvas = window.document.createElement('canvas');

  /**
   * Set the canvas width
   * @type {Number}
   */
  canvas.width = 707;

  /**
   * Set the canvas height
   * @type {Number}
   */
  canvas.height = 707;

  /**
   * ctx
   * @type {Object}
   */
  const ctx = canvas.getContext('2d');

  /**
   * lastTime
   * @type {string}
   */
  let lastTime;

  /**
   * Append the canvas
   */
  window.document.body.appendChild(canvas);

  /**
   * main - kickoff point for the game loop itself and handles
   * calling the update and render methods
   */
  function main() {

    /**
     * Get time delta information, which is required for smooth animation.
     * Because computers process instructions at different speeds,
     * we need a constant value that would be the same on every system.
     */

    /**
     * now
     * @type {string}
     */
    const now = Date.now();

    /**
     * deltaTime
     * @type {string}
     */
    const deltaTime = (now - lastTime) / 1000.0;

    /**
     * Call update/render functions
     */
    update(deltaTime);
    render();

    /**
     * Set lastTime, which is used to determine the time delta
     * for the next time this function is called.
     */
    lastTime = now;

    /**
     * Use the browser's requestAnimationFrame function to call this
     * function again as soon as the browser is able to draw another frame.
     */
    window.requestAnimationFrame(main);

  }

  /**
   * init
   */
  function init() {
    lastTime = Date.now();
    main();
  }

  /**
   * update - called by the main function (game loop)
   * @param {string} deltaTime
   */
  function update(deltaTime) {
    updateEntities(deltaTime);
    checkCollisions();
  }

  /**
   * updateEntities - called by the update function
   * @param {string} deltaTime
   */
  function updateEntities(deltaTime) {

    Game.allEnemies.forEach(function(enemy) {
      enemy.update(deltaTime);
    });

    Game.player.update();

  }

  /**
   * render - initially draws the game, then called for every game tick (loop of the engine)
   */
  function render() {

    /**
     * rowImages - holds the relative URLs of the row images
     * @type {Array}
     */
    const rowImages = [
      `${Resources.path}/water-block.png`,
      `${Resources.path}/grass-block.png`,
      `${Resources.path}/stone-block.png`,
      `${Resources.path}/stone-block.png`,
      `${Resources.path}/stone-block.png`,
      `${Resources.path}/stone-block.png`,
      `${Resources.path}/grass-block.png`
    ];

    /**
     * totalRows
     * @type {Number}
     */
    const totalRows = 7;

    /**
     * totalColumns
     * @type {Number}
     */
    const totalColumns = 7;

    /**
     * row
     */
    let row;

    /**
     * column
     */
    let column;

    /* Loop through the number of rows and columns we've defined above
     * and, using the rowImages array, draw the correct image for that
     * portion of the "grid"
     */
    for (row = 0; row < totalRows; row ++) {
      for (column = 0; column < totalColumns; column ++) {

        /**
         * ctx.drawImage
         * @param {string} - URL of image to draw
         * @param {string} - x coordinate
         * @param {string} - y coordinate
         */
        ctx.drawImage(Resources.get(rowImages[row]), column * 101, row * 83);

      }
    }

    /**
     * Call the renderEntities function
     */
    renderEntities();

  }

  /**
   * renderEntities - called by the render function and each game tick
   */
  function renderEntities() {

    /* Render Enemies
     * Loop through all of the objects within the allEnemies array and call
     * the render method.
     */
    Game.allEnemies.forEach(function(enemy) {
      enemy.render();
    });

    /* Render player
     * Renders the player on the canvas.
     */
    Game.player.render();

    /* Render gems
     * Loop through all of the objects within the allGems array and call
     * the render method.
     */
    Game.allGems.forEach(function(gem) {
    	gem.render();
    });

    /* Render stats
     * Renders the stat panel and containing elements at top of canvas
     */
    Game.stats.render();

  }

  /**
   * checkCollisions - determines if game entities have collided
   * @return {[type]} [description]
   */
  function checkCollisions() {

		/**
		* Check for the collision of two entities.
		* Function accepts two arguments.
		*/

    /**
     * collision
     * @param  {string} a - entity a
     * @param  {string} b - entity b
     * @return {boolean}
     */
		function collision(a, b) {
		  return a.x < b.x + b.width &&
		         a.x + a.width > b.x &&
		         a.y < b.y + b.height &&
		         a.y + a.height > b.y;
		}

  	/* Check enemy collisions.
  	 * If there is a collision, reset the player's position
  	 * and update the players lives or reset the game.
  	 */
  	Game.allEnemies.forEach(function(enemy) {

			if (collision(Game.player, enemy)) {

				/* Reset the players position.
				 */
				Game.player.hit();

				/* If the player has more than one life remaining,
				 * call the player.updateLives method and remove a life.
				 * If the player has no more lives remaining, reset the game.
				 */
				return Game.player.lives > 1 ? Game.player.updateLives('remove', 1) : Game.level.reset();

			}

  	});

  	/* Check gem collisions.
  	 * If there is a collision, call the gem.clear() method to
  	 * clear the gem from the canvas and call the stats.updateGems
  	 * to update the gems count and increase the score by 300 points.
  	 */
  	Game.allGems.forEach(function(gem) {

    	if (collision(Game.player, gem)) {

	    	gem.clear();

	    	Game.stats.updateGems();

    	}

  	});

  	/* Check goal collisions.
  	 * If the player gets to the other side, update the level
  	 */
  	if (Game.player.y == 70) {

				Game.level.update();

		}

  }

  /**
   * Load all of the images required to draw the game, then set init as
   * the callback method, so that once the images are loaded the game
   * will start.
   */
  Resources.load([
    `${Resources.path}/stone-block.png`,
    `${Resources.path}/water-block.png`,
    `${Resources.path}/grass-block.png`,
    `${Resources.path}/enemy-bug.png`,
    `${Resources.path}/stat-heart.png`,
    `${Resources.path}/stat-gem.png`,
    `${Resources.path}/gem-blue.png`,
    `${Resources.path}/gem-green.png`,
    `${Resources.path}/gem-orange.png`,
    `${Resources.path}/char-boy.png`
  ]);
  Resources.onReady(init);

  /**
   * Return public variables
   */
  return {
    canvas,
    ctx
  }

})();
Example #2
0
  /**
   * render - initially draws the game, then called for every game tick (loop of the engine)
   */
  function render() {

    /**
     * rowImages - holds the relative URLs of the row images
     * @type {Array}
     */
    const rowImages = [
      `${Resources.path}/water-block.png`,
      `${Resources.path}/grass-block.png`,
      `${Resources.path}/stone-block.png`,
      `${Resources.path}/stone-block.png`,
      `${Resources.path}/stone-block.png`,
      `${Resources.path}/stone-block.png`,
      `${Resources.path}/grass-block.png`
    ];

    /**
     * totalRows
     * @type {Number}
     */
    const totalRows = 7;

    /**
     * totalColumns
     * @type {Number}
     */
    const totalColumns = 7;

    /**
     * row
     */
    let row;

    /**
     * column
     */
    let column;

    /* Loop through the number of rows and columns we've defined above
     * and, using the rowImages array, draw the correct image for that
     * portion of the "grid"
     */
    for (row = 0; row < totalRows; row ++) {
      for (column = 0; column < totalColumns; column ++) {

        /**
         * ctx.drawImage
         * @param {string} - URL of image to draw
         * @param {string} - x coordinate
         * @param {string} - y coordinate
         */
        ctx.drawImage(Resources.get(rowImages[row]), column * 101, row * 83);

      }
    }

    /**
     * Call the renderEntities function
     */
    renderEntities();

  }