Браузерные игры
April 22, 2022

JS + Phaser пишем игру с Дино (часть 5) 🦖

Перед тем как начать:

В прошлой части мы с вами добавили коллизии, а так же разобрались с тем, как создать кнопку для перезапуска игры, если вы это пропустили, то советую вернуться к части 4.

Код, который уже готов живет тут.

Всем привет!

Просто бегать - это слишком скучно, поэтому я хочу добавить в игру счет, а в месте с ним и некоторый соревновательный эффект!

Отображаем счет

Первое что нам нужно сделать - это добавить новое поле в наш класс, давайте объявим его в методе create():

  create() {
    this.score = 0;
    
    // Остальной код фукнции
  }

Теперь мы с вами сможем как-то считать очки, которые получит игрок, но так же нам нужно и отображать эти данные, поэтому в этой же функции надо создать текстовый спрайт:

  create() {
    // Остальной код фукнции
    this.scoreText = this.add.text(width, 0, "00000", {
         fill: "#535353",
         font: '900 35px Courier',
         resolution: 5
       }).setOrigin(1, 0);
  }

Текстовый спрайт принимает следующие параметры:

  • Координату x своего положения
  • Координату y своего положения
  • Стартовое значения (взяли '00000' - как в оригинале игры)
  • Конфигурацию для текста: цвет, стиль шрифта, разрешение.


Как видите теперь у нас появился счет:

Считаем победные очки

Нам нужно где-то считать победные очки, для этого давайте создадим отдельную функцию handleScore() и проинициализируем ее в методе create():

create() {
  // Остальной код фукнции
  this.handleScore();
}
  handleScore() {
    this.time.addEvent({
      delay: 1000/10,
      loop: true,
      callbackScope: this,
      callback: () => {
        // 1
        if (!this.isGameRunning) { return; }

        // 2
        this.score++;
        this.gameSpeed += 0.01

        // 3
        const score = Array.from(String(this.score), Number);
        for (let i = 0; i < 5 - String(this.score).length; i++) {
          score.unshift(0);
        }

        // 3
        this.scoreText.setText(score.join(''));
      }
    })
  }

  1. Если игра не идет, то мы ничего не считаем
  2. Если все же идет, то прибавляем счет и увеличиваем скорость игры
  3. Так как отображение - это 5ти значное число, то приводим к такому виду
  4. Изменяем нам текстовый спрайт на новое значение

Запоминаем лучший результат

Давайте добавим нашей игре немного памяти и начнем запоминать лучший счет игрока, для этого создадим еще один текстовый спрайт:

create() {
  // Остальной код фукнции
  this.highScoreText = this.add.text(0, 0, "00000", {
        fill: "#535353",
        font: '900 35px Courier',
        resolution: 5
      }).setOrigin(1, 0);
 }

Кстати, я так подумала, давайте пока не начнется игра не будем показывать счет, поэтому для двух наших текстовых спрайтов по дефолту определим .setAlpha(0):

create() {
  // Остальной код фукнции
  this.scoreText = this.add.text(width, 0, "00000", {
         fill: "#535353",
         font: '900 35px Courier',
         resolution: 5
       }).setOrigin(1, 0).setAlpha(0);

  this.highScoreText = this.add.text(0, 0, "00000", {
        fill: "#535353",
        font: '900 35px Courier',
        resolution: 5
      }).setOrigin(1, 0).setAlpha(0);
}

Логично, что когда начнется игра нам нужно вызвать у спрайта со счетом  setAlpha(1), сделаем это в момент начала игры (в методе initStartTrigger()):

  initStartTrigger() {
    const { width, height } = this.game.config;
    
    this.physics.add.overlap(this.startTrigger, this.dino, () => {
      // Остальной код колбека
      
      const startEvent =  this.time.addEvent({
        delay: 1000/60,
        loop: true,
        callbackScope: this,
        callback: () => {
          // Остальной код колбека
          
          // Запустим игру
          if (this.ground.width >= 1000) {
            this.ground.width = width;
            this.isGameRunning = true;
            this.dino.setVelocityX(0);
            
            // Сюда добавим появление спрайта со счетом
            this.scoreText.setAlpha(1);
            
            startEvent.remove();
          }
        }
      });

    }, null, this);
  }

А вот когда произойдет коллизия нам бы сбросить счет, поэтому надо тоже добавить такую обработку в метод initColliders():

  initColliders() {
    this.physics.add.collider(this.dino, this.obsticles, () => {
      this.physics.pause();
      this.isGameRunning = false;
      this.anims.pauseAll();
      this.dino.setTexture('dino-hurt');
      this.respawnTime = 0;
      this.gameSpeed = 20;
      this.gameOverScreen.setAlpha(1);
      
      // Сюда добавим обнуление счета
      this.score = 0;
    }, null, this);
  }

Вот что у нас получилось:

Осталось добавить отображение и расчет лучшего забега, добавим это тоже в функцию initColliders():

  initColliders() {
    this.physics.add.collider(this.dino, this.obsticles, () => {
      // Вычистлим позицию где отрисовать счет
      this.highScoreText.x = this.scoreText.x - this.scoreText.width - 20;

      // Получим предыдущее максимальное значение
      const highScore = this.highScoreText
        .text.substr(this.highScoreText.text.length - 5);
        
      // Сравним текущее с предыдущим и определим новое значение
      const newScore = Number(this.scoreText.text) > Number(highScore)
        ? this.scoreText.text
        : highScore;

      // Добавим максимальный счет на сцену
      this.highScoreText.setText('Top: ' + newScore);
      this.highScoreText.setAlpha(1);

      // Остальной код функции
    }, null, this);
  }

На этом я закончу пятую часть из цикла статей по созданию игры с Дино, надеюсь вам было интересно и вы попробовали сами с нуля создать свою игру!

Вы можете найти код для этого урока тут

JS + Phaser пишем игру с Дино (часть 6) 🦖->