Добавляем автоперенос в игру на Kirikiri

Как вы знаете, японцам перенос на новую строку по пробелу не очень-то нужен, как следствие практически во всех японских ВНках на Kirikiri перенос осуществляется побуквенно.

Сегодня я расскажу, как перестать расставлять переносы руками в переводе и начать жить 🙂

И, прежде чем мы начнём, давайте поблагодарим товарища Nagato, написавшего первоначальный код этой процедуры.

Итак, что нам понадобится.
Прежде всего, это полный текст строки. Думаете, это не проблема? Увы, бывает всё не так просто и в разных играх он может добываться разными методами. Сегодня речь пойдёт о том, как это сделано в игре Tsugihagi Make Peace — Pretending x Friendship.

Приступим.

Открываем в редакторе файл MainWindow.tjs (надеюсь, распаковка скриптов у вас вопросов не вызвала) и добавляем в самом начал, туда, где определяются переменные:


var textLine = void; // автоперенос: переменная для хранения полного текста текущего фрагмента
var wrapNum = 0; // автоперенос: переменная для хранения количества пробелов
var wrapPos = 0; // автоперенос: переменная для хранения позиции переноса
var oldLine = void; // автоперенос: переменная для хранения предыдущей строки
var splitLine = void; // автоперенос: переменная для хранения массива слов
var canWrap = true; // автоперенос: признак возможности переноса строки (есть ли в строке пробелы и дефисы)
var newPage = false; // автоперенос: признак перехода на новый экран при превышении количества строк, помещающихся на экране
var mustReline = false; // автоперенос: признак необходимости переноса на новую строку

Отлично. Далее, находим функцию, отвечающую за вывод имени персонажа. И пусть вас не смущает, что есть фрагменты, в которых имя не используется, - функция всё равно будет вызвана.
dispname : function(elm)
И первой же строчкой пишем:
textLine = getCurrentInfo().lineStr; // получаем строку, которая будет выводится в окне диалога

Если что-то пойдёт не так, вы можете, конечно, перенести эту строку в функцию посимвольного вывода (о которой речь пойдёт ниже), но тогда этот код будет исполнятся при выводе каждой буквы каждого фрагмента, что с точки зрения программирования отчаянное рукожопство 🙂

Ах да! Полезный хинт! Хотите вывести окно со значением той или иной переменной? Нет проблем! Используйте для этого следующую функцию:
System.inform(textLine);

С этим разобрались. Осталось немного.
Ищем функцию, отвечающую за вывод очередного символа, - ch : function(elm), и в ней после проверки на включённость режима пропуска (if (skipNoDisp) { return 0;}), добавляем следующий код:

/*
Wordwrapping code
Nagato (nagato@readyoursicp.com)
Adapted by DOOMer
*/
/* Важные замечания от DOOMer'а:
- в elm.text хранится текущий выводящийся символ, не весь текст фрагмента, как можно было бы подумать
- переменная textLine присвоена в функции dispname
*/
if (textLine != void)
{
if (textLine.indexOf(" ") != -1 || textLine.indexOf("-") != -1) // если в строке нет пробелов и дефисов, то идём дальше
{
if (oldLine != textLine) // если эта строка отличается от уже обработанной, то переопределяем переменные
{
var tempStr = void; // автоперенос: переменная, которая будет содержать неразбитую исходную строку без символов экранирования
oldLine = textLine; // переменная, хранящая в себе исходную строку
wrapNum = 0; // количество мест переносов
for (var i = 0; i < oldLine.length; i++) // проходим циклом по всем буквам строки
{
if (oldLine[i] != '\\') // тут удаляются все символы экранирования "\"
tempStr = "%s%c" . sprintf(tempStr, oldLine[i]);
}
if (tempStr === void || (tempStr.indexOf(" ") == -1 && tempStr.indexOf("-") == -1)) // если строка пустая или пробелов с дефисами нет, то переносы не требуются
canWrap = false; // переносы не нужны
else
{
canWrap = true; // переносы возможны
splitLine = tempStr.split("/ |-/"); // разбиваем строку по пробелам и дефисам, получаем массив слов
}
wrapPos = current.x;
}

if (canWrap) // если переносы возможны
{
if (elm.text == " " || elm.text == "-") // если текущий символ пробел или дефис
{
wrapNum++; // увеличиваем счётчик возможных переносов
wrapPos = current.x;
}
if (wrapPos + current.lineLayer.font.getTextWidth(splitLine[wrapNum]) > current.relinexpos) // если позиция переноса + ширина оставшегося текста (с учётом действующего шрифта) выходит за правую границу окна сообщений
{
if (current.lineLayer.font.getTextWidth(splitLine[wrapNum]) <= current.relinexpos) // если ширина строки меньше отведённого под неё окна, то ничего не переносим
{
if (elm.text == " ") // если перенос по пробелу
{
elm.text = ""; // выпиливаем символ пробела - он не нужен
mustReline = true; // устанавливаем признак необходимости перехода на новую строку
}
if (mustReline) // если установлен признак перехода на новую строку, то...
{
mustReline = false; // ...сбрасываем признак перехода на новую строку
historyLayer.reline(); // ...переходим на новую строку в истории
if (current.processReturn()) // ...переносим на новую строку в окне сообщений; если больше нет места для новых строк, то переходим на новый экран
{
newPage = true; // устанавливаем признак перехода на новый экран
return showPageBreakAndClear(); // выводим новый экран
}
}
if (elm.text == "-") // если перенос по дефису (например, в "ёк-макарёк"), то выпиливать символ дефиса не нужно, мало того перенос должен произойти после вывода дефиса, перед выводом следующего символа...
mustReline = true; // ...поэтому устанавливаем признак необходимости перехода на новую строку только здесь, уже после кода перехода на новую строку
}
wrapPos = current.x;
}
}
}

if (newPage) // если произошёл переход на новый экран, то сбрасываем переменные
{
elm.text = ""; // сбрасываем значение текущего символа
newPage = false; // сбрасываем признак перехода на новый экран
}
}

Вот и всё.
Поздравляю. Мы это сделали. Возможно, у нас даже всё работает 🙂

Суббота, 30 сен 2017 Переводы

Комментариев пока нет.

Ваш отзыв

Вы должны войти, чтобы оставлять комментарии.

Поддержите меня!

Если вы хотите отблагодарить меня, можете закинуть денег мне на хостинг.
Делается это просто: в любом терминале ищем провайдера "Masterhost" и указываем лицевой счёт c123759 (обычно без первой буквы).

А я уж постараюсь и дальше стараться! :D

Яндекс.Деньги

41001543226857