HTML5 Phaser ECMAScript 6

Часть 21: Последовательная tween анимация карточек

Как я говорил в предыдущем посте, карточки я расположил по горизонтали. Переход между ними должен был быть анимированным. Имея опыт в создании сцены меню, вывод нужной карточки на экран было пустяшным делом. Но тут возникла проблема утомления игрока.

сцена изучения новых слов в Tiled редакторе

Логика игры в том, что бы показывать карточку повторно, если игрок на нее ответил не верно. Теперь представьте ситуацию, если пользователь ответил не правильно на 2 и 12 карточку? Для перехода с 12 на 2 и назад нужно быстро прокрутить 10 карточек. Для людей страдающих морской болезнью, это может вызвать чувство тошноты.

Что бы решить данную задачу не отказываясь от анимации, достаточно удалять карточки на которые игрок ответил правильно. Это добавит понимания принципа игры, а также значительно уменьшить интенсивность анимации. Лучше всего удалить карточку анимацией вверх, как бы убирая ее из колоды. А вот пустое место надо заполнить, переместив карточки справа.

анимация удаления карточки из колоды

Сделать это оказалось просто, достаточно обновить x координату у карточки, x координатой предыдущей. Но сложность возникла когда я начал писать «защиту от дурака»… что если пользователь быстро и несколько раз нажмем на кнопку, и сработает повторный вызов удаления карточки? До сих пор мы делали анимацию по логике:

if (hide_tween) hide_tween.stop;

Все верно, но в нашем случае, анимацию удаления карточки или заполнения свободного места останавливать НЕЛЬЗЯ! Если остановить, то карточка может еще не заняла нужную позицию и при следующем удалении, нарушиться ее расположение в списке. Вот тут я сделал заключение: анимацию надо делать только на базе независимых фиксированных чисел.

Если координаты каждой карточки рассчитывать исходя из ее позиции в колоде, то даже при условии, что анимация будет прервана на середине, дает гарантию правильного позиционирования карточек при следующем обновлении.

var new_x = (index * child.width) + (index * 48);
this.game.add.tween(child).to({x: new_x}, 500, Phaser.Easing.Quartic.Out, true);

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

this.question_group.iterate('word_id', word_id, Phaser.Group.RETURN_CHILD, function(child) {
  if (!child.exists) return;
  child.exists = false;

  this.hide_question_tween = this.game.add.tween(child).to({y: - child.height}, 500, Phaser.Easing.Quartic.Out, true);
  this.hide_question_tween.onComplete.add(function(child) {
    this.question_group.remove(child, true);
  }, this, null, child);
}, this)

Теперь мне стало понятно зачем нужно свойство exists. Оно позволяет считать объект удаленным, пока он может быть еще визуально видимым из за tween анимации к примеру. Также обратите внимание, если вам надо выполнить код по завершении цепочки анимации, то достаточно дождаться завершения последней… именно по этому достаточно хранить объект tween последней анимации:

this.question_group.forEach(function(child) {
  ...
  this.move_question_tween = this.game.add.tween(child).to({x: new_x}, 500, Phaser.Easing.Quartic.Out, true);
}, this, true);

Дальше у меня в планах добавить анимированные кнопки ответа и решить проблему с прогрессом урока (зелено, красно, желтые кружочки в середине экрана). Спасибо за уделенное время и надеюсь информация в этой статье была вам полезна.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *