Найти тему
Наука от Rezerford

Phaser 3. Платформер своими руками. Часть 6.

Модульное программирование

Прежде чем двигаться вперёд по нашему курсу хотелось бы Вас немного научить принципам модульного программирования. Принципы CommonJS взяли на вооружение даже создатели компилятора JavaScript и уже давно внедрили основные принципы в шестую редакцию ECMAScript.

Что же такое модульное программирование в двух словах? Если объяснять на пальцах - это создание отдельных модулей, отвечающих за тот или иной функционал и подключение их (импортирование) в другие модули или классы. В ES6 модули представляют собой классы, как во всех классических языках программирования, базирующиеся на ООП (Объектно Ориентированное Программирование). Хотя никто не запрещает использовать функциональное программирование и на базе функций создавать свои модули. Во многих современных JavaScript фреймворках пропагандируют философию функционального программирования, например в React.

Давайте рассмотрим объявление класса и задание методов в JavaScript (напоминаю, что речь идёт о ES6):

Вначале мы экспортируем этот модуль, чтобы из внешнего мира его можно было импортировать. Затем после ключевого слова class мы даём имя классу, который хотим создать. После ключевого слова extends мы указываем от какого класса будет наследоваться данный класс. В нашем проекте мы практически не будем задействовать расширение пользовательских классов, хотя это иногда полезно и более гибко, наследоваться например от Phaser.GameObject.

В классе есть специальная функция constructor. Это обыкновенная функция-конструктор, которую мы писали ещё в JavaScript 2015 с большой буквы (вспоминаются далекие времена, когда JS был в зачаточном состоянии, но уже тогда подавал огромные надежды). Внутри конструктора надо обязательно вызывать специальную функцию super() при наследовании от родителя, иначе все свойства и методы не будут унаследованы. Здесь же можно задавать свойства экземпляра этого класса. В этом примере не приводится установка для объекта определённого метода и так далее. Нам все возможности ES6 не нужны, если заинтересовались "новым" JavaScript, прочитайте замечательную книгу Николаса Закаса "ECMAScript 6 для разработчиков" и будете гуру в ES6.

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

У нас на данный момент лишь один файл в src, это index.js. Давайте разобьём его на модули. Вообще, для чего нужны модули? Может Вы подумали так все делают, потому что это "модно". С одной стороны да, а с другой стороны, применяя модульную структуру Вы во-первых делаете Вашу программу более гибкой и легко расширяемой, во-вторых другим программистам, которые будут в будущем читать Ваш код, будет легче разобраться с Вашим кодом (кроме того, необходимо комментировать свой код, но только "без фанатизма"), да и Вам самим не надо скроллить "километровый" файл, чтобы найти ту часть кода, которая например отвечает за управление главным героем. Если Вы поместите весь код, который касается главного героя (мы назовём этот объект как player) в отдельный модуль, то Вы в мгновение ока найдете код и исправите, например, ошибки.

Давайте перепишем нашу входную точку index.js следующим образом:

И создадим на том же уровне файл platformer-scene.js, в котором будет размещён весь код основной игровой сцены:

Все строки здесь "до боли" знакомые, потому что мы всё это разобрали в предыдущих статьях. Заметьте, мы также сюда вставили добавление на сцену игрового фона. Единственное, что здесь уникальное - это

super('platformer-scene');

Мы в функцию super передали имя этой сцены, которое нам ещё очень пригодится в будущем, когда мы будем делать переходы между сценами (например переход на следующий уровень, или когда gamer проигрывает, надо перейти на отдельную сцену, где отображается Game Over, отображение сцены заставки и так далее).

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

По хорошему, стоит наверное весь наш загрузчик вынести в отдельный модуль, чтобы не загромождать platformer-scene.js. Создайте ещё один файл preload-helper.js и скопируйте следующий код

А в platformer-scene.js удалите строки с импортированием assets и в методе preload удалите уже не нужную здесь загрузку, и напишите

Да, и естественно импортируйте наш хелпер в шапке platformer-scene.js

P.S. Вот мы наконец, более менее научились модульному программированию и отныне будем разбивать на кусочки всю нашу игру. Надо создать новый вид объектов (например враги в игре), делаем новый класс, импортируем его в platformer-scene.js и порождаем новый объект врага, и вуаля - у нас уже новый персонаж в игре.
Это и многое другое Вы узнаете дальше, в нашем незабвенном цикле статей, посвящённых Phaser 3 и созданию игр.
P.S.#2 Мы могли бы расширятся от встроенных классов Phaser, таких как Phaser.Scene, Phaser.GameObject.Sprite, Phaser.Input и так далее, но мы так не будем делать, так как не такой уж огромный у нас проект, чтобы делать таким образом. В больших проектах наверное стоит расширяться и дополнять базовые встроенные классы и это будет верно.

Перейти к содержанию