Данный файл является частью Руководства по TADS для авторов игр.
Copyright © 1987 - 2015 Майкл Дж. Робертс (Michael J. Roberts). Все права защищены.
Руководство было преобразовано в формат HTML Н. К. Гайем (N. K. Guy), компания tela design.

Перевод руководства на русский язык - Валентин Коптельцев


Глава девятая


Основы Multimedia TADS

HTML и Multimedia TADS

Вообще-то для написания игры под Multimedia TADS не требуется знаний HTML, поскольку все средства форматирования обычного TADS (последовательности \b, \n, \t и т. д.) прекрасно работают и в мультимедийном интерпретаторе. Можно сказать больше - использование этих средств будет предпочтительным с точки зрения обратной совместимости, а также обеспечения нормального отображения игры при запуске на интерпретаторах, не поддерживающих мультимедийные возможности (таковыми являются, например, универсальные проигрыватели типа Spatterlight или Gargoyle).

Однако вам потребуется в некотором объеме изучить HTML в случае, если вы захотите ввести в свою игру расширенные возможности форматирования. Полноценный учебник и справочник по HTML, как говорится, выходит за рамки настоящего Руководства, однако благодаря популярности данного языка по нему существует огромное количество документации, которую можно найти и в книжных магазинах, и бесплатно в Интернете.

В большинстве случаев вы сможете использовать в Multimedia TADS стандартные теги HTML без каких-либо модификаций. Однако есть ряд областей, имеющих свою специфику в TADS - прежде всего речь идет о тегах, определяющих структуру документа. Возможно, вы захотите ознакомиться с этими областями поближе, прежде чем начнете использовать более сложные средства. Для этого вы можете обратиться к приложению I, Отличия Multimedia TADS от стандартного языка HTML.


Отладка HTML

HTML является языком программирования, в связи с чем имеет строгие правила синтаксиса, которым необходимо следовать, чтобы все работало, как должно.

Если интерпретатор Multimedia TADS обнаруживает в программе непонятный ему синтаксис HTML, он, как правило, просто игнорирует соответствующий тег. Благодаря этому выводимый текст, как правило, не "уродуется", однако его форматирование теряется.

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

   // Функция вывода гиперссылки (command - ссылка, text - текст ссылки); 
   // при отключенном режиме HTML (global.HTML=nil) выводится просто текст
   displayLink: function( command, text )
      {
       if ( not global.HTML )
          say( text );
       else
      {
       "<A HREF=\"";
         say( command );
        "\">";
        say( text );
        "</A>";
  }
}   
  

Тем не менее, некоторым подспорьем для проверки тегов является подсветка синтаксиса в редакторе.


Включение режима HTML при помощи последовательности "\H+"

Чтобы начать использовать в своей игре возможности HTML, в первую очередь необходимо сообщить об этом интерпретатору Multimedia TADS. Дело в том, что в целях обратной совместимости со старыми играми мультимедийный интерпретатор по умолчанию запускается в режиме, при котором вся разметка HTML просто игнорируется. Для того, чтобы интерпретатор ее воспринимал, необходимо передать ему специальную команду форматирования. В самом начале игры, например, в одной из первых строк функции init(), необходимо указать следующее:
    "\H+";

(Иначе говоря, требуется вывести на экран специальной управляющей последовательности, состоящей из трех символов - \H+). На экране на самом деле ничего отображаться не будет, однако мультимедийный интерпретатор TADS перейдет в режим обработки форматирования HTML.

Начиная с этого момента, Multimedia TADS будет интерпретировать последовательности HTML в вашей игре, значительно расширяя возможности форматирования выводимого текста.

Во всех более-менее свежих версиях русскоязычной стандартной библиотеки stdr.t эта последовательность уже включена в состав функции commonInit(), так что автору игры ничего делать не потребуется.

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

При конвертации чисто текстовой игры в мультимедийную возможен и следующий подход - режим HTML включается только там, где он используется, а затем снова отключается. Отключение HTML осуществляется последовательностью "\H-";. Такой подход наиболее логичен, если расширенные возможности форматирования текста нужны вам в ограниченном числе мест, при этом для основной части игры вы хотите полностью исключить возможность каких-то искажений выводимого текста. Однако при разработке новой игры под мультимедийный интерпретатор вам, скорее всего, проще будет включить режим HTML один раз в самом ее начале. В то же время в целях отладки и тестирования имеет смысл предусмотреть системный глагол, который бы включал/выключал режим HTML путем вывода соответствующей управляющей последовательности.

Если вы планируете использовать для формирования строки состояния стандартный код из библиотеки advr.t, обязательно прочитайте раздел про старый и новый формат строки статуса, поскольку вам в этом случае, скорее всего, также придется определить символ препроцессинга USE_HTML_STATUS. Правда, если вы будете самостоятельно формировать собственную нестандартную строку состояния, определять его не потребуется.


Специальные символы - < и &

При активном режиме HTML два символа приобретают специальное значение, поскольку с них начинаются управляющие последовательности HTML. Первый такой символ - знак "меньше" ("<"), открывающий теги HTML. Второй знак - амперсанд ("&"), начинающий последовательности для отображения нестандартных символов. Будучи управляющими символами, сами они при этом не отображаются.

Вряд ли в тексте вашей игры эти символы будут встречаться часто, однако для корректного их отображения вам потребуется преобразовать каждый такой символ в специальные последовательности. Для знака "меньше" это будет

  &lt;

, а для амперсанда -

  &amp;
Обратите внимание, что специальные последовательности вида "<<" и ">>", служащие для вывода значения переменной, менять не требуется и не следует; например, следующее определение
  ldesc = "На доске накорябано уравнение: x &lt; << blackboard.xValue >>"
не претерпит изменений при переносе игры на мультимедийный интерпретатор. Причиной этого является то, что данный синтаксис используется только компилятором TADS, который обнаруживает такие вложенные выражения и удаляет их из текста до того, как этот текст будет записан в бинарный файл игры .GAM. Теги же HTML обрабатываются мультимедийным интерпретатором, который уже не увидит последовательности "<<".

Разметка HTML

Команды форматирования HTML называют разметкой HTML, поскольку они как бы размечают простой текст, внося дополнительную информацию. Разметка бывает двух видов: сущности, которые позволяют вывести определенный символ, используя зарезервированное под него обозначение; и теги, содержащие информацию по структуре и/или форматированию текста, а также примечания к нему.

Сущности

В парадигме HTML сущность представляет собой, по сути, более длинный способ записать один символ. Необходимость в сущностях возникла по следующим двум причинам.

Как вы уже могли заметить, названия сущностей всегда начинаются с амперсанда ("&") и заканчиваются точкой с запятой (";"). Это означает, что и сам символ амперсанда является управляющим - для вывода его на экран необходимо записать соответствующую ему сущность ("&amp;"). При включении сущности в текст все символы между открывающим сущность амперсандом и замыкающей ее точкой с запятой удаляются из выводимого текста, и вместо них выводится единственный символ, соответствующий данной сущности.

Теги

Теги служат для включения в текст информации о необходимом форматировании.

Теги всегда начинаются со знака "меньше" ("<") и заканчиваются знаком "больше" (">"). Между этими знаками располагается имя тега. Иногда этим именем всё и ограничивается - например, для перехода на новую строку можно использовать тег <BR>. В других случаях для тега указываются атрибуты.

Атрибут может состоять только из имени либо принимать какое-либо значение. В последнем случае за именем атрибута ставится знак равенства ("="), за которым указывается значение атрибута.

Например, для тега <HR> (вывод горизонтальной линии) можно определить атрибут NOSHADE, которому не присваивается никакого значения, однако само его наличие говорит о том, что горизонтальная линия не должна иметь тени. Таким образом, тег <HR> выводит горизонтальную линию, отбрасывающую тень, а <HR NOSHADE> - простую линию без тени. Кроме того, для данного тега можно определить атрибут ALIGN с одним из значений, определяющих способ выравнивания для линии: LEFT означает выравнивание по левому краю, RIGHT - по правому, а CENTER - по центру. Таким образом, тег <HR ALIGN=CENTER> выведет отцентрованную горизонтальную линию с тенью, а <HR ALIGN=RIGHT NOSHADE> - выровненную по правому краю линию без тени.

Контейнерные теги

Некоторые теги носят название контейнерных. Такой тег как бы отмечает кусок текста и состоит из двух частей - открывающей и закрывающей (указывающей, где заканчивается отмеченный текст). Все символы между открывающей и закрывающей частью являются как бы "содержимым" контейнерного тега. Сами эти части также для краткости именуют тегами.

Закрывающая часть (тег) всегда носит то же название, что и открывающая, но с наклонной чертой перед ним. Например, закрывающим тегом для <I> будет </I>. Атрибуты в закрывающем теге никогда не указываются.

Пример контейнерного тега - тег <B>, для которого весь заключенный в нем текст выводится полужирным шрифтом:

    "А это будет напечатано <B>полужирным</B> шрифтом! ";

В данном примере слово "полужирным" будет выделено.

Контейнерные теги можно вкладывать один в другой, однако внутренний тег всегда должен закрываться раньше внешнего. Таким образом, следующая запись некорректна с точки зрения синтаксиса HTML:

   /* Недопустимое форматирование HTML */
   "А этот текст набран <B>полужирным, <I>полужирным курсивом и </B>просто курсивом</I>! ";

Ошибка здесь состоит в том, что тег <I> вложен внутрь тега <B>, однако при этом закрывающий тег </B> расположен в тексте раньше, чем </I>. Правильный вариант выглядит так:

   /* Это корректная запись */
   "А этот текст набран <B>полужирным, <I>полужирным курсивом и </I></B><I>просто курсивом</I>! ";
  

Использование разметки в TADS

Пользоваться разметкой HTML в TADS несложно: ее элементы просто вставляются в выводимый на экран текст.

Пусть, например, вам требуется вывести полужирным шрифтом пару фрагментов описания комнаты. Для этого достаточно окружить эти фрагменты тегами <B> прямо в тексте описания:

   coldCave: room
     sdesc = "Холодная пещера"
     ldesc = "В этой пещере стоит зверский <B>холод</B>.
             Пронизывающий ветер задувает из узкого лаза на севере. 
             Ты явно не выдержишь здесь долго: ты просто <B>замерзнешь</B>! "
   ;

