[RMMV] Пишем свой первый плагин
Сегодня мой день был потрачен не зря, ибо мне удалось написать свой первый небольшой плагин для нового RPG Maker MV. Сразу скажу, что ни разу не профессионал, занимаюсь в свободное от кухни время и только только разбираюсь во всём это безобразии. Хотя есть некоторый опыт скриптоковыряния VX Ace, что конечно же мне помог и тут. В любом случае спешу поделится своими изысканиями и надеюсь они будут ещё полезны кому-нибудь.
Начать мне хотелось бы с редактора. Как вы уже наверное заметили, в отличии от VX Ace в MV своего редактора нет. Скрипты лежат в открытом виде и можете спокойно их редактировать в любом текстовом редакторе. В одном из видеоуроков человек порекомендовал brackets. Опыта у меня не много в подобного рода редакторах, но мне понравился. Особенно очень удобно когда начинаешь что-то писать, а тебе бац и сразу подсказки. Мелочь, а приятно. При желании можно выбрать удобную цветовую тему. Так что можете тоже попробовать совершенно бесплатно .
Для начала о том, что мы будем сегодня делать. Этот простой плагин рисует на экране небольшое окошко с иконкой и цифрой. Данные берутся из переменных (Variables) RPG Maker. А спомощью ключа (switch) можно включить или спрятать отображение данного окна. Теперь для чего? Например NPC даёт герою задание, что нужно собрать 20 шишек. Понятно, что задание не сильно увеселительное, но можно игроку немного скрасить жизнь. Отображая например цифрами, сколько ему ещё осталось мучится. Выглядит это примерно так:
Для того, что бы пользователь мог выбрать произвольные ячейки (Variables) и ключ (Switch) для отображения, мы выведем эти параметры в настройки нашего плагина. В принципе можно вынести и размер окна и его положение на экране, но мне бы пока не хотелось так всё сразу запутывать.
Итак, создадим новый файл ItemOnMap.js в папке нашего проекта, а именно js\plugins. Этого уже достаточно, что бы он уже появился в списке доступных плагинов, однако всё же стоит добавить его описание:
Здесь название нашего файла. Не могу сказать, что это нужно наверняка, но во всех плагинах под MV примерно такое-же оформление. Возможно система по этому определяет, что это именно наш плагин а ни чей-нибудь ещё.
А так это выглядит когда мы подключаем наш плагин:
Сначала создаём «копию» основной функции системы:
Затем заменяем её уже своей фунцией:
внутри которой вызываем настоящую, что бы ничего не поломалось:
И затем уже добавляем создание нашего окошка:
Ну и самое интересное. Окно появилось, и остаётся только вывести в него информацию:
Проверяем, что бы он не был равен 0, иначе будет ошибка.
Собственно на этом всё, остаётся только не забыть закончить главную функцию плагина:
Как видите ничего сложного почти нет. Хотя по правде говоря было очень не просто сходу разобраться со всем этим, и если бы не потраченные дни предварительного разбирания и ковыряния VX Ace, мне бы не удалось это всё сделать так «быстро». Однако надо сказать огромное спасибо авторам, что так же как в VX Ace, RMMV название функций и переменных очень схожи, что конечно хоть и не сильно, но всё же упрощает написание плагинов под RMMV.
Если вдруг будут какие-то вопросы, постараюсь в меру своих сил ответить
p.s. огромное спасибо всем кто мне помогал и помогает разбираться с премудростями RPG Maker, как здесь на форуме, так и в нашем горячо любимом чатике. Как видите мои глупые вопросы наконец вылились во что-то если не серьёзное, так во что-то не плохое это точно.
Полный текст плагина «ItemOnMap.js:»
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
... и почему она нам показывает рожи и подмигивает нам.
Это называется "самовызываемой анонимной функцией".
function() { ... } - это функция. У неё нет имени, иначе было бы function <имя> () { ... }, поэтому она анонимная. Она заключена в скобки: (function() { ... }). После скобок добавлены ещё две скобки (), которые вызывают предыдущий член выражения. Поскольку предыдущий член выражения - это функция, то вызывается функция. Но если бы она сама не была заключена в скобки, то строчка не воспринималась бы как выражение. Поскольку функция ничему не присваивается и имени у неё нет, то, отработав, она перестаёт существовать. Завершающая точка с запятой нужна для обозначения конца строчки (хотя в принципе её можно и не ставить).
Зачем нужна эта страшная конструкция? Почему она настолько обязательна, что с неё начинаются почти все плагины?
Дело в том, что первоначально Яваскрипт на веб-страницах выполнял очень ограниченную роль и обходился без заморочек - включая такую заморочку как область видимости переменных. Поэтому если без такой обёртки в своём плагине написать, например, var parameters = PluginManager.parameters('ItemOnMap'), то это создаст глобальную переменную parameters, содержащую параметры плагина ItemOnMap. Все переменные, объявленные с var вне функции объявляются в глобальном пространстве. Поэтому-то это и опасно: так можно либо переписать нужную другому модулю переменную, либо же, наоборот, другой модуль может переписать вашу. Единственный способ "защитить" переменные в Яваскрипте был использование такой вот анонимной функции. Переменные, объявленные внутри функции снаружи не видны и ничего не затирают... Зато код внутри функции прекрасно их видит, даже код функций, создаваемых внутри анонимной функции.
Короче! В Яваскрипте 6, который используется Мейкером MV, это больше не требуется. Сообщество Яваскрипта не хотело никого заставлять пользоваться эзотерической конструкцией, они просто не подумали, что области видимости могли понадобиться. А теперь, когда стало ясно, что это так, они добавили этот функционал в язык.
Вот как можно сделать вместо самовызываемой анонимной функции:
Код Мейкера и многих плагинов не использует этого по разным причинам: по привычке, из-за незнания (Яваскрипт 6 сравнительно новый), из-за опасения, что среда будет поддерживать только 5-ю часть... Тем не менее, сейчас Яваскрипт 6 вошёл в широкое пользование и поэтому поддерживается в MV, так что кому больше нравится без анонимной функции - может спокойно без неё обойтись.
Пояснения по неясным местам
Честно не знаю, зачем тут написано Number, но в других скриптах сделано так же, так что видимо так надо
Когда пользователь вводит параметры плагина, он не может указать, вводит он число или строку. 300 - это число триста или это название фильма? Допустим, Яваскрипту придётся складывать два параметра, не зная, что они из себя представляют: 300+007 - это будет 307 или строка '300007'? Поэтому когда нужно получить из параметра число, его нужно сделать таковым в явном виде. В Яваскрипте есть несколько способов преобразовать строку в число, например, parseInt('2+2') даёт 4, а Number('2+2') более прямолинейный и возвратит NaN (Not a Number - "не число", потому что есть лишние символы).
[hr]
Каждая функция в Яваскрипте - это объект (так же, как в Руби). И у этих объектов-функций есть такие методы как call и apply. Здесь вызывается метод apply у функции, содержащейся в this.initialize. Метод call в качестве первого параметра принимает объект, который в рамках исполнения функции будет считаться за this, а далее можно перечислить аргументы. Метод apply делает то же самое, но принимает не открытый список аргументов, а массив аргументов. Например, это одно и то же (во втором случае квадратные скобки обозначают запись массива):
Ну а arguments - в рамках выполнения метода особый массивоподобный объект, содержащий все аргументы. Если нужно вызвать метод с такими же аргументами и контекстом (this), с которыми был вызван данный, пишут:
Таким образом в Яваскрипте вплоть до 5-й версии производилось наследование. Классы в Яваскрипте организовывались традиционно так:
В Яваскрипте 6-й версии уже есть привычный синтаксис объявления и описания классов . Кроме того, многие кодеры на Яваскрипте используют самодельные функции, позволяющие унаследовать один класс от другого и даже добавить до кучи дополнительные наборы черт, например . После этого достаточно написать
Чтобы класс НазваниеКласса был дочерним к НазваниеРодительскогоКласса и в дополнение имел свойства из Плюшка и Плюшка2. Уверена, где-нибудь в Yanfly Core должен быть такой метод.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
EvilCat пишет: Хочется объяснить
Спасибо огромное!
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
EvilCat пишет: Хочется объяснить
Профессиональный подход, лёгкий слог и ни миллиграмма воды. Крутое объяснение...
Ленивый волчонок с большими амбициями
Рассказ "Рождение мага" , периодически обновляется
РПГ История Егеря . Основной текущий проект.
Покой нальёт
Людям всем, и сбежит морок...
Но пока в нём живут,
Но пока в нём растут,
Не видать нам вины
Как неба в крови.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Дело в том, что Руби - это преимущественно классовый язык. В нём объявляются классы, создаются объекты-экземпляры классов, а некоторые классы являются наследниками других классов.
А Яваскрипт - это преимущественно прототипный язык. В нём у объектов есть не класс, а прототип, схема. Когда у объекта требуешь "выполни метод Х", то объект сначала ищет среди собственных, индивидуальных свойств, а если не находит - то ищет в прототипе. В классовых языках объект ищет метод Х в объявлении класса. У прототипных языков тоже есть наследование, поскольку у прототипов могут быть прототипы (именно эту роль выполняет строчка НазваниеКласса.prototype = Object.create(НазваниеРодительскогоКласса.prototype) - она создаёт протитип класса так, чтобы у этого прототипа был собственный прототип, такой же, как у родительского класса. Если объект не нашёл метод Х ни у себя, ни в своём прототипе, то поиск продолжается в прототипе прототипа, и далее по всей цепочке прототипов. Так же, как в классовых языках метод ищется сначала в объявлении класса, а затем - в объявлении родительского класса, а затем - в родительском классе родительского класса и так далее.
Но Руби и Яваскрипт не принципиально отличаются. У Руби тоже можно редактировать собственные свойства объекта и даже его "прототип" (когда пишут class << object и затем задают изменения). У Яваскрипта есть возможность узнать принадлежность объекта к классу через оператор instanceof: он проверяет, есть ли в цепочке прототипов объекта прототип этого класса. А современный Яваскрипт 6-й версии даже позволяет записывать объявление класса без всех этих Object.create(что-то-там.prototype).
Статья Википедии
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
lindar пишет: Подскажите, а что и куда нужно добавить чтобы окно отображалось и на экране битвы?
Уж не знаю зачем вам это понадобилось
Но достаточно перед строчкой «function ItemOnMap() {»
Добавить, по аналогии с «_Scene_Map_createAllWindows»:
Правда появятся проблемы:
Наше окошко будет перекрывать системные сообщения о битве. Поэтому нужно указать где-то другое место.
Буду делать в виде отдельного скрипта добавлю в настройки: Отображать ли окно во время битвы и координаты на экране.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
lindar пишет: Мне исключительно с целью отслеживания переменных)
Хм, ну да, F9 во время битвы не работает,…
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Мдааа,… перечитываю сейчас и понимаю, как же все по детски написано
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
DK пишет: Было бы хуже, если бы ты посчитала, что все нормально. А если ты видишь, что можно было написать лучше, значит ты улучшила свои навыки
Ну это понятно
Собственно осознание и переработка вылились в обновлённую статью.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
