RTADS FAQ

Материал из Wiki о русской интерактивной литературе (текстовых играх)
Перейти к: навигация, поиск

Часто Задаваемые Вопросы и Ответы о системе RTADS

Мультимедиа

Вопрос от Zargo:
Подскажите, пожалуйста, как можно подключить графику и звук в игру и можно ли вообще это сделать на RTADSе.

Можно, для интерпретаторов с поддержкой мультимедиа. Это проигрыватели для систем Windows, Macintosh и Linux. Выглядит и реализуется как HTML верстка с некоторыми ограничениями. Графические/музыкальные ресурсы можно зашить в файл игры или распространять отдельными файлами. Графика: jpg, png, mng. Последний позволяет отображать анимированные изображения. Также можно воспроизводить анимацию из последовательности jpg, динамическим контентом или псевдографикой. Поддержка Gif не была реализована по причине ограничений лицензии.


Вопрос от ifn00b
Касательно мультимедийных возможностей - какие типы аудио-файлов можно подключить к RTADS? И каким образом происходит их проигрывание - интерпретатор вызывает внешнее приложение, которое зарегистрировано в системе для файлов данного типа?

Midi, wav, MP3 и Ogg Vorbis. Для проигрывания используется DirectX.

Подробно обо всем этом можно узнать здесь (увы, на английском языке): http://www.tela.bc.ca/tads-manual/tads-12.html

P.S. По мнению большей части сообщества, избыток графики и звука уводит от настоящего IF. Будьте очень осторожны и используйте эти возможности тогда, когда это оправдано.

Сборка и компиляция

Чем отличаются debug и release версии игры?

В debug версию включается дополнтельная информация, которая позволяет отлаживать игру в TADS Workbench. Из-за этого: во-первых, существенно увеличивается размер файла, во-вторых, весь текст записывается в открытом виде и может быть просмотрен любым редактором, в-третьих, старые версии интерпретаторов могут слетать на играх с длинными строками, скомпилированными в отладочном режиме.

Вывод: при выпуске игры в свет не забывайте компилировать и выкладывать release версию.

Отладка

Есть ли в ТАДС способы автоматического тестирования библиотек и игр?

В отладочных целях ещё в первых версиях ТАДС двадцатилетней давности были предусмотрены средства ввода команд из файла и вывода результата в другой файл. Таким образом, можно сверять файлы результатов с целью проверки корректности работы игры после последних изменений и её проходимость, без необходимости внимательного "ручного" просмотра.

Подробно это описано в пока непереведенной главе мануала: Параграф "Testing Your Game"

Вкратце:

mygame.exe -o walkthru.in  - записывает в файл команды по мере прохождения
mygame.exe -i walkthru.in -l walkthru.log  - запускает игру и вводит список команд, 
а выходящий текст записывает в файл.

Файл с выводом из предыдущей и новой версии можно сравнить с помощью специальных программ, типа WinMerge.

Синтаксис

Почему индексация массивов и строк начинается с единицы?!

Конечно же, это риторический вопрос. Но довольно часто ошибки в игре вызываются тем, что автор «на автомате» впечатал уже отложившийся на подкорке кусочек кода, который сработал бы для массивов, начинающихся с 0. Поэтому если у вас появляются ошибки выхода за пределы массива или строки какие-то обрезанные выводятся – в первую очередь проверяйте код, работающий с индексами массивов.


Никак не могу привыкнуть к этому полупаскальному-полусишному синтаксису. Можно ли как-нибудь привести его к единой форме?

Да. Существует специальная директива #pragma C+. Она включает режим соответствия языку C для файла, в котором упомянута, поэтому вы сможете использовать привычные == для сравнения и = для присваивания. А директива #pragma C- возвращает все к стандартному виду.

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


Как создать список (list) из одного элемента?

Если вы задали переменную "a" без указания какого либо типа, т.е.

local a;

то присвоить ей список из одного элемента

a := [b];

не удастся.

Нужно либо изначально указать что это список

local a=[];

либо поступить так:

a := [] + b;

Это также следует учитывать при передаче параметра типа список из одного элемента.

foo([param[3]]) // не будет работать

local temp:=param[3];
foo([temp]) // будет


При вызове метода foo() без аргументов возникает ошибка компиляции.

Если метод не принимает аргументов, то сотрите скобки при его вызове.

bar.foo(); //ошибка
bar.foo;   //вызов метода

При объявлении метода скобки все-равно нужны!

Неочевидные приемы

Почему не наследуются лексические свойства (sdecs, noun и пр.)?

В стремлении упростить жизнь авторам игр, TADS не делает особых различий между классом и объектом (экземпляром класса). Однако отличия есть, хоть и небольшие. Во-первых, класс нематериален в игре — вы никак не сможете взаимодействовать с ним. Во-вторых (уже догадались?) лексические свойства (sdesc, ldesc, noun, adjective) наследуются только от классов, а от объектов нет.

Пример:

coin : item
    desc = 'золотая/1пж монета/1ж'
    ldesc = "Золотая монета с изображением профиля Императора. "
    isHer = true
;

coin1 : coin
    location = treasury
;

coin2 : coin
    location = chest