HTML действует только в том тексте, который выводится на экран. Применять его, например, внутри кода программы бесполезно.

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

   ampkeyVerb: deepverb
     verb = 'ampkey'
     action(actor) =
     {
       local x;

       /* ЭТО НЕУДАЧНЫЙ ПРИМЕР, КОТОРЫЙ НЕ БУДЕТ РАБОТАТЬ!!! */
       x := inputkey();
       if (x = '&amp;')
         "Вы нажали клавишу <q>&amp;</q>!\n";
       else if (x = '&lt;')
         "Вы нажали клавишу <q>&lt;</q>!\n";
       else
         "Вы нажали <<x>>!\n";
     }
   ;

Этот код не будет работать так, как от него ожидается. Проблема состоит в том, что сравнения строк будут выполняться некорректно, поскольку TADS в этой ситуации не будет пытаться интерпретировать разметку HTML. Правильным способом записи условия на равенство амперсанду в данном случае будет (x = '&'), а на равенство знаку "меньше" - (x = '<'). Еще раз - будет заблуждением считать, что вам постоянно потребуется думать о HTML при написании программы, это вовсе не так. HTML может возникнуть на вашем горизонте только, когда потребуется вывести текст на экран.

Вот корректная версия вышеприведенного фрагмента:

   ampkeyVerb: deepverb
     verb = 'ampkey'
     action(actor) =
     {
       local x;

       x := inputkey();
       if (x = '&')
         "Вы нажали клавишу <q>&amp;</q>!\n";
       else if (x = '<')
         "Вы нажали клавишу <q>&lt;</q>!\n";
       else
         "Вы нажали <<x>>!\n";
     }
   ;
Упражнение для читателя: поскольку сам этот документ также написан с применением HTML, примеры кода с разметкой должны использовать сущности для отображения этой разметки. Например, чтобы браузер вывел последовательность &amp;, потребуется написать &amp;amp; в исходном коде этой страницы. Попробуйте повысить свое умение пользоваться языком HTML, попытавшись воспроизвести разметочные последовательности, необходимые для отображения тех или иных примеров из этой главы. Проверить себя вам будет несложно - для этого достаточно будет открыть данный документ не в браузере, а в простом текстовом редакторе (например, "Блокноте").

Старая и новая строка статуса

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

Обычный текстовый интерпретатор TADS жестко запрограммирован на вывод строки состояния в стиле игр от Infocom. Другими словами, с левой стороны этой строки выводится название текущей локации, а с правой - разделенные косой чертой количества набранных игроком очков и сделанных ходов. За вывод названия комнаты отвечает жестко запрограммированный метод statusLine в коде объекта-локации. Любой выводимый этим методом текст автоматически размещается с левой стороны строки состояния. Текст с правой стороны строки генерируется функцией setscore(), которая, в свою очередь, вызывает функцию scoreFormat(). При каждом таком вызове выводимый функцией текст размещается с правой стороны строки.

При этом функциональность строки состояния в текстовом интерпретаторе TADS со временем расширялась, именно поэтому вывод текста в левую ее часть осуществляется при помощи метода, а в правую - при помощи функции. TADS 1 вообще не позволял менять текст с правой стороны строки состояния - такая возможность была добавлена позже.

Multimedia TADS снимает все эти ограничения. Здесь строка состояния находится под полным контролем автора игры. В Multimedia TADS предусмотрены так называемые "баннеры" (подробно описанные в следующем разделе), которые позволяют задать вывод текста в область панели в верхней части окна интерпретатора. Эта область может иметь любой размер по вашему выбору и содержать все те же элементы, что и основное окно - сложное форматирование, графические изображения и любые другие возможности HTML. А можно пойти и еще дальше, определив несколько строк состояния - количество баннеров ограничивается только размером окна приложения. Также вы можете отображать и скрывать строки состояния по ходу игры.

Однако некоторую цену за такую гибкость все же придется заплатить: форматирование строки состояния ложится целиком на ваши плечи. В то время как в стандартном текстовом интерпретаторе TADS все форматирование строки состояния осуществляется автоматически, в Multimedia TADS от автора требуется задать для нее форматирующую разметку HTML.

К счастью, в стандартной библиотеке advr.t имеются средства поддержки, автоматически генерирующие необходимые команды HTML с целью эмуляции стандартной строки состояния в мультимедийном режиме. Результаты работы этих средств можно заменить собственными форматирующими командами, однако по умолчанию будут задействованы именно они, что сильно упрощает разработку. Чтобы использовать строку состояния по умолчанию, необходимо скомпилировать игру, определив символ препроцессинга USE_HTML_STATUS.

