Войти на сайт
×
ТЕМА: [RMMV] Пишем свой первый плагин v2.0 [Часть 1]
[RMMV] Пишем свой первый плагин v2.0 [Часть 1] 7 года 1 нед. назад #100326
|
Как быстро летит время, казалось бы только вчера вышел RPG Maker MV, а уже пролетело 2 года За это время много что изменилось, выходили новые версии самого редактора, поменялось много чего в самом движке MV, а главное за эти два года мои личные знания тоже изменились от «ну эт вот тут такая штука» до «класс наследует свойства родителя».
Перечитав свой первый урок («[RMMV] Пишем свой первый плагин»), мне стало немного стыдно. Многое написано слишком уж по детски, а многие вопросы вообще были не освещены или описаны в стиле «ну эт вот тут так надо». Спустя некоторое время мне захотелось немного переработать написанный материал. Но не пугайтесь, я не буду заменять всё слишком заумными словами, а просто постараюсь выражаться более грамотно, ну и по возможности более подробно. Начну пожалуй с редакторов. В своё время мне понравился редактор «Brackets». Не скажу, что он плох, но бывает немного порой медлительным. Как альтернативу стоит упомянуть как минимум «Visual Studio Code» и «Sublime Text». Не буду на них особо заострять внимание, скажу лишь то, что в «Visual Studio Code» очень большая база всевозможных плагинов и дополнений (выпадающие подсказки, отладка итд), а «Sublime Text» на сегодняшний день однозначно самый быстрый редактор, с не менее большими возможностями. При желании я думаю вы и сами с ними разберётесь, в крайнем случае можно писать скрипты и в обычном блокноте Но вернёмся к RPG Maker MV. Как пример мы будем рассматривать всё тот же плагин отображения предметов на экране «ItemsOnMap». С недавних пор в RPG Maker MV немного изменилось окно отображения параметров плагинов и мы рассмотрим это более подробно всё. Начнём с самого простого, с оформления нашего нового скрипта. Для этого создадим новый файл «MUR_ItemsOnMap_2.js» в папке нашего проекта «js/plugins/MUR_ItemsOnMap_2.js» с таким вот минимальным кодом: //=============================================================================
// MUR Items On Map v2.0
//=============================================================================
/*:
* @plugindesc Show Items On Map v2.0
* @author Mur
*
*/
(function() {
})(); Этого вполне достаточно, что бы наш плагин вот так отображался: Пройдёмся более детально по частям: //=============================================================================
// MUR Items On Map v2.0
//============================================================================= /*:
* @plugindesc Show Items On Map v2.0
* @author Mur
*
*/ (function() {
})(); Но вернёмся к описанию плагина. У нас имеется два поля @plugindesc и @author. Как не трудно догадаться, первое это описание нашего плагина, а второе указание его автора. Вы может там написать абсолютно любой текст, на любом языке, при условии, что ваш файл сохранён в кодировке UTF-8(современные редакторы предлагают это делать про умолчанию). Однако есть немного не приятный момент. Дело в том, что зарубежные пользователи скорее всего не смогут понять, о чём речь. Для того, что бы сделать наш плагин интернациональными, по крайней мере ту часть которая отвечает за описание, мы несколько усложним описание плагина. А именно сделаем две секции описаний, на английском языке и на русском: //=============================================================================
// MUR Items On Map v2.0
//=============================================================================
/*:en
* @plugindesc Show Items On Map v2.0
* @author Mur
*
*/
/*:ru
* @plugindesc Показать предметы на карте v2.0
* @author Mur
*
*/
(function() {
})(); Теперь, если мы запустим английскую версию RPG Maker MV, то получим описание как на скриншоте выше, а если запустим русскую версию, то соответственно описание будет на русском языке: Теперь рассмотрим ещё одну часть описания плагина, а именно «Help», или как в русской версии указано «Помощь». Для того что бы разместить в информацию в этом блоке достаточно добавить в наш скрипт ещё одно поле @help: /*:ru
* @plugindesc Показать предметы на карте v2.0
* @author Mur
* @help это пример описания помощи по настройке нашего скрипта «Show Items On Map»
* Это вторая строка описания
* Это третья строка описания
* Это четвёртая строка описания
* Это пятая строка описания
*
*/ Ограничений на количество строк помощи нет, и если их будет достаточно много, сбоку просто появится полоса прокрутки(scrollbar). С разделом «Помощь» разобрались и теперь самое время перейти к параметрам плагина. Но для начала я напомню для тех кто не в курсе, что в составе RPG Maker MV есть такая очень важная и очень удобная штука — отладчик. Вызывается он нажатием клавиши F8 во время запуска игры из редактора. Более подробно отладчик мы рассмотрим в другой раз, а сейчас мне бы хотелось остановится на вкладке «Console». Сюда будут сыпаться всякого рода ошибки, если они будут, а так же можно сюда выводить отладочную информацию. Например если в основную функцию мы добавим такой код, (function() {
console.log("Hello world!");
})(); то в закладке «Console» мы увидим своё сообщение. А если попробуем вызвать несуществующую функцию, например «abyrvalg()»: (function() {
abyrvalg();
})(); то получим соответствующее сообщение об ошибке: В правой части указано имя файла из которого произошел вызов(или случилась ошибка), а после двоеточия указан номер строки в которой это случилось. Но вернёмся к настройкам плагина. В отличии от предыдущей версии, мы его немного усложним для программирования, но упростим настройку для пользователя. Поскольку наш плагин будет отображать количество предметов которое есть в наличии у игрока, то логично будет запросить эти данные у системы (а точнее у инвентаря). Но в любом случае нам нужно вынести в настройки номер(идентификатор/ID) предмета данные о котором мы хотим отображать. Номер предмета(или его ID) указан в рядом с названием предмета в «Базе данных» в закладке «Предметы». Дальше нам нужно сделать возможность включать и отключать отображение нашего окошка. Это можно сделать двумя способами: как и в предыдущей версии урока с помощью ключа(switch), а так же с помощью вызова команды плагина. Мы рассмотрим оба способа, но пока зарезервируем в настройках параметр с номером ключа. Различные ситуации требуют различного положения окна на экране, для этого мы заведём ещё два параметра, это положение на экране по оси X и положение на экране по оси Y. Ну и последним параметром который мы зададим, отображать ли наше окошко во время диалогов. Например, если мы зададим координаты отображения в нижней части экрана, то велика возможность наложения окна сообщений и окна с нашими данными. Итого у нас получилось параметров:
Для того, что бы описать какой-либо параметр используются три ключевых слова, так же начинающихся с символа @: это @param — наше название параметра, @default — значение по умолчанию, а так же параметр @desc (описание), содержмое которого теперь отображается в окне где задаётся значения переменной. Так же можно описать подробности в секции @help. Собрав всё воедино, получим такой код заголовка: /*:ru
* @plugindesc Показать предметы на карте v2.0
* @author Mur
* @help Item ID — номер предмета в базе данных
* Show switch ID — номер переключателя разрешающего отображение
* Position X — положение окна на экране по оси X
* Position Y — положение окна на экране по оси Y
* Enabled while message — показывать ли при отображении окна сообщений
*
* @param Item ID
* @desc номер предмета в базе данных (по умолчанию 1)
* @default 1
*
* @param Show switch ID
* @desc номер переключателя разрешающего отображение (по умолчанию 1)
* @default 1
*
* @param Position X
* @desc положение окна на экране по оси X (по умолчанию 10)
* @default 10
*
* @param Position Y
* @desc положение окна на экране по оси Y (по умолчанию 10)
* @default 10
*
* @param Enabled while message
* @desc message — показывать ли при отображении окна сообщений (по умолчанию true)
* @default true
*/ А при настройке плагина это будет выглядеть вот так: Тоже самое нужно повторить, но уже для англоязычной секции (*:en). Для того, что бы в нашем коде получить доступ к параметрам плагина, мы должны обратится к менеджеру плагинов и в качестве параметра передать имя файла плагина, но безе расширения js: var params = PluginManager.parameters('MUR_ItemsOnMap_2'); Далее, уже у массива params мы можем запросить интересующие значение: var itemId = params['Item ID']; Но есть один нюанс. Все значения представляют из себя строку текста и для того, что бы получить число или логический тип, нам придётся сделать дополнительное преобразования. Например для того, что бы наша переменная содержала число, а не строку, необходимо вызвать функцию Number. И в качестве параметров передать строку: var itemId = Number(params['Item ID']);
var showSwitchID = Number(params['Show switch ID']);
var positionX = Number(params['Position X']);
var positionY = Number(params['Position Y']); Для того, что бы получить логическое значение мы сравним строку на наличие слова true (истина) и если оно указано, то наша переменная получит логическое значение — true: var enableWhileMessage = params['Enabled while message'].toUpperCase() == "TRUE" ? true : false; Какая страшная и непонятная конструкция скажете вы и будете правы, но давайте рассмотрим её подробнее: В JavaScript со строкой можно делать различные преобразования: разрезать, заменять части и другие операции. В данном примере метод «.toUpperCase()» делает все буквы большими. Например, если мы присвоим значение переменной a, var a = "abc"; а затем вызовем метод «.toUpperCase()», var b = a.toUpperCase(); Теперь для чего нам это нужно? Дело в том, что мы не знаем как пользователь напишет значение, он может написать «true», а может и «TRUE», а может и вообще «tRuE» и в том, и в другом, и в третьем случае это будет подразумеваться одно и тоже, но строки будут не равны. Именно для этого мы приводим к единому виду «TRUE». Что же касается второй «страшной» конструкции, это сокращённая форма условия «If». Её можно записать в виде: var enableWhileMessage;
if (params['Enabled while message'].toUpperCase() == "TRUE") {
enableWhileMessage = true;
} else {
enableWhileMessage = false;
} Согласитесь очень громоздкая конструкция для задания значения одной переменной. Поэтому её часто заменяют такой: переменная = условие истины ? значение если истина : значение если ложно Теперь, для отладки, мы можем вывести в «Console» наши значения переменных и проверить, что всё в порядке: //=============================================================================
// MUR Items On Map v2.0
//=============================================================================
/*:
* @plugindesc Показать предметы на карте v2.0
* @author Mur
* @help Item ID — номер предмета в базе данных
* Show switch ID — номер переключателя разрешающего отображение
* Position X — положение окна на экране по оси X
* Position Y — положение окна на экране по оси Y
* Enabled while message — показывать ли при отображении окна сообщений
*
* @param Item ID
* @desc номер предмета в базе данных (по умолчанию 1)
* @default 1
*
* @param Show switch ID
* @desc номер переключателя разрешающего отображение (по умолчанию 1)
* @default 1
*
* @param Position X
* @desc положение окна на экране по оси X (по умолчанию 10)
* @default 10
*
* @param Position Y
* @desc положение окна на экране по оси Y (по умолчанию 10)
* @default 10
*
* @param Enabled while message
* @desc message — показывать ли при отображении окна сообщений (по умолчанию true)
* @default true
*/
(function() {
var params = PluginManager.parameters('MUR_ItemsOnMap_2');
var itemId = Number(params["Item ID"]);
var showSwitchID = Number(params['Show switch ID']);
var positionX = Number(params['Position X']);
var positionY = Number(params['Position Y']);
var enableWhileMessage = params['Enabled while message'].toUpperCase() == "TRUE" ? true : false;
console.log("itemId=" + itemId);
console.log("showSwitchID=" + showSwitchID);
console.log("positionX=" + positionX);
console.log("positionY=" + positionY);
console.log("enableWhileMessage=" + enableWhileMessage);
})(); Я намерянно здесь сокращу только русскоязычную часть, дабы не удилять и без того очень длинную статью. Убедившись, что у нас всё отлично работает и мы забираем значения настроек правильно, мы неожиданно можем столкнуться с некоторыеми трудностями. К сожалению программисты зачастую бывают очень ленивы и забывают, что пользоваться плодами их творчества зачастую будут люди далёкие от программирования. Кроме того никто не застрахован от ошибок, очепяток итд. Что будет если мы вместо позиции X, равной 10, напишем в настройках плагина какую-нибудь билиберду в виде текста «АБЫРВАЛГ!». Вы думаете хоть кто-нибудь проверяет в своих плагинах, а что собственно туда вводят пользователи? Конечно нет! И как и следовало ожидать, наш плагин получит ошибочное значение NaN (Not A Number - не является числом) и при дальнейшей попытке ипользовать значение переменной positionX вылетит с ошибкой, а бедный пользователь будет возмущаться, что ваш плагин не работает. Как же в такой ситуации быть? Понятно, что всех критических ситуаций не учесть, но в данном случае можно проверить значения переменных на отстувие значение NaN и вывести предупреждающее окно. Об этом мы поговорим во второй части, а пока ограничимся предупреждением в окно консоли: if (isNaN(itemId) || isNaN(showSwitchID) || isNaN(positionX) || isNaN(positionY)) {
console.error('MUR Items On Map: Не верно заданы параметры плагина');
} Уже закончив статью и перечитывая материал ещё раз, меня заинтересовала вкладка «Текст» в окне, где задаётся значение параметра. Мой пытливый ум сразу же решил проверить, а не может ли быть в этом месте другой тип? Например числовой? И как показала практика достаточно задать дополнительное поле вида «@type number», что бы стало возможным задавать цифровое значение. Но на этом моя тушка не успокоилась и стала экспериментировать ещё. Опытным путём выяснилось, что если задать тип «@type boolean» можно будет задать значения в виде радиобатонов (Да/Нет). Но и это ещё не всё! Если задать например «@type item», то будет выпадающий список с предметами, где результатом будет ID выбранного предмета. А если задать «@type switch», то по клику откроется окошко со списком ключей и можно задать номер ключа. Как теперь это выглядит в коде: /*:
* @plugindesc Показать предметы на карте v2.0
* @author Mur
* @help Item ID — номер предмета в базе данных
* Show switch ID — номер переключателя разрешающего отображение
* Position X — положение окна на экране по оси X
* Position Y — положение окна на экране по оси Y
* Enabled while message — показывать ли при отображении окна сообщений
*
* @param Item ID
* @desc номер предмета в базе данных (по умолчанию 1)
* @default 1
* @type item
*
* @param Show switch ID
* @desc номер переключателя разрешающего отображение (по умолчанию 1)
* @default 1
* @type switch
*
* @param Position X
* @desc положение окна на экране по оси X (по умолчанию 10)
* @default 10
* @type number
*
* @param Position Y
* @desc положение окна на экране по оси Y (по умолчанию 10)
* @default 10
* @type number
*
* @param Enabled while message
* @desc показывать ли при отображении окна сообщений (по умолчанию true)
* @default true
* @type boolean
*/ И как это выглядит визуально: Более подробное изучение данного вопроса выявило, что начиная с версии 1.5.0 появились дополнительные ключевые слова в параметрах. Если у вашего плагина слишком много параметров, то их можно сгруппировать объединив командой @parent. В нашем примере мы можем объединить X и Y позицию на экране. Для этого немного изменим структуру параметров: * @param Position
*
* @param X
* @parent Position
* @desc положение окна на экране по оси X (по умолчанию 10)
* @default 10
* @type number
*
* @param Y
* @parent Position
* @desc положение окна на экране по оси Y (по умолчанию 10)
* @default 10
* @type number Хочу так же обратить ваше внимание, что в этом случае немного измениться и код доступа к этим параметрам: var positionX = Number(params['X']);
var positionY = Number(params['Y']); Так же появилась ещё одна не менее важная конструкция это @text. Она позволяет выводить вместо названия параметра на английском языке произвольный текст. Например: * @param Position
* @text Положение окна на экране
*
* @param X
* @parent Position
* @text Координата X
* @desc положение окна на экране по оси X (по умолчанию 10)
* @default 10
* @type number
*
* @param Y
* @parent Position
* @text Координата Y
* @desc положение окна на экране по оси Y (по умолчанию 10)
* @default 10
* @type number Теперь вместо «Position» у нас будет выводится «Положение окна на экране», а вместо «X» — «Координата X». Примечательно, что для каждого языка можно задать свой текст и у нас решается проблема перевода названий параметров на другие языки. Про параметр @type было уже сказано выше, дополню лишь, что могут быть ещё и другие типы: Например, с помощью «@type note», можно задать много строчный текст. Если указать @type как number, то можно дополнительно ограничить максимальное и минимальное значение, с помощью конструкций @max и @min. А с помощью конструкции @decimals можно указать количество цифр после запятой(точки), если необходимо задать более число с плавающей точкой; С помощью «@type file» можно сделать возможным выбор файла на диске, причём в параметре @dir можно указать путь где его искать. Например «@dir audio/bgm/» позволит выбрать аудио файл в папке «audio/bgm/». Так же есть ещё один дополнительный параметр @require. Если его значение установлено в 1, то при экспорте проекта, выбранный файл будет так же включён. Помимо ранее рассмотренных @type switch и @type item, есть ещё возможность задать следующие: @type animation — выбрать анимацию, в значении будет ID (номер); @type actor — выбрать актёра(персонажа), в значении будет ID (номер); @type class — выбрать класс, в значении будет ID (номер); @type skill — выбрать навык, в значении будет ID (номер); @type item — выбрать предмет, в значении будет ID (номер); @type weapon — выбрать оружие, в значении будет ID (номер); @type armor — выбрать броню, в значении будет ID (номер); @type enemy — выбрать противника, в значении будет ID (номер); @type troop — выбрать сцена боя, в значении будет ID (номер); @type state — выбрать состояние, в значении будет ID (номер); @type tileset — выбрать набор тайлов, в значении будет ID (номер); @type common_event — выбрать общее событие, в значении будет ID (номер); @type switch — выбрать переключатель, в значении будет ID (номер); @type variable — выбрать переменную, в значении будет ID (номер); Так же в этих параметрах можно указать «@require 1» и тогда при экспорте проекта данный ресурс будет учтён. В при указании типа @type boolean, так же можно ещё переопределить название пунктов с помощью @on и @off. Например в нашем случае можно локализовать так: * @param Enabled while message
* @text Показывать ли окно
* @desc показывать ли при отображении окна сообщений (по умолчанию true)
* @default true
* @type boolean
* @on Отображать всегда
* @off Скрыто при сообщениях Так же можно создать и более сложные конструкции, например с помощью «@type select», «@option» и «@value», можно создать выпадающий список: * @type select
* @option XP
* @value 1.0
* @option VX
* @value 2.0
* @option VX Ace
* @value 2.1
* @option MV
* @value 3.0 В @option задаётся название которое будет отображаться в списке, а в @value указывается значение которые сохранится в параметрах, при выборе этого пункта. Если есть необходимость задать значение как в текстовом виде, так и выбрать готовое значение из списка, пригодится конструкция в виде «@type combo» и «@option»: * @type combo
* @option XP
* @option VX
* @option VX Ace
* @option MV Конструкция такая же как и в случае с @type select. Если необходимо указать или выбрать несколько значений параметра, то можно указать список(List) в виде: @type text[] — массив строк @type note[] — массив много строчных значений @type number[] — массив чисел @type variable[] — массив переменных @type item[] — массив предметов @type combo[] — массив выпадающих списков @type file[] — массив файлов @type struct<Anything>[] — массив произвольных структур Так же стоит учитывать, что при получении значения такого параметра, на выходе будет уже не строка, а массив нескольких значений. Ну и последнее это возможность создавать свои, произвольные структуры: /*~struct~ItemAward:
* @param Item
* @type item
*
* @param Count
* @type number
* @min 1
* @max 99
* @default 1
*/ Последние конструкции здесь приведены больше как пример возможностей и требуют в будущем отдельного рассмотрения. Ну в заключении как теперь выглядит финальная, на данном этапе, версия плагина: //=============================================================================
// MUR Items On Map v2.0
//=============================================================================
/*:
* @plugindesc Показать предметы на карте v2.0
* @author Mur
* @help Item ID — номер предмета в базе данных
* Show switch ID — номер переключателя разрешающего отображение
* Position X — положение окна на экране по оси X
* Position Y — положение окна на экране по оси Y
* Enabled while message — показывать ли при отображении окна сообщений
*
* @param Item ID
* @text Номер предмета
* @desc номер предмета в базе данных (по умолчанию 1)
* @default 1
* @type item
*
* @param Show switch ID
* @text Номер переключателя
* @desc номер переключателя разрешающего отображение (по умолчанию 1)
* @default 1
* @type switch
*
* @param Position
* @text Положение окна на экране
*
* @param X
* @parent Position
* @text Координата X
* @desc положение окна на экране по оси X (по умолчанию 10)
* @default 10
* @min 0
* @max 800
* @type number
*
* @param Y
* @parent Position
* @text Координата Y
* @desc положение окна на экране по оси Y (по умолчанию 10)
* @default 10
* @type number
*
* @param Enabled while message
* @text Показывать ли окно
* @desc показывать ли при отображении окна сообщений (по умолчанию true)
* @default true
* @type boolean
* @on Отображать всегда
* @off Скрыто при сообщениях
*
*/
(function() {
var params = PluginManager.parameters('MUR_ItemsOnMap_2');
var itemId = Number(params["Item ID"]);
var showSwitchID = Number(params['Show switch ID']);
var positionX = Number(['X']);
var positionY = Number(['Y']);
var enableWhileMessage = params['Enabled while message'].toUpperCase() == "TRUE" ? true : false;
if (isNaN(itemId) || isNaN(showSwitchID) || isNaN(positionX) || isNaN(positionY)) {
console.error('MUR Items On Map: Не верно заданы параметры плагина');
} else {
console.log("itemId=" + itemId);
console.log("showSwitchID=" + showSwitchID);
console.log("positionX=" + positionX);
console.log("positionY=" + positionY);
console.log("enableWhileMessage=" + enableWhileMessage);
}
})(); И как это выглядит визуально: В заключении хочу обратить ваше внимание, что не смотря на возможность как-то «облагородить» вводимые пользователем данные, всё так же осталась актуальна проблема ввода некорректных данных на вкладке «Текст». Например можно всё так же в координатах задать текстовое значение, а при получении данных получить ошибку в виде NaN(Not A Number). Из-за большого объёма, обилия примеров и ограниченности форума на количество картинок в одном посте, обзор кодовой части я перенесу во вторую часть. p.s. Надеюсь вас не слишком утомила данная «простыня». |
Последнее редактирование: 6 года 10 мес. назад от Mur.
Администратор запретил публиковать записи гостям.
|
[RMMV] Пишем свой первый плагин v2.0 [Часть 1] 7 года 1 нед. назад #100329
|
Во-первых, учился на твоих первых двух уроках! Ибо тот твой код был действительно понятен, а код например ДК довольно сложен для моего неокрепшего ума.
Во-вторых, было б здорово услышать всякие облегчающие жизнь фишечки относительно программ. Мне приходит на ум только одна - есть такие волшебные штуки как "сниппеты". При помощи них любую функцию или мукерскую переменную можно "писать" двумя нажатиями. Предварительно настроив большинство переменных мукера такие как "гейм_вариаблс" и прочее, можно даже не запоминая их и не копируя "писать их" любым понятным для вас словом, после этого нажав "tab". На данный момент использую "саблайм текст 3" и при вводе "icon" у меня пишется функция показа картинки битмапой, HP определенного члена партии - hp0, hp1 и т.д., а при вводе "mv" пишется фундамент плагина - его название,описание,параметры. Очень удобно и здорово экономит время,учитывая мой 2-3-часовой сон |
Администратор запретил публиковать записи гостям.
|
[RMMV] Пишем свой первый плагин v2.0 [Часть 1] 7 года 1 нед. назад #100330
|
yuryol пишет:
Во-первых, учился на твоих первых двух уроках! Ибо тот твой код был действительно понятен, а код например ДК довольно сложен для моего неокрепшего ума. Спасибо на добром слове, постараюсь не разочаровать и в будущем. yuryol пишет: Во-вторых, было б здорово услышать всякие облегчающие жизнь фишечки относительно программ. По поводу снипетов я догадываюсь о чём речь, постараюсь разобраться в этом вопросе и по возможности описать тоже. |
Администратор запретил публиковать записи гостям.
|
[RMMV] Пишем свой первый плагин v2.0 [Часть 1] 7 года 1 нед. назад #100333
|
Ага. В Visual Studio Code тоже они есть.
А для шаблонов разных типов, можно поставить плагин на кастомные шаблоны файлов. Что нравится в VSC - мгновенная реакция на введенный символ и дерево файлов и поддиректорий (которого не хватало в Sublime). Писать на JS и подобном в нем максимально приятно. В отличие от WebStorm, который хоть и предоставляет более полное автодописывание за тебя и некоторые другие не особо часто используемые штуки, но имеет самую большую задержку между нажатием клавиши и появлением символа на экране (ощущение, будто комп тормозит). |
Последнее редактирование: 7 года 1 нед. назад от Lekste.
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: VarVarKa
|
Время создания страницы: 0.347 секунд