Я потерял много времени, пытаясь найти решение — как осуществить обмен данными между vue.js и Phaser. Этот вопрос заинтересовал меня, т.к. все что не касается игровой механики, намного удобнее и быстрее делать вне игрового движка, например: авторизация и вывод игровой статистики.
Поскольку у меня есть некоторый опыт работы с Vue.js, то я решил использовать его для этих целей.
Поскольку Phaser работает как отдельное приложение, то вы не можете передавать или извлекать информацию из него, для этого вам потребуется немного пофантазировать.
Я не мог найти, как передать какую-то переменную в Phaser через процесс инициализации игры или как достучаться из него во Vue. Казалось бы, у обоих инструментов есть большие комьюнити, но я нашел лишь много подобных вопросов на форумах или под видео на YouTube — и все они либо без ответа, либо содержат не рабочие или не полноценные ответы. Я решил написать эту короткую статью, потому что надеюсь помочь другим энтузиастам, которые находятся в самом начале пути.
Для того чтобы Phaser в целом запустить внутри Vue, я использовал проект -ion-phaser(статья).
Далее пошаговая инструкция:
Создаем пустой проект. (Начнем с нуля, для того чтоб мы были на одной странице)
vue create my-awesome-project
cd my-awesome-project
yarn add phaser vuex @ion-phaser/core
Настраиваем Phaser
Нужно добавить 2 строчки в main.js
import { defineCustomElements as defineIonPhaser } from '@ion-phaser/core/loader'
defineIonPhaser(window);
Также нужно задать конфигурацию загрузки ассетов в файле /vue.config.js.
Создаем файл хранилища - vuex.
Разместим его в - /src/store/index.js
Подключаем его в приложение Vue:
// /src/main.js
import store from './store'
....
....
createApp(App)
.use(store)
.mount('#app');
Добавим игровую логику:
Для примера я взял код с официального сайта Phaser.
Подключаем и конфигурируем игру в компоненте Vue - /src/game/Game.vue
В этом файле стоит обратить внимание на строки 44-51. Именно тут происходит прослушивание изменений состояния переменной count.
Само же изменение значения мы произведем внутри игровой логики. Будем начислять очки за каждую собранную звезду)
Разместим код игрового уровня в файле - /src/game/scenes/PlayScene.js
Файл довольно длинный и содержит лишь адаптированную копию кода, поэтому рассмотрим лишь отрывок который добавил автор:
import store from "@/store";
/*********/
collectStar(player, star) {
star.disableBody(true, true);
store.commit('increment');
}
Первая строка внедряет vuex в игровой код.
На строке 6 - мы производим вызов мутирующего метода - increment. Собрали звезду - добавили очко.
Протестируем то что мы накодили.
Запускаем приложение:
yarn serve
На экране мы должны увидеть следующую картинку:
Игровой персонаж ударяясь головой об платформу вызывает появление звездочек, после того как он соберет 5ть - будет выведено сообщение о выигрыше средствами Vue.js.
Подводя итоги. В статье были рассмотрено следующее:
Интеграция Phaser во Vue.js
Подключение и настройка хранилища Vuex
Обмен состоянием между Vue.js и Phaser в обе стороны.
Ссылка на репозиторий с исходным кодом.
PS: Мой основной язык РНР, но для общего развития последнее время изучаю и серверный javascript. Самым веселым способом изучения, мне показалось - создать многопользовательскую сетевую игру. Если вам также интересна данная тема - буду рад пообщаться и покодить вместе :-)
Vadiok
1-й момент: вместо того, чтобы следить за
$store.state.count
лучше использовать computed свойство.2-й момент: вы параметры игры передаете из data, делая их реактивными, в т.ч. все, что формируется в Scenes. С т.з. производительности очень так себе идея. Если использовать Composition API, то можно избежать реактивности. Либо можно параметры передавать также как computed свойство, тогда Vue вроде как тоже не будет вешать реактивность на все, что внутри объекта.
Desprit
В дополнении к этому я бы очень советовал использовать Pinia вместо Vuex. Она на Typescript и помогает избежать багов, связанных с типами данных.
Vadiok
Да. Но в примере автора можно вообще просто переменную вне компонента через ref создать и с ней работать.
khudyakv
в pinia еще и мутаций больше нет
Alexandroppolus
Чего-то вроде observable.ref (из МобХ) так и не появилось?
Vadiok
Если говорить о Vue, а не о Vuex, то в composition API аналогом будет shallowRef. Хотя в примере ддя конфига, передаваемого в Phaser даже такая реактивность не требуется.
Yurich_T
Тут вместо вочера лучше использовать сеттер компьютед переменной.
volkovnd
На саом деле на счёт computed св-ва не соглашусь, поскольку состояние с количеством хранится внутри store, поэтому было бы логичнее хранить в геттере store св-во isWin, которое расчитывалось исходя от count и уже непосредственно его пробрасывать на компоненты
Vadiok
Наверное, да. Тут в целом код такой, что вместо того, чтобы его рефакторинг, лучше заново все написать.
VladVerpeta Автор
Спасибо за комментарии, все они уместные)
Кто-то даже сделал форк на гитхабе и воплотил все описанные выше комментарии в жизнь)
---
Не думаю что переданный конфиг в data - хоть как то замедлит игровой процесс, так же как и выбор как следить за стораджом(watch или computed), как по мне это уже больше экономия на спичках и вкусовщина.
----
Напомню что, цель статьи была - показать как легко и просто можно реализовать обмен данными между Vue и игрой на Phaser