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);
}На этом я закончу вторую часть из цикла статей по созданию игры с Дино, надеюсь вам было интересно и вы попробовали сами с нуля создать свою игру!
Вы можете найти код для этого урока тут