;

coin3 : coin
    location = purse
;

В таком виде пример работать не будет, потому что лексические свойства объекта coin не наследуются потомками. Соответственно, вы просто не найдете монет в игре, потому что к ним никак нельзя будет обратиться (свойство noun-то не заполнено!). Уже догадались, как исправить? Правильно, пишем в первой строке:

class coin : item

и все встает на свои места.

Примечание: на момент написания заметки библиотека находилась в состоянии активной разработки и desc, к примеру, стал наследоваться нормально, просто дублируя словоформы много раз. Несмотря на это, рекомендуется ВСЕГДА использовать классы, если требуется наследовать лексические свойства.


Как динамически изменить ldesc (и другие свойства с двойными кавычками)?

Двойные кавычки (") — удобная особенность языка TADS, однако принцип их работы может немного смутить новичков. Двойные кавычки служат для вывода текста на экран, то есть, как только в ходе выполнения программы интерпретатор встречает строку в двойных кавычках, он тут же отображает её. Если строка в двойных кавычках присвоена в качестве свойства какого-либо объекта, то она будет отображаться при каждом обращении к этому свойству. Смысл этого в том, чтобы облегчить автору работу с текстом — базовой единицей всей ИЛ. При этом следует понимать, что строка в двойных кавычках — это не переменная как таковая, а, фактически, завуалированный метод для вывода переданного текста на экран. Он ничего не возвращает, поэтому строками в двойных кавычках нельзя манипулировать так же, как обычными переменными. Например, следующий, на первый взгляд правильный код не будет работать:

vase : item
    gdesc = 'ваза/1ж'
    ldesc = "Хрупкая фарфоровая ваза. "
...

    doDrop(actor) =
    {
        "Ваза была так тонка, что разбилась при падении. ";
        self.ldesc := "Теперь ваза представляет собой лишь груду черепков. ";
        pass doDrop;
    }
;

Так как метод «двойные кавычки» ничего на самом деле не возвращает, ldesc в данном примере перепишется пустым значением и описание исчезнет вообще. Для решения этой проблемы следует переписать определение ldesc вот так:

vase : item
    gdesc = 'ваза/1ж'
    ldesc = 
    {
        if (not self.broken)
            "Хрупкая фарфоровая ваза. ";
        else
            "Теперь ваза представляет собой лишь груду черепков. ";
    }

    broken = nil
...

    doDrop(actor) =
    {
        "Ваза была так тонка, что разбилась при падении. ";
        self.broken := true;
        pass doDrop;
    }
;


Ещё один способ - вставить в строку с двойными кавычками вызов изменяемого свойства. Например:

vase : item
    gdesc = 'ваза/1ж'
    ldesc = 
    {
        if (not self.broken)
            "Хрупкая фарфоровая ваза. ";
        else
            "Из-за <<negodyai>> ваза превратилась в груду черепков. ";
    }

    broken = nil
    negodyai=''
...

    doDrop(actor) =
    {
        "Ваза была так тонка, что разбилась при падении. ";
        self.broken := true;
        negoyai:=dToS(actor,rdesc); 
        // функция dToS перехватывает вывод на экран "двукавычного" 
        // свойства rdesc и присваивает переменной negoyai
        pass doDrop;
    }
;

Здесь мы превратили свойство rdesc действующего актера из строки с двойными кавычками в строку с одинарными и записали в объекте. Это свойство мы можем менять по ходу всей игры, и это будет менять описание. В данном случае - виновника происшествия.


Как реализовать части тела или объекта?

Как пример сложной фразы часто приводят примеры из серии:

врезать/ударить/пнуть ногой/хвостом/ёжиком (по) лбу/ноге/ягодицам/сенсорам монстра/робота/тети Клавы

На самом деле, это реализуется довольно просто:

class bodypart: fixeditem
    dobjGen(actor, verb, indirectobj, preposition) =
    {
        self.location.dobjGen(actor, verb, indirectobj, preposition);
    }
    iobjGen(actor, verb, directobj, preposition) = 
    { 
        self.location.iobjGen(actor, verb, directobj, preposition); 
    }
;

zhvala : bodypart
    location = megaant
    desc = 'жвала/2'
    adjective = 'муравья' 'муравья#r' 'муравью' 'муравью#r'
    ldesc = "Большие страшные жвала. "
;

Теперь "ударить муравья по жвалам палкой" будет равнозначно "ударить муравья палкой". Если вы хотите сделать отличную от такой реакцию, то напишите исключение для конкретных значений параметра verb.

Усложнение принимаемых фраз

Как заставить понимать команду с тремя существительными, ввести наречия, сделать несколько проходов в одной стороне света и т.п.

Большинство таких нестандартных подходов не стоят затрачиваемых усилий для их реализации. Постарайтесь упростить те случаи для которых вы хотите их использовать.

Например, по порядку:

  1. привязать лошадь веревкой к забору = привязать веревку к забору и привязать веревку к лошади
  2. тихо открыть дверь = смазать петли салом и открыть дверь
  3. на юге вы видите три пещеры. Кровавый след тянется в ту, что западнее, а из восточной выползает вязкий белесый туман