JS + Phaser пишем игру с Дино (часть 2) 🦖
В прошлой части мы с вами настроили сборку проекта, загрузили статику и настроили наши первые анимации, если вы это пропустили, то советую вернуться к части 1.
Код, который уже готов живет тут.
В этой части мы с вами добавим для Дино оставшиеся анимации и контролы действия, а так же настроим плавный старт игры!
Включим debug режим
Для начала давайте на время разработки включим debug
режим для нашей игры, для этого в index.js
в конфиге нужно заменить debug: false
на debug: true
:
import Phaser from 'phaser'; import PlayScene from './PlayScene'; import PreloadScene from './PreloadScene'; const config = { type: Phaser.AUTO, width: 1000, height: 340, pixelArt: true, transparent: true, physics: { default: 'arcade', arcade: { // Включаем debug debug: true } }, scene: [PreloadScene, PlayScene] }; new Phaser.Game(config);
Теперь мы можем с вами видеть границы спрайта Дино:
Учимся пригибаться
Теперь можно добавить для Дино возможность пригибаться, для этого нам нужно обработать клавишу вниз.
Вернемся к нашей функции, которая обрабатывает нажатие клавиш и добавим следующий код:
createControll() { // остальной код этой функции this.input.keyboard.on('keydown-DOWN', () => { if (!this.dino.body.onFloor()) { return; } this.dino.body.height = 58; this.dino.body.offset.y = 34; }); this.input.keyboard.on('keyup-DOWN', () => { this.dino.body.height = 92; this.dino.body.offset.y = 0; }); }
Как вы можете заметить, мы добавили два обработчика. Первый будет срабатывать когда мы нажимаем кнопку вниз, а второй - когда отпускаем.
В этих обработчиках мы меняем высоту нашего спрайта, зачем спросите вы?
Все просто, давайте посмотрим на спрайты разных состояний Дино:
Думаю, после этой картинки понятно, почему когда мы нажимаем клавишу вниз - нам нужно уменьшить рост Дино, а когда отпускаем - вернуть его в исходное состояние.
Сейчас в браузере при нажатии клавиши вниз мы получим следующее:
Дальше давайте создадим анимацию для того, чтобы потом ее применить к Дино при нажатии клавиши вниз:
initAnims() { // Остальной код функции this.anims.create({ key: 'dino-down-anim', frames: this.anims.generateFrameNumbers('dino-down', {start: 0, end: 1}), frameRate: 10, repeat: -1 }); }
А в функции update()
внесем изменения так, чтобы мы начали смотреть на высоту персонажа при выборе того, какую анимацию рисовать:
update() { this.ground.tilePositionX += this.gameSpeed; if (this.dino.body.deltaAbsY() > 0) { this.dino.anims.stop(); this.dino.setTexture('dino', 0); } else { // Исходя из высоты выбираем анимацию this.dino.body.height <= 58 ? this.dino.play('dino-down-anim', true) : this.dino.play('dino-run', true); } }
Отслеживаем начало игры
И так, в классическом хромовском динозаврике игра начинается с первого прыжка, раз уж мы делаем копию этой игры, то давайте повторим это вопедение.
Для этого нам нужно добавить некоторый триггер, который нам подскажет, то первый раз игрок подпрыгнул и пора бы начать игру.
create() { // Остальной код функции this.startTrigger = this.physics.add.sprite(0, 10).setOrigin(0, 1).setImmovable(); this.initStartTrigger(); }
Можно заметить, что у нас появилась вот такая вот странная штука вверху экрана:
Давайте сделаем первое прикосновение с добавленным нами спрайтом - триггером для начала игры, для этого нужно создать метод initStartTrigger()
, который как раз и позволит нам это отслеживать:
initStartTrigger() { const { width, height } = this.game.config; // Обработчик this.physics.add.overlap(this.startTrigger, this.dino, () => { // Если параметр y, у нашего страйта триггера === 10, // то переместим наш триггер, чтобы больше его не трогать if (this.startTrigger.y === 10) { this.startTrigger.body.reset(0, height); return; } // Как только мы начнем игру, // то можно перестать слушать данный обработчик this.startTrigger.disableBody(true, true); }, null, this); }
Сейчас у нас получилось следующее:
Дальше нам нужно с вами завести флаг начала игры:
create() { // Остальной код функции this.isGameRunning = false; }
А в нашей функции update()
, если игра еще не началась - то нужно убрать все обработки:
update() { // Ничего не делаем, если игра не началась if (!this.isGameRunning) { return; } this.ground.tilePositionX += this.gameSpeed; if (this.dino.body.deltaAbsY() > 0) { this.dino.anims.stop(); this.dino.setTexture('dino', 0); } else { this.dino.body.height <= 58 ? this.dino.play('dino-down-anim', true) : this.dino.play('dino-run', true); } }
Но игру нам нужно где-то начать, поэтому давайте сделаем пару доработок, для начала, я хочу задать стартовую ширину земли - равную ширине спрайта Дино, для того, чтобы пока игра не началась не отрисовывать ее полностью так же как и в оригинале:
create() { // Остальной код функции // Ставим вместо width -> 88px this.ground = this.add.tileSprite(0, height, 88, 26, 'ground').setOrigin(0, 1); }
После чего добавим обработку начала игры в наш метод initStartTrigger()
Так этот файл будет выглядеть после всех доработок:
initStartTrigger() { const { width, height } = this.game.config; // Обработчик this.physics.add.overlap(this.startTrigger, this.dino, () => { // Если параметр y, у нашего страйта триггера === 10, // то переместим наш триггер, чтобы больше его не трогать if (this.startTrigger.y === 10) { this.startTrigger.body.reset(0, height); return; } // Как только мы начнем игру, // то можно перестать слушать данный обработчик this.startTrigger.disableBody(true, true); const startEvent = this.time.addEvent({ delay: 1000/60, // Небольшая задержка loop: true, // Зациклинность callbackScope: this, // Область работы - наш класс callback: () => { // Обработчик срабатывания // Немного переместим нашего Дино this.dino.setVelocityX(80); // И активируем ему анимацию this.dino.play('dino-run', 1); // Плавно будем добавлять ширину земли // но только пока она будет меньше ширины canvas if (this.ground.width < width) { this.ground.width += 17 * 2; } // Как только достигним нужной ширины - запустим игру if (this.ground.width >= 1000) { this.ground.width = width; this.isGameRunning = true; this.dino.setVelocityX(0); startEvent.remove(); } } }); }, null, this); }
На этом я закончу вторую часть из цикла статей по созданию игры с Дино, надеюсь вам было интересно и вы попробовали сами с нуля создать свою игру!
Вы можете найти код для этого урока тут