Как сделать Flappy Bird на HTML5 с помощью Phaser
Изначально статья была опубликована в блоге её автора [English]
Flappy Bird небольшая милая игра с простой механикой, и я подумал, что она будет превосходным примером для урока о создании игр с помощью HTML5. Поэтому в этой статье мы попробуем сделать упрощенную версию Flappy Bird в 65 строчек кода.
Взгляните на игру, которую мы собираемся сделать.
Замечание 1: вы должны обладать базовыми знаниями JavaScript, чтобы понять эту статью.
Замечание 2: Если вас заинтересует фреймворк Phaser, то вы можете узнать о нём больше, прочитав мою статью быстрый старт c Phaser.
Настройка
Скачайте базовый шаблон. В нём вы найдёте:
- phaser.min.js — минифицированный фреймворк Phaser версии v1.1.5.
- index.html — страничка игры.
- main.js — файл, в котором мы будем писать код.
- assets/ — папка с двумя картинками (птичка и труба).
Разместите эти файлы на сервере. Откройте index.html в браузере, а main.js — редакторе или IDE.
В файле main.js вы должны увидеть базовую структуру проекта на Phaser, которую мы обсуждали в прошлой статье.
// инициализировать Phaser и создать игру с поле размером 400px на 490px
var game = new Phaser.Game(400, 490, Phaser.AUTO, 'game_div');
var game_state = {};
game_state.main = function() { };
game_state.main.prototype = {
preload: function() {
// загрузка всей необходимой статики
},
create: function() {
// настройка игры; вызывается сразу после preload
},
update: function() {
// вызывается 60 раз в секунду
},
};
game.state.add('main', game_state.main);
game.state.start('main');
Теперь мы собираемся реализовать функции preload()
, create()
и update()
и
добавить новые недостающие для полноценной игры функции.
Птичка!
Итак, начнём программировать! Давайте сначала сосредоточимся на птичке, которой можно было бы управлять с помощью «пробела».
Всё достаточно просто и хорошо документировано, поэтому код должен быть понятен. Для лучшей читаемости я удалил инициализацию Phaser и код отвечающий за контроль состояний (этот код вы могли видеть выше).
Давайте напишем функции preload()
, create()
и update()
.
preload: function() {
// сменим фон игры
this.game.stage.backgroundColor = '#71c5cf';
// загрузим картинку Птички
this.game.load.image('bird', 'assets/bird.png');
},
create: function() {
// покажем птичку на экране
this.bird = this.game.add.sprite(100, 245, 'bird');
// добавим гравитацию, заставив птичку падать вниз
this.bird.body.gravity.y = 1000;
// добавим функцию jump в качестве обработчика нажатия пробела
var space_key = this.game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
space_key.onDown.add(this.jump, this);
},
update: function() {
// если птичка вылетела за пределы экрана (слишком высоко или слишком низко),
// то необходимо вызвать функцию restart_game
if (this.bird.inWorld == false)
this.restart_game();
},
После этого добавим две новые функции.
// поможем птичке подпрыгнуть
jump: function() {
// добавляем вертикальную скорость птице
this.bird.body.velocity.y = -350;
},
// начинаем игру заново
restart_game: function() {
// запускаем состояние "main", которое перезапускает игру
this.game.state.start('main');
},
Сохраните файл main.js с новым кодом и обновите index.html. Вы должны увидеть птичку подпрыгивающую при нажатии пробела.
Трубы
Игра Flappy Bird не будет такой интересной без труб, поэтому давайте добавим их.
Сначала надо загрузить изображение трубы в функции preload()
.
this.game.load.image('pipe', 'assets/pipe.png');
Затем надо создать группу труб в функции create()
. Мы собираемся обрабатывать
большое количество труб в игре, поэтому будет проще использовать группу объектов.
Она будет содержать 20 труб, с которыми мы вольны делать всё, что душе угодно.
this.pipes = game.add.group();
this.pipes.createMultiple(20, 'pipe');
Теперь нам требуется функция, добавляющая трубу в игру. По умолчанию, трубы в группе «мертвы» и не показываются. Итак, мы берём неиспользованную трубу, показываем её и следим за тем, чтобы она автоматически удалялась, когда становится невидимой. Таким образом нам всегда будет хватать труб.
add_one_pipe: function(x, y) {
// получаем первую неиспользованную трубу из группы
var pipe = this.pipes.getFirstDead();
// позиционируем трубу на игровом поле
pipe.reset(x, y);
// добавим скорость трубе, чтобы она двигалась влево
pipe.body.velocity.x = -200;
// удаляем трубу, когда она становится невидимой
pipe.outOfBoundsKill = true;
},
Предыдущая функция покажет нам только одну трубу, но нам нужны шесть с промежутками между ними. Так давайте напишем соответствующую функцию.
add_row_of_pipes: function() {
var hole = Math.floor(Math.random()*5) + 1;
for (var i = 0; i < 8; i++) {
if (i !== hole && i !== (hole + 1)) {
this.add_one_pipe(400, i*60 + 10);
}
}
},
Теперь, чтобы трубы появлялись, надо вызывать функцию add_row_of_pipes()
каждые 1.5
секунды. Для этого мы можем добавить соответствующий таймер в функцию create()
.
this.timer = this.game.time.events.loop(1500, this.add_row_of_pipes, this);
И наконец добавим строчку кода, останавливающую таймер в начало функции
restart_game()
.
this.game.time.events.remove(this.timer);
Теперь вы можете сохранить файл и попробовать поиграть. Наша затея медленно превращается в настоящую игру.
Подсчёт очков и столкновения
Последняя вещь, которую необходимо добавить в игру это подсчет очков и научиться обрабатывать столкновения. И сделать это очень просто.
Добавьте эти строчки в функцию create()
, чтобы показать счёт в левом верхнем игру.
this.score = 0;
var style = { font: "30px Arial", fill: "#ffffff" };
this.label_score = this.game.add.text(20, 20, "0", style);
А это добавьте в add_row_of_pipes()
, чтобы увеличивать счёт каждый раз, когда
новая создаётся новая труба.
this.score += 1;
this.label_score.content = this.score;
Эту строчку, в свою очередь, надо добавить в функцию update()
, чтобы вызвать
restart_game()
каждый раз, когда птичка встречается с роковой трубой.
this.game.physics.overlap(this.bird, this.pipes, this.restart_game, null, this);
Эгей, мы закончили! Я вас поздравляю, теперь у вас есть HTML5 клон игры Flappy Bird. Вы можете найти её код на github.
Что дальше?
Игра работает, но она немного скучная. В следующей статье мы узнаем как сделать её интереснее с помощью звуков, анимации, меню и прочего. Поэтому, если вы не подписаны на рассылку, то обязательно подпишитесь, чтобы узнать, когда будет готова следующая статья (форма подписки доступна на странице оригинальной статьи, — прим. переводчика).
Также вы можете взглянуть на мой чэллендж (!!!) «по одной HTML5-игре в неделю» на сайте lessmilk.com.