View file Space-Quiz-master/src/js/game.js

File size: 4.23Kb
import Player from './modules/player';
import Quiz from './modules/quiz';
import Starfield from './modules/starfield';
import State from './modules/state';
import Modal from './modules/modal';

'use strict';

/**
 * Class representing the main logic for the game and
 * holding all objects and data.
 */
export default class Game {
  /**
   * @param {HTMLCanvasElement} canvas The canvas dom element.
   * @param {Object[]} data The data with game quiz uploaded from database.
   * @param {Object[]} assets The images required for the game.
   */
  constructor({
    gameLvl,
    gameUi,
    gameModal,
    data,
    assets
  }) {
    // assign base properties
    this.$gameLvl = gameLvl;
    this.$canvasBlock = this.$gameLvl.querySelector('.game-level__canvas-block');
    this.canvas = this.$gameLvl.querySelector('.canvas-block__canvas');
    this.ctx = this.canvas.getContext('2d');
    this.canvas.width  = this.$canvasBlock.clientWidth;
    this.canvas.height = this.$canvasBlock.clientHeight;

    this.width = this.canvas.width;
    this.height = this.canvas.height;

    this.data = data;
    this.assets = assets;

    this.raccoon = this.assets.getImage('raccoon.png');
    this.cookie = this.assets.getImage('cookie.png');

    this.$gameUi = gameUi;
    this.$gameModal = gameModal;
  }

  /** Reset properties and start the game. */
  start() {
    this._init();
    this._reset();
  }

  _reset() {
    this._time = false;
    this._isOver = false;

    this._now = (new Date()).getTime();
    this._last = (new Date()).getTime() - 1;
    this.delta = 1;
    this._loop = null;

    // the object of cursor position
    this.cursor = {
      x: this.width / 2,
      y: this.height / 2
    };

    this.state.reset();
    this._modal.reset();
  }

  /** Create main objects and initiates game loop. */
  _init() {
    this._starfield = new Starfield(this);
    this._quiz = new Quiz(this);
    this._quiz.newQuest();
    this._player = new Player(this);

    // init game interface and count score and lives
    this.state = new State({
      elem: this.$gameUi,
      callback: this.gameOver.bind(this)
    });

    // init game over modal
    this._modal = new Modal({
      elem: this.$gameModal
    });

    // create mousemovement event to have the current mouse position
    this.canvas.addEventListener('mousemove', (function(e) {
      this._getMousePosition(e);
    }).bind(this));

    this._loop = requestAnimationFrame((function() {
      this._gameloop();
    }).bind(this));
  }

  /**
   * Calculate the current mouse position inside the canvas.
   * @param {MouseEvent} event
   */
  _getMousePosition(event) {
    let nx = event.clientX;
    let ny = event.clientY;

    this.cursor = {
      x: nx,
      y: ny
    };
  }

  /** Show game over modal window and clear game objects. */
  gameOver() {
    let score = this.state.getScore();
    this._modal.show(score);
    this._isOver = true;

    this.ctx.clearRect(0, 0, this.width, this.height);

    this._player = null;
    this._quiz = null;

    this._loop = null;
  }

  /**
   * Create new delta, calls update and render functions,
   * calls itself again on completion.
   */
  _gameloop() {
    if (!this._isOver) {
      // create new delta value
      this._setDelta();
      // calculate new data
      this._update();
      // render it to the canvas
      this._render();
      // call this function again
      this.loop = requestAnimationFrame((function() {
        this._gameloop();
      }).bind(this));
    }
  }

  /** Call all update functions needed for game. */
  _update() {
    this._starfield.update(this.delta);
    this._quiz.update(this.delta);
    this._player.update(this.delta);

  }

  /** Call all rendering functions needed for game. */
  _render() {
    this.ctx.clearRect(0, 0, this.width, this.height);
    this._starfield.render(this.ctx);
    this._quiz.render(this.ctx);
    this._player.render(this.ctx);
    // render cookie at mouse position
    this.ctx.drawImage(this.cookie, this.cursor.x - 10, this.cursor.y - 10);
  }

  /**
   * Recalculate new delta value based on the current time and
   * the last time called to make precise time based animations.
   */
  _setDelta() {
    this._now = (new Date()).getTime();
    this.delta = (this._now - this._then) / 1000;
    this._then = this._now;
  }

}