Пример реализации традиционной строки состояния средствами HTML можно посмотреть в стандартной библиотеке advr.t, в методе statusLine объекта room (той его версии, которая определена внутри раздела #ifdef USE_HTML_STATUS). Если вы хотите использовать свой формат строки состояния, просто замените этот метод своим, используя команду replace. Если вы в своей игре не используете библиотеку advr.t, вы можете просто перенести этот кусок кода в свою игру.

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


Баннеры

Тег BANNER, введенный в HTML версии 3.0 (но впоследствии из языка убранный), позволяет создать для документа непрокручиваемую область на экране и вывести в нее отформатированный при помощи разметки HTML текст. В Multimedia TADS данный тег (в несколько расширенном варианте) используется для создания строки состояния, куда большинство текстовых игр выводит текущую локацию, а также количество сделанных игроком ходов и набранных им очков.

По своему функционалу тег BANNER схож с так называемыми фреймами, реализованными в подавляющем большинстве интернет-браузеров, однако больше подходит для создаваемых в Multimedia TADS текстовых игр. (К слову, фреймы в Multimedia TADS не поддерживаются). Фундаментальным отличием между этими средствами является то, что BANNER задает область, оформление и содержимое баннера внутри основного текста документа HTML, в то время как фрейм просто содержит ссылку на другой ресурс (документ), чье содержимое и отображается во фрейме. Использование сторонних ресурсов не вписывается в концепцию Multimedia TADS, поэтому фреймы для него не применимы.

Тег BANNER является контейнерным. Все элементы форматирующей разметки, расположенные между тегами <BANNER> и </BANNER>, отображаются в баннере. Здесь могут располагаться любые теги, кроме TITLE и BANNER (т. е. баннеры не могут быть вложенными; повторный тег <BANNER> будет игнорироваться).


Идентификатор баннера

Для тега BANNER можно указать атрибут ID и присвоить баннеру некое имя. Имя это может быть совершенно произвольным; оно нужно для того чтобы в последующих аналогичных тегах можно было ссылаться на ту же область экрана. Когда Multimedia TADS встречает тег BANNER, то прежде всего проверяет, существует ли уже баннер с тем же идентификатором; если да, то все его имеющееся содержимое (включая форматирование) очищается и формируется заново на основе нового тега. Если же баннера с указанным в атрибуте ID идентфикатором не существует, создается новая область баннера, куда и выводится содержимое. Система запоминает идентификатор нового баннера, и последующие теги могут обращаться к нему и обновлять его содержимое.

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


Расположение баннера на экране

Для тега BANNER можно задать атрибут ALIGN, который укажет, где именно на экране разместить баннер. Возможны четыре значения: TOP (сверху), BOTTOM (снизу), LEFT (слева) и RIGHT (справа). Если значение не указать, система будет считать, что указано ALIGN=TOP. Эти значения имеют следующий эффект:

Каждый баннер, по сути, делит окно ввода на две части. В первоначальном состоянии, когда баннеры отсутствуют, окно ввода занимает всю область основного окна Multimedia TADS. Первый определенный вами баннер делит окно на две части в соответствии с назначенным размещением баннера. Например, если первый баннер размещается сверху, окно будет выглядеть следующим образом:

    Содержимое первого баннера    




    Окно ввода    



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

Например, если вы теперь зададите второй баннер с левым размещением (ALIGN=LEFT), окно примет следующий вид:

    Содержимое первого баннера (ALIGN=TOP)    
Содер-
жимое
второго
баннера
(ALIGN=
LEFT)




    Окно ввода    



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

Содер-
жимое
первого
баннера
(ALIGN=
LEFT)
Содержимое второго баннера (ALIGN=TOP)




    Окно ввода    



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


Окрашивание баннеров

Цвет текста и фона для баннера можно задать, используя внутри него тег BODY. Этим же тегом можно задать использование для баннера фонового рисунка. Такой тег, размещенный внутри баннера, оказывает влияние только на сам этот баннер; таким образом, каждый баннер и основное окно игры могут иметь различные цвета.

Атрибуты размера

В теге BANNER можно указать атрибуты HEIGHT и WIDTH, задающие его высоту и ширину соответственно. Поскольку по одному из направлений баннеры всегда имеют жестко определенный размер в соответствии со своим размещением (горизонтальным или вертикальным), то смысл будет иметь только один из этих атрибутов.

Для горизонтального баннера (ALIGN=TOP или ALIGN=BOTTOM) значение будет иметь только атрибут HEIGHT, отвечающий за высоту, поскольку такой баннер займет всю ширину исходного основного окна. Если атрибут HEIGHT для такого баннера не задан, высота будет выбрана в соответствии с высотой его содержимого. Если этот атрибут задан, он задает высоту баннера в пикселях. Также можно указать эту высоту в процентах от высоты основного окна, указав перед значением высоты знак процента ("%"). Например, чтобы создать баннер, занимающий нижнюю четверть основного окна, можно указать примерно следующее:

   <banner id='myBanner' align=bottom height='25%'>

Атрибут HEIGHT также может вместо числового (абсолютного или относительного) указания высоты иметь значение PREVIOUS. Это означает, что, если баннер уже отображается (например, его тег ID совпадает с идентификатором одного из предыдущих баннеров), его высота не меняется. Если указано HEIGHT=PREVIOUS, а баннер еще не отображается, используется настройка по умолчанию (высота баннера определяется его содержимым). Для часто обновляемых баннеров такое значение атрибута HEIGHT, как правило, очень удобно, поскольку занимаемая баннером область экрана при этом не меняется. Стандартная реализация строки статуса в библиотеке advr.t использует настройку HEIGHT=PREVIOUS, сохраняя тем самым эту строку постоянной по размеру и положению на экране на все время игры.

Для вертикальных баннеров (ALIGN=LEFT или ALIGN=RIGHT) учитываться будет только атрибут ширины WIDTH. Как и для HEIGHT, можно задать для него абсолютное, относительное значение, а также специальное значение PREVIOUS. Если ширина баннера не указана, система установит минимальное значение, достаточное для размещения любого "неделимого" элемента содержимого баннера. Неделимыми считаются, например, отдельные слова и изображения, поскольку они не переносятся с одной строки на другую.

Если у вас не получается получить баннер необходимого вам размера и с правильным размещением на экране, то можно попробовать использовать таблицу внутри баннера. Таблицы позволяют наиболее полно контролировать размеры текстовых блоков HTML, а также их взаимное расположение. Использование таблиц будет особенно полезным для вертикальных баннеров (ALIGN=LEFT или ALIGN=RIGHT), поскольку вы наверняка захотите по максимуму сократить пространство экрана, отводимое таким баннерам.


Границы

Атрибут BORDER позволяет указать для баннера окантовку по внутренней границе (при ALIGN=TOP эта граница будет снизу, при LEFT - справа, при RIGHT - слева и при BOTTOM - сверху).

Окантовка может оказаться полезной, если баннер совпадает по цвету с примыкающей к нему областью окна (эта область может быть как другим баннером, так и основным окном игры). Для атрибута BORDER никаких значений не задается; если этот атрибут указан, окантовка прочерчивается, в противном же случае баннер выводится без окантовки.


Удаление баннера

Атрибут REMOVE означает, что баннер необходимо удалить. Будет удален с экрана баннер, чей идентификатор совпадает с указанным в теге <BANNER REMOVE> в атрибуте ID значением. Тег <BANNER REMOVE> не является контейнерным, и замыкать его тегом </BANNER> не следует.

Атрибут REMOVEALL дает команду на удаление всех отображаемых в текущий момент на экране баннеров. При этом указывать идентификатор не требуется. Данный атрибут удобен для внезапных массированных изменений, например, при перезапуске игры.


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

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

Некоторые команды вносят изменения в состояние игры напрямую, минуя шаги, которые обычно делаются игрой в нормальном режиме. В частности, команды отмены последнего хода (UNDO), перезапуска (RESTART) и восстановления ранее сохраненного состояния игры (RESTORE) изменяют внутреннее состояние игры, синхронизируя его с неким предыдущим ее состояием. Однако эти команды не окажут влияния на созданные вами баннеры, поскольку баннеры отражают состояние экрана, а не игры.

Таким образом, вышеперечисленные команды не влияют на баннеры примерно по тем же причинам, почему они не влияют на ранее отображенный в окне игры текст. Например, при отмене последней команды текст, который выводился на экран при ее выполнении, не стирается, дальнейший текст будет выводиться после него. Так же обстоит дело и с баннерами.

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

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

В зависимости от конкретной игры и стоящих перед баннерами (и вами) задач, могут сработать и альтернативные подходы. Например, при наличии баннеров, которые должны обновляться не очень часто, вы можете определить процедуру, актуализирующую их содержимое, и принудительно вызывать ее в нужных местах игры. Обращение к этой процедуре можно добавить в метод action для глаголов в advr.t, соответствующих командам отмены последнего хода, перезапуска и восстановления игры (лучше всего с использованием инструкции modify).


Пример реализации строки состояния

Определенная в библиотеке advr.t строка состояния формируется при помощи тега BANNER и по стилю оформления близка к используемой в интерпретаторах TADS без поддержки мультимедийных функций.

    statusLine =
    {
        "<banner id=StatusLine height=previous>
        <body bgcolor=statusbg text=statustext><b>";

        self.statusRoot;

        "</b><tab align=right><i>";

        say(global.score); "/";
        say(global.turnsofar); " ";
        
        "</i></banner>";
    }

Первая строка содержит тег BANNER, который использует принятое по умолчанию расположение TOP, чтобы строка состояния представляла собой полосу в верхней части основного окна программы. В этом же теге для баннера задается идентификатор (ID) "StatusLine"; таким образом, по этому идентификатору к баннеру можно будет обращаться всякий раз, когда потребуется обновить строку состояния. Само слово "StatusLine" можно заменить на любое другое - главное, чтобы все идентификаторы баннеров были уникальными в пределах программы.

Во второй строке при помощи тега BODY устанавливается цвет текста и фона в баннере-строке состояния с использованием механизма параметризованных цветов.

В следующей строке осуществляется вызов метода statusRoot для отображения названия текущей локации (в большинстве случаев для этого используется свойство sdesc объекта-комнаты, хотя в некоторых случаях выводится дополнительная информация, например, "Озеро, на плоту").

Следующая строка выравнивает оставшийся текст по правому краю окна баннера при помощи тега <TAB ALIGN=RIGHT>. Всякий раз, когда размер окна изменяется, текст строки состояния будет автоматически переформатирован так, чтобы должным образом разместиться в имеющемся пространстве.

В следующих двух строках выводятся текущий счет и текущее количество сделанных игроком ходов.

Наконец, последняя строка завершает создание баннера. Поскольку BANNER является контейнерным тегом, блок инструкций необходимо закрыть ответным тегом </BANNER>, чтобы программа "знала", где оканчивается содержимое баннера и возобновляется текст основного окна программы.


Пример реализации панели команд

Вы можете использовать тег BANNER для вывода списка наиболее употребимых команд и постоянного отображения его на экране. В качестве примера приведен код, выводящий такой список в вертикальном баннере вдоль левой границы окна.

   "<banner id=CommandBar align=left width=75>
    <body bgcolor=yellow textcolor=black>
    <br><a href='инвентарь'>инвентарь</a>
    <br><a href='счет'>счет</a>
    <br><a href='см'>осмотреться</a>
    <br>
    <br><a href='север'>идти на север</a>
    <br><a href='юг'>идти на юг</a>";

    // дополнительные команды добавляются аналогичным образом

    "</banner>";

Благодаря возможности динамического обновления баннеров список команд можно всегда поддерживать в состоянии, актуальном для текущей игровой ситуации. Этого можно добиться, например, дописав код строки состояния и формируя после каждого хода новый баннер с тем же идентификатором (что аналогично замене предыдущего баннера с сохранением занимаемой им области на экране) и с командами, применимыми в текущий момент.


Разделение области баннера

У вас может возникнуть ситуация, когда вам потребуется разделить баннер на две части - примерно по следующей схеме:

Баннер 1 Баннер 2




    Окно ввода команд    



Сам по себе тег BANNER не позволяет сделать это напрямую. Однако вы можете добиться такого же эффекта, используя один-единственный баннер, содержащий таблицу из одного ряда и двух колонок:

   "<table width='100%' cellspacing=0 cellpadding=0>
    <tr align=center valign=middle>
    <td bgcolor=yellow>Это левая половина
    <td bgcolor=green>Это правая половина
    </table>";

Звуки и музыка в Multimedia TADS

Multimedia TADS предлагает дополнительные по сравнению со стандартным HTML средства, позволяющие автору использовать в своей игре звуковые эффекты и музыку. На момент создания Multuimedia TADS в HTML не была предусмотрена возможность воспроизведения звука, в связи с чем средства звуковой поддержки TADS не основаны на каких-либо стандартах HTML.


Форматы звуков и музыки

Версия 2.5.6 HTML TADS поддерживает следующие звуковые форматы: MIDI для музыки (в стандартном формате MIDI); Windows WAV для оцифрованных звуковых эффектов; MP3 для сжатых звуковых и музыкальных файлов (поддерживается, начиная с версии 2.2.7); а также формат Ogg Vorbis (с версии 2.5.6).

Хотя эти форматы не являются абсолютно универсальными, они действительно широко распространены и хорошо документированы. Многие программы создания мультимедийных звуковых эффектов позволяют создавать файлы этих форматов, для них имеется большое количество уже готовых свободно распространяемых в Интернете файлов звуковых эффектов и музыки. Кроме того, в своей совокупности эти форматы "закрывают" большую часть потребностей, чаще всего возникающих у авторов при создании игр. Формат WAV позволяет создавать записи наиболее высокого качества, способные передать практически любой звук, в то время как MIDI является гибким и компактным форматом для хранения музыки. MP3 и Ogg Vorbis являются использующими сжатие цифровыми звуковыми форматами, которые при достаточно высокой достоверности звучания обеспечивают значительно меньший объем звукового файла, чем несжатый WAV; оба этих формата хорошо подходят как для звуковых эффектов, так и для музыки.

Почему вместо MP3 лучше использовать Ogg Vorbis

Для оцифрованных звуковых эффектов в ваших играх на TADS предпочтительнее использовать Ogg Vorbis, а не MP3.

С точки зрения формы и функциональности Ogg Vorbis и MP3 эквивалентны. Оба формата способны ужать звуковой файл в несколько раз, а то и на несколько порядков. Оба допускают потерю качества исходного звучания: высокая степень сжатия достигается в том числе за счет отказа от деталей в исходном звуковом образце, которые с точки зрения данных форматов являются неслышимыми или минимально слышимыми. Для обоих форматов существуют кодеки, позволяющие пользователю выбрать степень потери качества для достижения той или иной эффективности сжатия конечного файла. По части возможностей воспроизведения звука в Multimedia TADS у Ogg Vorbis и MP3 также абсолютный паритет.

Почему же в таком случае рекомендуется использовать именно Ogg Vorbis, несмотря на всю популярность MP3?

Основная причина состоит в том, что Ogg Vorbis - это полностью бесплатный формат с открытым исходным кодом. С MP3 дело обстоит не так; определенные коммерческие организации заявляют патентные права на ряд его компонентов. Сложности с патентными правами делают MP3 изгоем в мире Линукса до такой степени, что в некоторых дистрибутивах TADS под Линукс поддержка MP3 сознательно отключена. При использовании в вашей игре MP3 пользователи на таких системах ничего не услышат. Ogg Vorbis же не просто поддерживается любым мультимедийным интерпретатором TADS - он встроен в него, так что пользователям не требуется заморачиваться с кодеками и прочими адд-онами.

Более того, Ogg Vorbis считается еще и более совершенным в техническом плане. Он позволяет сжимать аудиофайлы сильнее с меньшими потерями качества. Иначе говоря, с большой степенью вероятности можно утверждать, что при использовании Ogg Vorbis ваши звуковые и музыкальные эффекты будут звучать лучше.

На самом деле единственным, пожалуй, аргументом в пользу MP3 является привычка - скорее всего (если вы пользователь Windows), этот формат знаком вам лучше, чем Ogg Vorbis, да и конвертер для него у вас уже установлен. С привычками бороться, конечно, тяжело, однако по крайней мере проблема с конвертером решается просто. Поищите бесплатный конвертер Ogg Vorbis для Windows запросом oggDropXPd. Его скачивание и установка займут менее минуты. После этого вам достаточно будет перетащить на его значок файлы WAV, и они будут сконвертированы в Ogg.

MIDI

HTML TADS поддерживает MIDI, однако использовать этот формат в новых играх настоятельно не рекомендуется. Поддержка MIDI на ПК всегда была несколько непредсказуемой, поскольку во многих операционных системах воспроизведение MIDI-файлов возложено на звуковую карту. В связи с этим качество этого воспроизведения может сильно варьироваться. Это также ограничивает возможности TADS по управлению воспроизведением MIDI-файлов. Например, для такой музыки TADS не всегда способен организовать постепенное снижение громкости; кроме того, на многих компьютерах эта функция применима только к одному-единственному треку, поэтому, например, постепенное затухание одного трека при нарастании громкости другого и наложение треков друг на друга не всегда будут доступны.

Ресурсы в формате MIDI в игре для HTML TADS должны иметь расширение ".mid" или ".midi".

MP3 Аудио

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

Как уже сказано выше, вместо MP3 рекомендуется использовать Ogg Vorbis в связи с доступностью последнего на большем числе платформ, а также его преимуществами в качестве звука и эффективности сжатия.

Официальное название MP3 - MPEG 2.0 Audio layer III. TADS поддерживает MPEG 2.0 Audio layer II и III.

Ресурсные файлы MP3 в игре на HTML TADS должны иметь одно из следующих расширенией:

    .MPG
    .MP2
    .MP3

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

HTML TADS позволяет использовать ресурсы MP3 для любых целей (и как музыкальное сопровождение, и в качестве звуковых эффектов), однако не делает никаких предположений относительно того, как именно будет использоваться конкретный файл MP3, поэтому в теге <SOUND> необходимо в явном виде указать уровень.

Аудиоформат Ogg Vorbis

Ogg Vorbis также является аудиоформатом с использованием сжатия, пригодный для хранения и воспроизведения широкого спектра звуковых записей. Как и MP3, он преобразует исходный сигнал с учетом особенностей человеческого восприятия, удаляя часть элементов звуковой картины. Однако в отличие от MP3 он совершенно бесплатен и имеет открытый исходный код. Многие считают, что Ogg Vorbis более эффективен с точки зрения сжатия сигнала и при этом обеспечивает лучшее качество звучания, чем MP3.

Бесплатные программы для кодирования и воспроизведения звуковых файлов с использованием Ogg Vorbis можно найти в Интернете, например, по адресу Vorbis.com. Справочная информация по формату доступна на Xiph.org.

В HTML TADS ресурсы Ogg Vorbis должны иметь расширение .OGG. Как и для MP3, для Ogg Vorbis необходимо явно указывать уровень в теге <SOUND>.

Звуковая архитектура

Уровни

Звуки в HTML TADS разнесены по четырем "уровням" (layers): фоновый (background) уровень, фоновый внешний (background ambient) уровень, внешний (ambient) уровень, а также уровень первого плана (foreground). Обратите внимание, что эти уровни не имеют ничего общего с упомянутыми выше уровнями MPEG, представляющими собой просто разные форматы кодирования звука.

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

Фоновый уровень (background) предназначен для музыки. Фоновую музыку можно зацикливать, чтобы обеспечить непрерывное музыкальное сопровождение, причем можно запрограммировать воспроизведение нескольких музыкальных фрагментов поочередно. Изменить фоновую музыку можно в любой момент, когда вы этого захотите; например, можно назначить свою фоновую музыку для каждой локации в игре.

Фоновый внешний уровень (bgambient) используется для непрерывных звуковых эффектов (например, завывание ветра). По сути своей он ничем не отличается от фонового уровня.

Внешний уровень (ambient) также используется для фоновых звуковых эффектов, однако для таких, которые не будут непрерывными. Можно задать набор таких эффектов, проигрываемых случайным образом для создания атмосферы в игре (например, в ночном лесу может периодически ухать сова, завывать волк и т. п.). Как и для предыдущих уровней, этот набор эффектов можно в любой момент изменить.

Уровень первого плана (foreground) предназначен для озвучивания определенных действий игрока (например, когда тот открывает скрипучую дверь или стреляет).

Для полноты картины необходимо упомянуть, что вся эта система воспроизведения звуков была разработана с учетом того, что не каждая операционная система способна одновременно воспроизвести четыре трека. В настоящее время все современные версии HTML TADS (для Windows и для Macintosh) способны одновременно воспроизводжить множество треков, так что на практике такое ограничение не встречается. Однако, если (что, конечно, маловероятно) TADS когда-нибудь будет портирован на менее совершенную платформу, то будет происходить следующее: звуковые эффекты уровней с бОльшим приоритетом будут временно останавливать воспроизведение эффектов уровней "заднего плана" с тем, чтобы не заставлять операционную систему воспроизводить больше звуков, чем она способна. Уровень первого плана имеет наибольший приоритет, далее расположены внешний, фоновый внешний и фоновый. Вот пример, как это работает. Пусть игра запущена на операционной системе, способной одновременно воспроизводить только один трек, и в игре имеется музыкальное сопровождение, причем трек проигрывается на фоновом уровне. В какой-то момент становится необходимым коротко озвучить какое-либо действие в игре (например, щелканье выключателя). Поскольку больше одного звука система воспроизвести не может, в момент проигрывания эффекта для выключателя воспроизведение музыки будет прервано, а затем возобновлено с места остановки. Еще раз подчеркнем, что на практике вам не придется сталкиваться с такой проблемой, поскольку для существующих версий такого ограничения нет, и портирование TADS на платформы с такими ограничениями не планируется.

Очередность воспроизведения

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

В каждый момент времени HTML TADS допускает наличие одного активного звука в каждом из уровней. Звуки фонового уровня должны иметь формат MIDI, MPEG или Ogg Vorbis, а остальных уровней - WAV, MPEG или Ogg Vorbis.

В пределах каждого из уровней звуки организуются в очередь. Иначе говоря, звуки воспроизводятся последовательно в том порядке, который вы задали. Когда вы инициируете звук, вы также указываете, как он взаимодействует с другими звуками в очереди и как происходит его воспроизведение:

Тег <SOUND>

Звуковые возможности HTML TADS активируются при помощи специального тега <SOUND>. Данный тег отсутствует в стандарте HTML, хотя отдельные браузеры его поддерживают.

Атрибуты тега <SOUND> задают действия, которые этот тег должен выполнять.

Атрибут SRC определяет имя ресурса, содержащего звуковые данные. Это имя должно иметь расширение .WAV для файлов в формате WAV; .MID или .MIDI для файлов MIDI; .MPG, .MP2 или .MP3 для файлов MP3; и, наконец, .OGG для файлов Ogg Vorbis. Про создание и использование ресурсов можно почитать далее в этой главе.

Атрибут LAYER указывает уровень, в котором будет проигрываться звук. Этот атрибут может принимать одно из следующих значений: FOREGROUND, BGAMBIENT, AMBIENT и BACKGROUND. Хотя уровень, как правило, необходимо указывать в явном виде, HTML TADS в некоторых случаях способен самостоятельно выбрать уровень для звукового ресурса, основываясь на косвенных признаках:

Атрибут RANDOM позволяет задать вероятность проигрывания звука в одном из внешних уровней, если требуется, чтобы звуковой эффект воспроизводился время от времени случайным образом. Атрибут может принимать значения от 1 до 100; при низких значениях звук будет воспроизводиться изредка; если атрибут равен 100, звук будет проигрываться всегда, когда есть возможность (например, если не воспроизводится другой звук на том же или более приоритетном уровне).

Атрибут REPEAT позволяет задать количество воспроизведений звука и может использоваться на любом уровне. В качестве значения для данного атрибута можно задать либо целое число, которое будет соответствовать числу повторений звука, либо LOOP, что будет означать непрерывное воспроизведение звукового ресурса до принудительного его завершения.

Если вы не задали значения атрибута REPEAT для звукового фрагмента на внешнем уровне, указав при этом для него атрибут RANDOM, система будет по умолчанию использовать установку REPEAT=LOOP. Если же для такого звука задать в атрибуте REPEAT некое конечное значение, он будет воспроизведен максимум это количество раз, при этом система по-прежнему будет случайным образом решать после каждого хода, воспроизводить данный звук или нет.

Если задать значение атрибута REPEAT для звука переднего плана, этот звук будет воспроизведен заданное количество раз подряд.

При указании значения атрибута REPEAT для фонового и внешнего фонового уровней звук будет воспроизведен заданное число раз. Реальная последовательность воспроизведения звуковых фрагментов будет зависеть от значений атрибута SEQUENCE для рассматриваемого и для всех остальных фоновых звуковых фргаментов.

Атрибут SEQUENCE используется для управления порядком воспроизведения (повтора) группы фоновых звуковых эффектов и, соответственно, в основном предназначен для фонового и внешнего фонового уровней. Данный атрибут может принимать значения REPLACE, RANDOM или CYCLE. В первом случае (REPLACE) при начале воспроизведения нового звукового фрагмента очередь звуковых ресурсов, ожидающих воспроизведения, очищается (иначе говоря, те звуковые фрагменты, которые система не успела воспроизвести, проигрываться уже не будут). Для RANDOM после воспроизведения нового звукового фрагмента система приступает к воспроизведению других фрагментов, имеющихся в очереди (при условии, что циклы воспроизведения, задаваемые атрибутом REPEAT, для них еще не исчерпаны). При этом очередной звуковой фрагмент выбирается случайным образом. Аналогичным образом система работает и при значении CYCLE, с той разницей, что будет воспроизводиться не случайный фрагмент, а первый в очереди.

Этот атрибут можно использовать для организации переходов между музыкальными фрагментами. Например, вы можете задать REPEAT=1 для вступительной музыки, а затем указать REPEAT=LOOP и SEQUENCE=RANDOM для набора фоновых музыкальных фрагментов. При этом очередной трек для воспроизведения будет выбираться случайным образом, что позволит сделать фоновую музыку менее однообразной.

Атрибут INTERRUPT (значение для него не задается) указывает, что необходимо немедленно прервать воспроизведение любого трека, играющего в настоящий момент, и начать воспроизведение нового звукового фрагмента. Этот атрибут рекомендуется использовать только для звуковых эффектов уровня переднего плана.

Атрибут CANCEL отменяет воспроизведение всех треков, стоящих в очереди в данный момент. При отсутствии дополнительных указаний тег <SOUND CANCEL> отменяет воспроизведение треков на всех уровнях. Это можно использовать, например, для отключения всех звуковых эффектов при переходе игрока в новую локацию. Кроме того, для данного тега можно указать конкретный уровень с тем, чтобы отменить воспроизведение только для этого уровня; можно задавать значения FOREGROUND, AMBIENT и BACKGROUND. Например, тег <SOUND CANCEL=AMBIENT> отменит воспроизведение треков только для внешнего уровня.

Атрибут ALT позволяет задать текстовое описание проигрываемого трека. Это может быть полезно при запуске мультимедийной игры на интерпретаторе, не поддерживающем воспроизведение звука - в этом случае вместо проигрывания самого трека будет будет выводиться его описание. Текущая версия интерпретатора под Windows в настоящее время игнорирует данный атрибут.

Атрибуты FADEIN и FADEOUT позволяют организовать постепенное увеличение громкости воспроизводимого трека вначале либо плавное его затухание в конце. Их действие подробно описано далее. В качестве значения для атрибута указывается длительность периода постепенного изменения громкости в секундах. Эта длительность может быть дробной; например, FADEIN=2.5 означает, что нарастание громкости будет происходить в течение двух с половиной секунд.

Когда звуковой фрагмент воспроизводится несколько раз при помощи атрибута REPEAT, постепенное увеличение громкости применяется только для первого воспроизведения, а постепенное ее затухание - только для последнего. Основное предназначение REPEAT - создание фонового музыкального или звукового сопровождения, которое звучит все время, без переходов между повторным воспроизведением. Если вам обязательно необходим эффект нарастания/затухания звука при каждом проигрывании фрагмента, самым правильным будет соответствующим образом переделать сам трек, полностью отказавшись от использования FADEIN и FADEOUT.

Атрибут VOLUME позволяет задать относительную громкость воспроизведения звука. Его значением может быть целое число от 0 до 100, при этом 0 соответствует полной тишине, 100 - максимальному уровню громкости аудиофайла, а промежуточные значения - пропорционально уменьшенному уровню громкости (наподобие регулятора-крутилки звуковых колонок). Значения вне пределов диапазона 0-100 являются недопустимыми. Влияние атрибута VOLUME ограничивается тем треком, для которого он определен; он не меняет общий уровень громкости колонок, установленный на компьютере, а также громкость других треков, воспроизводимых одновременно с VOLUME-треком либо после него на том же уровне. Основное предназначение данного атрибута - дать автору игры контроль над относительной громкостью звуковых фрагментов, проигрываемых одновременно, с тем, чтобы достичь требуемого микширующего эффекта.

Атрибуты VOLUME и FADEIN/FADEOUT взаимодействуют очевидным способом. Значение атрибута VOLUME используется в качестве "номинальной" громкости основной части текущего трека, так что FADEIN постепенно увеличивает громкость от нуля до этого значения, а FADEOUT - наоборот, уменьшает от "номинала" до полной тишины. Иначе говоря, VOLUME задает абсолютный уровень громкости для трека, относительно которого осуществляется постепенное наращивание или затухание звука.

Обратите внимание, что не все интерпретаторы HTML TADS поддерживают разные уровни звука и их плавное изменение; те, которые не поддерживают, просто будут игнорировать соответствующие атрибуты.

Плавное изменение громкости

Плавное изменение громкости воспроизведения от нулевого уровня до максимума и обратно иногда называют фейдом. Фейды полезны, например, для сглаживания перепадов громкости двух воспроизводящихся подряд треков - сначала один трек затухает, затем начинается следующий трек, громкость которого постепенно нарастает.

Фейды влияют на воспроизведение только того трека, для которого они определены, и не оказывают действия на общий уровень громкости, установленный для компьютера или для игры. В частности, при постепенном нарастании громкости трека, воспроизводимого на уровне переднего плана, громкость звука на заднем плане меняться не будет.

HTML TADS для Windows поддерживает плавное изменение громкости звука, начиная с версии 2.1. Более старые версии (а также некоторые версии для других операционных систем) не поддерживают фейды, однако наличие соответствующих атрибутов в игре не приведет к нежелательным эффектам - эти атрибуты просто будут проигнорированы интерпретатором. Функция systemInfo() позволяет проверить мультимедийные возможности интерпретатора, в том числе наличие поддержки плавного изменения громкости.

В HTML TADS имеется пять основных режимов изменения громкости, управляемых атрибутами FADEIN и FADEOUT тега SOUND.

1. Увеличение громкости вначале трека. При проигрывании нового звукового файла можно задать для него постепенное увеличение громкости вначале, задав атрибут FADEIN в соответствующем теге SOUND. Указав FADEIN=секунды, вы зададите период в секундах, в течение которого громкость будет нарастать до максимума. Вот пример:

<SOUND SRC="song.mp3" FADEIN=1.75>

Длительность периода нарастания громкости в этом случае составит 1.75 с. Как нетрудно заметить, можно указать и дробное число секунд (отделив его точкой).

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

<SOUND SRC="song.mp3" FADEOUT=2.5>

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

Атрибуты FADEIN и FADEOUT можно комбинировать, чтобы задать для трека плавное нарастание громкости вначале и плавное ее затухание в конце:

<SOUND SRC="song.mp3" FADEIN=1.75 FADEOUT=2.5>

Как видно из вышеприведенного примера, длительности периодов нарастания и убывания громкости необязательно должны совпадать.

Обратие внимание, что атрибут FADEOUT в данном примере применяется только в том случае, если трек воспроизводится до конца. Если вы используете <SOUND CANCEL> или <SOUND INTERRUPT> для прерывания трека до его окончания, будет применена установка для затухания звука, указанная в теге прерывания воспроизведения.

3. Перекрестные фейды между двумя треками. Как уже говорилось выше, переходы между треками можно сгладить, используя постепенное затухание громкости в конце предыдущего трека и постепенное нарастание - вначале следующего. Иногда вы можете захотеть сделать переход от одного трека к другому еще более плавным - не только без резкого прерывания звука, но даже без "провала" с постепенным затуханием/нарастанием громкости. Одним из способов добиться этого является так называемый перекрестный фейд. Такое название носит эффект, когда предыдущий трек затухает, а новый трек одновременно с этим наращивает громкость. Поскольку два плавных, противоположных по направлению перехода громкости накладываются друг на друга, слышимый уровень громкости остается примерно постоянным во время всего перехода. Это означает, что слушатель не улавливает изменения уровня громкости, но и резкой замены одного трека другим также не происходит: первый трек просто постепенно переходит в другой. Звуковые перекрестные фейды часто используются в кинематографе при смене сцен; в текстовых квестах они могут использоваться в аналогичных ситуациях.

Чтобы создать перекрестный фейд в HTML TADS, можно дополнить атрибуты FADEIN и FADEOUT ключевым словом CROSSFADE. Просто укажите вместо FADEIN=длительность FADEIN=CROSSFADE,длительность, например:

<SOUND SRC="song.mp3" FADEIN=CROSSFADE,1.5 FADEOUT=CROSSFADE,1.5>

Если вы укажете FADEIN=CROSSFADE,длительность, то данный трек будет осуществлять наращивание громкости одновременно с затуханием звука у предшествующего трека, при этом для предшествующего трека автоматически будет выполнено затухание громкости с такой же длительностью, как если бы вы указали для предшествующего трека FADEOUT=CROSSFADE,длительность.

При указании FADEOUT=CROSSFADE,длительность текущий трек (т. е. тот, для которого указан этот атрибут) начнет приглушать громкость за указанную длительность до своего окончания, при этом следующий трек начнет проигрываться в момент начала этого затухания. Однако автоматического постепенного нарастания громкости для следующего трека не произойдет, соответствующий атрибут FADEIN для следующего трека необходимо задать в явном виде.

Обратите внимание, что перекрестные фейды, заданные атрибутом FADEIN, не будут работать для звуков, воспроизводимых случайным образом. Это связано с тем, что в этом режиме воспроизведения система дожидается определенного момента времени перед тем, как сделать выбор, какой именно трек проигрывать. Если для выбранного трека задан атрибут FADEIN=CROSSFADE, то применять его оказывается слишком поздно, поскольку предыдущий трек уже закончился. Корректным способом работы с перекрестными фейдами треков, воспроизводимых случайным образом, будет использование атрибута FADEOUT=CROSSFADE, которые работоспособны и при случайном воспроизведении треков, поскольку применяются в конце трека, когда выбор следующего трека уже осуществлен.

Аналогичным образом перекрестные фейды, заданные атрибутом FADEIN, не будут применяться для последнего трека в "закольцованном" (при помощи CYCLE) наборе. Хотя может показаться, что у системы достаточно информации для применения фейда в таком случае, на самом деле это не так: невозможно узнать заранее, не будет ли добавлен в очередь на воспроизведение в последний момент перед окончанием ее проигрывания еще один трек, поэтому система не может быть полностью уверена, что пользователь действительно хочет применить плавное изменение громкости к первому треку в очереди при циклическом переходе к ее началу. Правильным решением в такой ситуации опять-таки будет использование для этих целей атрибута FADEOUT.

4. Прерывание воспроизведения трека с постепенным затуханием громкости. Для досрочного прерывания звучания трека обычно используется атрибут CANCEL, описанный выше. В стандартном режиме звучание просто резко обрывается. Это может быть неприятно для слушателя, особенно если речь идет о постоянно играющей фоновой музыке. Зачастую этот нежелательный эффект можно сгладить, применив постепенное затухание громкости звука. Этого можно добиться, используя атрибут FADEOUT совместно с CANCEL:

<SOUND CANCEL=BACKGROUND FADEOUT=1.5>

Этим интерпретатору TADS сообщается, что для текущего трека, воспроизводимого на фоновом уровне, необходимо немедленно начать снижать громкость с такой интенсивностью, чтобы довести ее до нуля через полторы секунды. Когда это произойдет, трек будет считаться оконченным, как и при использовании обычного атрибута CANCEL, т. е. воспроизведение следующего трека (заданного новым тегом <SOUND>) может быть начато сразу после затихания предыдущего. Обратите внимание, что в приведенном выше примере не требуется ждать полторы секунды (до полного затухания звука), чтобы вывести тег <SOUND> для нового трека - этот тег может выводиться немедленно, а TADS поставит его в очередь на воспроизведение и начнет проигрывать, как только стихнет предыдущий звук.

5. Прерывание воспроизведения трека с перекрестным фейдом. При досрочном прерывании трека вы можете использовать также перекрестный фейд. Как мы только что видели, при совместном использовании FADEOUT и CANCEL стандартным поведением системы будет постепенное снижение до нуля громкости проигрываемого трека и начало воспроизведения следующего трека сразу после того, как это произошло. Однако, если вы используете значение CROSSFADE, воспроизведение следующего трека сможет быть начато немедленно при одновременном снижении громкости текущего трека. Например:

<SOUND CANCEL=BACKGROUND FADEOUT=CROSSFADE,1.5>

По данной команде громкость текущего трека начнет плавно снижатся, при этом заданный новым тегом <SOUND> трек сможет начать проигрываться немедленно, накладываясь на период уменьшения громкости текущего трека. Обратите внимание, что для постепенного увеличения громкости нового трека необходимо явно прописать атрибут FADEIN, в противном случае его воспроизведение начнется сразу на максимальной громкости.

Вы также можете прервать воспроизведение текущего трека и начать следующий одним тегом, используя запись <SOUND SRC=файл FADEIN=CROSSFADE,время INTERRUPT>. При этом новый трек начнет воспроизводиться сразу же, постепенно увеличивая громкость в течение указанного врмени, а для предыдущего трека громкость будет снижаться до нуля в течение того же периода. (Обратите внимание, что если для этого тега дополнительно задан атрибут FADEOUT, значение этого атрибута будет применяться только к новому треку; уменьшение громкости предыдущего трека все равно будет контролироваться установкой атрибута FADEIN нового трека. Это сделано с целью обеспечить одинаковую длительность интервалов изменения громкости для обоих треков, чтобы не происходило скачка громкости во время перехода от одного трека к другому).

Эти два метода (использование CANCEL с указанием нового тега SOUND vs "комбинированный" INTERRUPT) дают практически идентичный эффект - они оба ведут к немедленному плавному снижению громкости предыдущего трека, причем в фоновом режиме, чтобы обеспечить одновременное нарастание громкости следующего трека. Второй метод может оказаться несколько проще, поскольку требует всего одного тега. С другой стороны, первый метод позволяет чуть полнее контролировать ситуацию, поскольку позволяет задать интервалы снижения-нарастания громкости предыдущего и следующего треков независимо друг от друга. Собственно, интервал нарастания громкости для нового трека вообще можно не указывать - это может оказаться полезным, скажем, в случае, если трек сам по себе уже содержит фрагмент с нарастанием громкости.

Использование плавной регулировки громкости с REPEAT

Атрибут REPEAT разработан для создания фоновой музыки или звуковых эффектов, формирующих атмосферу в игре. При этом один или несколько звуковых фрагментов объединяются в цикл, проигрываемый неопределенное количество раз. Поскольку целью является создание непрерывного фонового звукового сопровождения, паузы и перепады громкости между отдельными фрагментами будут нежелательными. Поэтому и регулировки громкости при переходе от одного фрагмента к другому происходить не должно.

В связи с этим TADS будет применять атрибут FADEIN (при его наличии) только, когда повторяемый звук проигрывается в первый раз, а FADEOUT - в последний.

Если вы используете группу треков, задав для них SEQUENCE=LOOP или SEQUENCE=RANDOM, атрибуты изменения громкости обрабатываются следующим образом. FADEIN действует, как обычно, и это в принципе нормально; единственное, за чем нужно следить - не применять данный атрибут ни для какого трека в группе, кроме самого первого. FADEIN и здесь будет применяться только при первом воспроизведении трека, поэтому при повторном воспроизведении этого трека после завершения цикла (для SEQUENCE=LOOP) либо за счет случайного выбора (SEQUENCE=RANDOM) нежелательного изменения громкости не произойдет. Для атрибута FADEOUT TADS будет проверять очередь очередь на воспроизведение перед тем, как начать проигрывать очередной трек. Если эта очередь не пуста, то FADEOUT будет просто игнорироваться.

Если вам все-таки требуются плавные изменения громкости при переходе от одного трека в цикле к другому, то использованием FADEIN и FADEOUT этого не добиться. Однако есть простой путь обхода данного ограничения - достаточно отредактировать аудиофайлы таким образом, чтобы нарастание громкости вначале и ее уменьшение в конце были "встроены" в сам трек.

Звуки в баннерах

Теги <SOUND> могут использоваться только в главном окне игры. Их можно размещать внутри тегов <BANNER>, но треки, соответствующие расположенным таким образом звуковым тегам, по-прежнему будут считаться частью основного окна, которое будет определять хронометраж их воспроизведения и распределение по слоям.

Очистка экрана

Поскольку тег <SOUND>, по сути, представляет собой часть форматирующей разметки, определяющей внешний вид окна вывода, звуковые эффекты концептуально являются частью той страницы, на которой они появляются. Это означает, что при очистке экрана с использованием функции clearscreen() воспроизведение всех звуков будет прервано.

Если вы хотите использовать полноэкранную анимацию или другие эффекты, требующие стирания информации с экрана, но при этом хотите сохранить звуки, вам необходимо использовать баннер. Баннер позволяет заменять информацию на части экрана, не очищая все окно. При этом баннер может занимать всю площадь окна программы (для этого используется атрибут HEIGHT=100%).

Переносимость

На момент написания этой документации форматы MIDI, WAV и MPEG поддерживаются версиями HTML TADS как под 32-битную Windows, так и под "Макинтош". Формат Ogg Vorbis пока поддерживается только версией под Windows.

Когда (и если) появятся порты HTML TADS под другие операционные системы, возможно, что часть звуковых возможностей будет ими поддерживаться, но, вероятно, не в полном объеме и не для всех аудиоформатов. Работа со звуком требует специализированных аппаратных средств; не все компьютеры ими располагают, хотя у большинства более-менее современных машин они имеются. Форматы звуковых ресурсов, используемые в HTML TADS, не являются абсолютным стандартом, однако они достаточно широко распространены для того, чтобы считаться стандартом де-факто. Тем не менее, нельзя исключать того, что при портировании HTML TADS под другие платформы вспомогательные библиотеки будут доступны не для всех аудиоформатов.

Как автор, вы должны четко представлять возможные компромиссы, на которые придется пойти при использовании звука в игре. Например, вы должны помнить о том, что некоторые игроки могут использовать системы без поддержки звука, а другие предпочитают играть с отключенным звуком.

К счастью, в текстовом квесте сравнительно просто использовать звук в качестве вспомогательного средства, а не ключевой составляющей игры. Основным преимуществом использования звуковых эффектов в текстовых играх является возможность создания соответствующей атмосферы и настроения; хотя такие эффекты могут значительно обогащать игру, их можно исключить без катастрофических последствий, поскольку игра останется полностью проходимой и без них.

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


Ресурсы в Multimedia TADS

Если вы занимаетесь системным программированием под "Макинтош" или Windows (либо если вы когда-либо программировали графический пользовательский интерфейс), вы, скорее всего, знакомы с понятием ресурса, означающим некоторые данные (чаще всего двоичные), являющиеся внешними по отношению к программе и подгружаемые ею в ходе выполнения.

В этом контексте ресурсы используются для создания пиктограмм, определений меню и прочих объектов, с которыми неудобно работать, забивая их определения непосредственно в программу. Ресурсы также используются для вывода из состава программы, например, строковых констант, чтобы их можно было менять без перекомпиляции самой программы (что бывает полезно, например, при переводе на другие языки). Для большинства операционных систем с графическим интерфейсом существуют наборы инструментов, программные интерфейсы и определения файловых форматов, облегчающие манипуляции ресурсами.

В Multimedia TADS термин "ресурс" используется для сходного по смыслу набора средств, однако их реализация значительно отличается; чтобы не путать одно с другим, полезно запомнить, что обычные ресурсы операционной системы никогда не используются при работе в TADS.

Multimedia TADS позволяет автору игры включать в состав игры определенные типы данных, например, графические файлы JPEG и PNG. Для обычного языка HTML в обычном Интернет-браузере к таким объектам обычно обращаются, используя URL-адреса. Однако TADS не является обычным браузером и вместо URL-адресов использует ресурсы.


Назначение ресурсам имен

Автор игры может пользоваться ресурсами, обращаясь к ним из тега HTML в тексте, выводимом игрой. Когда содержащий тег текст выводится на экран, интерпретатор TADS автоматически загружает ресурс и отображает его так, как указано в теге.

Как уже упоминалось выше, в обычном HTML такого рода ссылка представляет собой URL-адрес, указывающий на некий файл, лежащий на веб-сервере. В HTML TADS вместо адреса используется имя ресурса.

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

   <IMG SRC="background.jpeg">

Таким образом браузеру дается команда загрузить изображение из файла с названием "background.jpeg" из того же подкаталога, в котором размещена текущая страница.

Ресурсы Multimedia TADS функционируют очень сходным образом, поскольку представляют собой, по сути, просто имена файлов. Местоположением "текущей страницы" для TADS всегда будет каталог, в котором расположен файл игры.

Пусть, например, интерпретатор TADS выполняется под Windows, проигрывая игру из файла C:\TADS\GAMES\MYGAME.GAM. Основной каталог, в котором TADS начнет искать ресурсы при обращении к ним - это каталог с файлом игры, т. е. C:\TADS\GAMES\. Если в своей игре вы используете следующий тег

   <IMG SRC="picture.jpg">

, то Multimedia TADS загрузит изображение из файла C:\TADS\GAMES\PICTURE.JPG.


Относительные ссылки

Имя ресурса может содержать "относительный путь" примерно в том же формате, как и для относительного URL-адреса. Поскольку интерпретатор TADS не работает с URL-адресами, то начинать имя ресурса с "http://", как для абсолютного URL-адреса, не следует. Напомним, что за "точку отсчета" в "относительном пути" принимается каталог с игрой.

В именах ресурсов TADS для разделения подкаталогов всегда используются прямые слэши ("/") вне зависимости от соглашений, принятых в операционной системе (обратный слэш ("\") в DOS и Windows, двоеточие на "Макинтошах" вплоть до MacOS 9, прямые слэши в NIX-подобных системах и MacOS X). TADS самостоятельно преобразует имена ресурсов к формату, используемому в текущей ОС, что исключает необходимость перекомпиляции игры с разными именами ресурсов под разные платформы.

Рассмотрим, например, случай, когда игра запущена под HyperTADS на "Макинтоше", и полное имя файла игры звучит как Macintosh HD:TADS:Games:MyGame.gam. Пусть игра выводит следующий тег:

   <IMG SRC="pics/skull.png">

HyperTADS автоматически преобразует его к названию в формате MacOS, считая, что это имя файла с путем, записанным относительно каталога с игрой, и попытается обратиться к следующему файлу: Macintosh HD:TADS:Games:pics:skull.png.


Чувствительность к регистру символов

При использовании букв верхнего и нижнего регистра в именах ресурсов необходимо быть внимательным. Сам по себе TADS не чувствителен к регистру, однако таковыми могут оказаться некоторые файловые системы (например, в UNIX, LINUX и MacOS X). Чтобы на таких системах не возникало ошибок, имена ресурсов должны совпадать с именами файлов в т. ч. с учетом регистра. Один из рекомендуемых подходов в данной ситуации - использовать везде только строчные символы.

Обратите внимание, что механизм Multimedia TADS, включающий ресурсы в состав файла игры, не чувствителен к регистру. Таким образом, если вы создаете игру в операционной системе с именами файлов, чувствительными к регистру символов, а затем перед релизом включаете ресурсы в состав файла игры, имена ресурсов не будут чувствительными к регистру. На первый взгляд, это упрощает жизнь автора, однако на самом деле тут есть одна проблема: если у вас есть два ресурса, чьи имена отличаются только регистром, Multimedia TADS будет обращаться к ним как к разным ресурсам, пока они находятся во внешних файлах, но окажется неспообен их различить после того, как они будут включены в состав файла игры. Таким образом, при разработке игры в среде с регистрозависимыми именами файлов надо следить за тем, чтобы имена ресурсов отличались не только регистром.

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


Поддерживаемые форматы изображений

Multimedia TADS поддерживает три формата изображений: JPEG, PNG и MNG. В идеале хотелось бы оставить в TADS поддержку только одного графического формата, чтобы облегчить портирование TADS под разные операционные системы; однако в настоящее время нет одного-единственного формата, который бы одинаково успешно решал все задачи, связанные с хранением изображений. К счастью, JPEG и PNG во многих отношениях удачно дополняют друг друга и поэтому способны закрыть большинство потребностей пользователей.

Обратите внимание, что формат GIF не поддерживается. Хотя данный формат широко распространен и популярен, я решил отказаться от его поддержки в Multimedia TADS в связи с патентными ограничениями системы сжатия данных в GIF. Формат PNG обладает всеми преимуществами GIF, при этом не содержит обременений, связанных с авторскими правами, и также широко распространен. Даже если ваш любимый графический редактор не поддерживает данный формат, найти необходимый конвертер в Интернете не будет проблемой.

Формат MNG сравнительно малораспространен, однако, как и GIF, поддерживает анимацию.


Поддерживаемые звуковые форматы

Подробно о поддерживаемых звуковых форматах см. в разделе Форматы звуков и музыки.


Расширения имен файлов

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

Обратите внимание, что расширение всегда отделяется от основной части имени точкой.


Включение ресурсов в состав файла игры

Чтобы упростить жизнь игроку при распространении игры, можно включить все ресурсы в состав файла игры. (Это также позволяет избежать "читерства" со стороны игроков, которые, в случае распространения игры совместно с набором графических файлов, могли бы эти графические файлы просматривать).

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

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

Самый простой способ включить ресурсы в состав файла игры - использовать соответствующие настройки компилятора.

Иногда бывает необходимо добавить ресурсы в файл игры "задним числом", без перекомпиляции самой игры. Для этого используется утилита - "менеджер ресурсов", которая имеется в составе дистрибутива TADS. Название исполняемого файла утилиты TADSRSC32.EXE. При использовании данной утилиты удобнее всего будет разместить все ресурсы в одном или нескольких подкаталогах того каталога, в котором лежит файл игры. Поскольку относительные пути также очень удобны для работы с внешними файлами ресурсов, этот способ организации файлов выбирает, пожалуй, большинство пользователей.

Предположим, ваши ресурсы расположены в двух подкаталогах с именами Rooms и Objects каталога, в котором лежит скомпилированный файл игры. Если ресурсы являются внешними файлами, обращение к ним будет происходить примерно так, как показано в следующем теге:

   <IMG SRC="Rooms/Cave.jpeg">

Для включения этих ресурсов в состав скомпилированного файла игры при помощи менеджера ресурсов нужно перейти в каталог с игрой и ввести в командной строке следующую команду:

   tadsrsc32 mygame.gam Rooms Objects

По ней будет запущен менеджер ресурсов с заданием включить все файлы в подкаталогах Rooms и Objects в скомпилированный файл игры (.GAM).

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

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


Использование внешних файлов ресурсов для распространения игры в нескольких конфигурациях

В наше время для большинства пользователей, пожалуй, размер файла игры не имеет большого значения, даже если ее приходится скачивать через Интернет. Однако в некоторых случаях "вес" игры является фактором, который приходится учитывать. В этом случае возможно два подхода.

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

Другой подход состоит в том, чтобы предложить свою игру в разных конфигурациях. При этом игра разбивается на два или несколько файлов, один из которых содержит только саму игру (в чисто текстовом виде или с минимальным количеством графических и звуковых ресурсов), а в остальных хранится весь мультимедийный контент игры. Можно пойти и еще дальше и предложить пользователю несколько мультимедийных файлов с разным уровнем качества графики и звука - для пользователей с быстрым и медленным доступом к Интернету.

Чтобы обеспечить вышеописанный функционал, Multimedia TADS позволяет упаковать ресурсы во внешний файл. Заметим, что для этого версия TADS должна быть не ниже 2.2.4, однако, поскольку данная версия была выпущена еще в прошлом тысячелетии, подавляющее большинство пользователей эту проблему просто не заметит.


Создание внешних файлов с ресурсами

Для создания внешнего файла с ресурсами используется тот же менеджер ресурсов, с помощью которого ресурсы включаются в файл игры. Единственное отличие состоит в том, что для создания внешнего файла необходимо указать в командной строке опцию -create:

   tadsrsc32 -create mygame.rs0 -add Rooms

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


Как происходит загрузка внешних файлов с ресурсами мультимедийным интерпретатором TADS

Каждый раз, когда Multimedia TADS загружает игру, он просматривает каталог игры на предмет наличия в нем файлов с расширением ".rsN", где N - цифра от 0 до 9. Например, если ваша игра называется GOLD.GAM, интерпретатор будет искать в ее каталоге также файлы GOLD.RS0, GOLD.RS1, GOLD.RS2 и т. д. Multimedia TADS откроет каждый такой файл и добавит ресурсы из него к ресурсам, имеющемся в файле .GAM.

Ресурсы во внешнем файле имеет более высокий приоритет, чем ресурсы в файле .GAM, т. е. при наличии двух ресурсов с одинаковым именем и в файле игры, и во внешнем файле будет использоваться ресурс из внешнего файла. Кроме того, если одноименные ресурсы имеются в двух и более внешних файлах, использоваться будет ресурс из файла с наибольшим числом в расширении (т. е., например, при конфликте ресурсов в файлах MYGAME.RS1 и MYGAME.RS3 будут браться ресурсы из MYGAME.RS3). Такая схема позволяет создавать несколько конфигураций мультимедийной игры для игроков с разными возможностями доступа к Интернету. Скажем, в файл игры можно включить ресурсы с низким уровнем разрешения (и малым объемом), а во внешний файл - ресурсы с более качественным изображением. В этом случае игроки, скачавшие внешний файл, автоматически увидят более качественные графические файлы, так как ресурсы из внешнего файла будут иметь приоритет.

Обратите внимание, что игрок имеет возможность указать интерпретатору путь ко внешним файлам с ресурсами. По умолчанию Multimedia TADS ищет ресурсы в том же каталоге, в котором лежит игра. Если игрок по каким-то причинам не может положить файлы с ресурсами в этот же каталог, он может указать опцию командной строки -respath при запуске интерпретатора:

   htmltads -respath d:\gold\res gold.gam

Вышеприведенная команда означает, что игра GOLD.GAM будет запущена из текущего каталога, однако файлы с ресурсами GOLD.RS0, GOLD.RS1 и т. д. будут браться из каталога D:\GOLD\RES.


Пример использования внешних файлов с ресурсами

Вышеописанный механизм обращения к ресурсам позволяет создавать разнообразные комбинации конфигураций игры для скачивания. Допустим, вы хотите создать две версии игры - одну для игроков с медленным Интернетом (качество хуже, но и размер компактнее), а другую - для быстрого Интернета (с более качественным и объемным мультимедийным содержимым). Для этого можно разместить изображения и звук в высоком качестве в одном каталоге (пусть он называется ResHQ), а затем сжать их со снижением качества и скопировать их в другой каталог (например, ResLQ). Далее при помощи менеджера ресурсов создаются два файла:

    tadsrsc -create mygame.rs0 -add ResLQ
    tadsrsc -create mygame.rs1 -add ResHQ

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

При выкладывании игры в сеть в дополнение к файлу игры можно разместить и два файла с ресурсами с соответствующими пояснениями - пользователи будут скачивать один из них в зависимости от своих желаний и возможностей.


Опции менеджера ресурсов

Существует два формата вызова менеджера ресурсов из командной строки:

  tadsrsc32 [файловые_опции] <имя_файла_ресурсов> [действия] 

либо

  tadsrsc32 [файловые_опции] <имя_файла_ресурсов> @<имя_файла_действий>

Второй случай аналогичен первому, однако действия не перечисляются в командной строке, а считываются из файла с именем имя_файла_действий.

Если ни опции, ни действия не указаны, будет выведено содержимое файла с именем имя_файла_ресурсов.

Возможна единственная файловая опция - -create, по которой создается новый файл с ресурсами.

Возможно указать следующие действия:

-type <тип> Позволяет указать тип ресурсов. Возможны два значения - XFCN (внешние функции) или HTML (графика и звук). Если эту опцию не указывать, тип ресурсов будет определяться на основании расширения файла: .bin, .com и . (пустое расширение) будут считаться внешними функциями, а все остальные - мультимедийными ресурсами.
-replace Добавляет или заменяет перечисленные далее ресурсы. Это действие будет принято по умолчанию, если не будет указано иного.
-delete Удаляет перечисленные ресурсы из указанного файла.
-add Добавляет перечисленные ресурсы в указанный файл, однако, в отличие от -replace, не заменяет уже существующие ресурсы новыми.

В качестве источника ресурсов (имя_файла_ресурсов) можно указать имя файла или каталог (тогда действие будет применено ко всем файлам в каталоге). Если указать имя_файла_ресурсов=имя_ресурса, то ресурсу из файла с именем имя_файла_ресурсов будет присвоено имя имя_ресурса (если указать просто имя файла, ресурс получит то же имя, что и файл-источник).


Совместимость файла игры с разными версиями интерпретаторов при включении в него ресурсов

Multimedia TADS использует тот же базовый формат файла игры, что и предыдущие версии TADS (версия формата "C"), поэтому скомпилированные в мультимедийной среде игры в целом будут нормально проигрываться прежними версиями интерпретатора. Однако для включенных в файл игры ресурсов HTML формат таки обновлялся, и совсем старые интерпретаторы, пусть и с мультимедийными функциями, их "не увидят".

Минимальная версия интерпретатора, обеспечивающая корректную работу с включенными в файл игры мультимедийными ресурсами - 2.2.3. При этом, если ресурсы не включать в состав игры, данное ограничение отсутствует. На практике для русскоязычных игр это вообще не будет проблемой, поскольку формат 2.2.3 достаточно древний - релиз состоялся аж в конце 1990-х годов.


Конвертация существующей игры на TADS в мультимедийную версию

Поскольку чисто текстовые игры нормально проигрываются на HTML TADS, преобразовывать их в мультимедийную версию можно постепенно, т. е. начать с малого набора изменений, а затем понемногу расширять этот набор.

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

Шаг 1: замена всех вхождений специальных символов

Все специальные символы HTML необходимо заменить на соответствующие им последовательности:

< на &lt;
> на &gt;
& на &amp;

Помните, что заменять эти символы требуется только тогда, когда они находятся внутри текста, выводимого на экран. Если они располагаются внутри исходного кода, заменять их не надо. Например, в нижеприведенном примере символ > находится в строке текста и должен быть заменен:

  if ( global.suchValue )
     "Отсюда -> сюда! ";

В то же время в следующем примере символы >, << и >> не выводятся на экран и потому заменяться не должны:

   if ( firstValue > secondValue )
   {
     "<<firstValue>> больше, чем <<secondValue>>! ";
   }

К сожалению, не существует простого способа дать текстовому редактору команду автоматически заменить только те специальные символы, которые являются частью текстовых строк, и не трогать все остальные. Даже если текстовый редактор поддерживает регулярные выражения (а интегрированная среда разработки TADS их поддерживает), задать нужный шаблон поиска для данного случая будет нетривиальной задачей, особенно, если вы новичок. Поэтому, возможно, самым легким способом замены специальных символов будет пройти по всему исходному коду простым текстовым поиском и вручную заменить проблемные символы. Это вряд ли займет много времени, так как обычно данные три символа нечасто используются в выводимом на экран тексте.

Шаг 2 (необязательный): замена управляющих символов чисто текстового интерпретатора TADS на их HTML-эквиваленты

В чисто текстовых интерпретаторах TADS используется большое количество специальных последовательностей символов, которые вы, если у вас возникнет такое желание, можете заменить. Например, в текстовых интерпертаторах двойная кавычка выводится при помощи последовательности "\"". При желании вы можете заменить все такие последовательности на комбинацию символов, принятую в HTML для достижения аналогичного эффекта - &quot;.

Возможно, в результате ваш код будет смотреться несколько аккуратнее, поскольку везде будет применено единообразное форматирование HTML. Однако необходимо подчеркнуть, что данный шаг не является обязательным, поскольку HTML TADS способен воспринимать форматирующие символы старых версий TADS в полном объеме. В то же время использование HTML в ряде случаев дает более широкие возможности по управлению форматированием.

Скажем, в обычном TADS для вставки табулятора используется последовательность \t. Эквивалент, используемый в HTML TADS - тег <TAB MULTIPLE=4>, позволяющий установить любую длину табулятора. Другой пример - замена обычных двойных кавычек - " " - на типографские кавычки: « ».

Аналогично можно заменить открывающие и замыкающие последовательности выделения текста \( и \) на теги полужирного шрифта <B> и </B>, либо курсива <I> и </I>, либо на сочетание этих тегов. Эквивалентом последовательности перевода строки \b будет <P>, а окончания строки \n - <BR HEIGHT=0>. Тег HEIGHT в данном случае позволяет создать новую строку произвольной высоты (в данном случае нулевой).

Шаг 3: обновление кода, формирующего строку статуса

Примечание переводчика: текст в этом разделе скорее относится к переходу с версий TADS тех времен, когда никакой русификацией библиотек и не пахло. У меня есть ощущение, что данный шаг можно было бы удалить целиком - подавляющее большинство создававшихся ранее и теперь русскоязычных игр на TADS написаны под мультимедийную версию интерпретатора (собственно, я, пожалуй, не знаю ни одной игры на русском языке, которая писалась бы не под HTML TADS, пусть и без графики/звука). Тем не менее, я этот раздел сохранил - для истории и на всякий случай.

Строка статуса - это единственный пункт процесса преобразования игры в формат HTML, который может быть сопряжен с некоторыми трудозатратами; впрочем, в некоторых случаях делать вообще ничего не придется. Это целиком зависит от того, использует ли ваша игра строку состояния из библиотеки advr.t без изменений, или вы написали для нее свой собственный код.

Если в вашей игре вы просто использовали строку статуса из библиотеки advr.t и никак ее не модифицировали, у вас есть повод для радости - ничего делать не придется. Современные версии данной библиотеки позволяют эмулировать поведение строки статуса старых игр при помощи новых возможностей тега <BANNER>. Все, что вам нужно - заменить старую версию библиотеки advr.t новой. Проще некуда.

Однако если вы что-то делали со строкой статуса, чтобы добиться неких спецэффектов, вам потребуется переписать соответствующий код.

Баннеры (описанные немного выше) достаточно просто использовать -требуется всего лишь указать тег <BANNER> в коде игры. Каждому баннеру можно поставить в соответствие уникальный идентификатор, так что можно использовать неограниченное их количество.

В отличие от обычной строки статуса TADS, с которыми работают два разных участка кода, баннеры определяются сразу целиком в соответствующем теге. Таким образом, если код для вашей строки статуса разделен на две части, одна из которых обновляет левую часть строки при помощи метода statusLine, а другая - правую часть при помощи функции setscore(), при использовании баннера вам потребуется несколько изменить подход.

Одним из таких подходов может быть определение двух глобальных переменных - одна для текста, выводимого в левой части, а другая - в правой. Это могут быть строковые переменные, обновляемые теми самыми двумя разными участками кода. Затем после очередного хода игрока тег <BANNER> будет выводиться на экран, при этом в нем будут отображаться вышеуказанные глобальные переменные - например, при помощи функции say(). Конечно, можно сделать и по-другому - вовсе отказаться от схемы "правая часть - левая часть" и реализовать что-то принципиально иное (баннеры это позволяют), однако описанный выше подход является, пожалуй, наиболее простым, если необходимо с минимальными усилиями переделать существующий код.

Обратите внимание, что при этом вам следует исключить переводы строки (символы \n) из выводимых в баннере строк. Стандартный метод statusLine в этом случае просто переведет строку, в баннере же будет вставлена пустая строка, из-за чего его высота увеличится (если только она не была задана явно), что, в свою очередь, может привести к проблемам с форматированием.

Еще одна ключевая особенность, о которой необходимо помнить, создавая игру под мультимедийный интерпретатор, заключается в том, что в методе statusLine не следует размещать вызов setscore(), а также осуществлять вывод любого текста на экран. Это очень важно. Игра для мультимедийного интерпертатора вообще не должна обращаться к "старому" методу statusLine, поскольку он не учитывает особенностей форматирования при выводе текста в HTML. (Именно поэтому в более-менее современных версиях библиотеки advr.t вместо него используется метод statusRoot). Если вы обратитесь к statusLine из мультимедийной игры, выводимый этим методом текст попросту будет выведен не в строке статуса, а у приглашения на ввод команды, что почти наверняка является нежелательным.

Однако, обобщая все вышесказанное, необходимо отметить, что иногда вам все-таки потребуется использовать старые методы для отображения текста в строке состояния - а именно в том случае, если игра должна идти и на мультимедийном интерпретаторе, и на старых текстовых. В нижеприведенном примере мы исходим из того, что где-то вначале игры (например, в функции init) проводится проверка, поддерживает ли интерпретатор, на котором запущена игра, мультимедийные возможности, после чего результаты этой проверки записываются в свойство global.htmlEnabled. Кроме того, считаем, что текст для левой и правой части строки статуса сформирован и записан в соответствующие глобальные переменные.

  if ( global.htmlEnabled )
  {
    // Интерпретатор поддерживает мультимедийные возможности
    "<BANNER ID=StatusLine HEIGHT=PREVIOUS><BODY BGCOLOR=SILVER TEXT=BLACK><B>";
    say( global.leftStatusText );
    "</B><TAB ALIGN=RIGHT>";
    say( global.rightStatusText );
    "</BANNER>";
  }
  else
  {
    // Интерпретатор является чисто текстовым
    setscore( global.rightStatusText );
  }

Обратите внимание, что такой код не будет обновлять левую часть строки статуса в интерпретаторах без мультимедийных возможностей. Чтобы исправить это, необходимо, чтобы для класса room метод statusLine был определен примерно следующим образом:

  statusLine =
  {
    if ( not global.htmlEnabled )
      say( global.leftStatusText );
  }

Такая строка статуса будет полностью совместима как со старыми чисто текстовыми интерпретаторами, так и с современными мультимедийными.

Шаг 4 (необязательный): включение в игру мультимедийного содержимого и форматирование текста

Итак, вы завершили необходимые базовые шаги для преобразования игры в форму, совместимую с мультимедийным интерпретатором. Теперь можно приступать к добавлению мультимедийного содержимого в игру, ради которого, собственно, все и затевалось. Однако хорошим тоном считается не забывать и о тех пользователях, которые пользуются чисто текстовыми интерпретаторами (и их не так мало, как может показаться - например, многие современные универсальные проигрыватели, такие как Gargoyle или Spatterlight, не поддерживают мультимедийные возможности для TADS). Чтобы такие пользователи не были "ущемлены в правах", необходимо организовать в коде игры соответствующие проверки.

Зачастую при использовании сложного форматирования HTML текст в интерпретаторах без соответствующего функционала "слетает". Особенно страдают таблицы. Для проверки поддержки интерпертатором возможностей HTML можно использовать функцию systemInfo - например, так:

   if ( systemInfo(__SYSINFO_HTML ) = 1 )
   {
     // вывод таблицы с HTML-форматированием
   }
   else
   {
     // Вывод эквивалентного текста без использования HTML
   }

Обратите внимание, что systemInfo возвращает 1, если интерпретатор поддерживает HTML, и 0 в противном случае, так что не пытайтесь проверять ее на nil или true.

Еще можно отметить, что, начиная с версии 2.2.4, даже текстовые интерпретаторы TADS "понимают" некоторые теги HTML (например, <P>, <BR> and <B>), и эмулируют их, используя традиционные управляющие последовательности TADS с обратным слэшем (\). При этом systemInfo(__SYSINFO_HTML ) все равно вернет для них 0. Это еще более упрощает написание игры, если она использует только базовые теги HTML. Более подробная информация по этой теме приведена в приложении H.

Шаг 5: включение поддержки HTML

Наконец, как было уже описано ранее в этой главе, предусмотрите где-нибудь в своей игре (чаще всего это делается в функции init()) вывод последовательности "\H+", чтобы включить интерпретирование разметки HTML.


- Ого! - вскричал генерал, смотря на образчик каллиграфии, представленный князем, - да ведь это пропись! Да и пропись-то редкая! Посмотри-ка, Ганя, каков талант!
ФЕДОР МИХАЙЛОВИЧ ДОСТОЕВСКИЙ, Идиот (1869)

Глава восьмая Содержание Приложение A