16. АНИМАЦИЯ

Анимацией на компьютере я буду называть живое изображение с музыкой. Есть много способов создания потока картинок и звуков. Самый сложный их них -- показ видеороликов или кино. Для этой цели обычно входной поток записывают с файл специального формата, например, mp4 или wmv и затем проигрывают с помощью специальных программ -- проигрывателей. Файлы таких фильмов, как правило, имеют огромные размеры даже при относительно плохом разрешении изображений и очень плотном сжатии информации. Более простой вариант -- это автоматическое слайд-шоу, когда картинки показываются одна за другой с некоторой паузой, а музыка разделяется на фоновую и комментарии. Такой вариант более похож на документальный фильм, в котором дается некоторая словесная информация на фоне показа документов. Источниками слайд-шоу могут служить отдельные картинки, каждая в своем файле, и отдельные звуковые файлы -- аудиоклипы. В этом случае можно показывать большие изображения на весь экран. Создание таких слайд-шоу при наличии определенного числа фотографий -- очень простая задача. При этом звуковые комментарии можно записать через микрофон. В языке ACL реализован относительно простой механизм показа автоматического слайд-шоу. Но при разработке дополнительного кода его можно сделать и более фасонным и сложным. Более того, этот механизм пригоден также для визуализации некоторых процессов, описываемых математическими уравнениями, например, движения шаров упруго сталкивающихся со стенками сосуда и между собой.

В этом разделе дано описание команды #ag (animation graphics), которая позволяет реализовать анимационную графику и аудио-клипы. Сама команда имеет относительно простую структуру, потому что она предлагается для использования в комплексе с графическими командами #g и #eg, описанными выше, и использует только готовые картинки, записанные в память. Анимация создается использованием пяти операций. В названии операции достаточно записать только первую букву. Ниже описаны эти операции.

.

 #ag [op=o; wid=; hei=; xs=; ys=; file=;] FT

Эта операция открывает окно, в котором будет показываться анимация. Параметры [wid] и [hei] определяют полные ширину и высоту этого окна в пикселах экрана. Положение окна (левый верхний угол) на экране определяется параметрами [xs], [ys] относительно аналогичного угла экрана. Заголовок окна задается аргументом FT (форматированный текст). Предполагается, что эта операция должна быть выполнена до цикла. Если параметр [file=nomusic;] фоновой музыки не будет. То же самое происходит, когда файл указан, но он отсутствует в рабочей папке. Если же параметр [file] указывает на имя аудио клипа с расширением ".wav" (формат wave), ".au", ".aif" (формат aiff) или ".mid" (формат midi) начнет играть музыка в зацикленной моде, то есть музыка повторяется бесконечно долго. Наиболее разумно использовать формат midi, так как он компактный и вполне годится для фоновой музыки. Можно записывать файл с фоновой музыкой внутрь jar-файла программы в папку [resources]. Это удобно для модификаций программы в виде спец-окна или проигрывателя, см. главу 25. Для этого перед именем файла надо поставить символ &. В новых версиях JRE поле окна остается прозрачным, поэтому его надо сразу же заполнить следующей командой.

.

 #ag [op=m; n=; xs=; ys=; file=;] FT

Эта операция показывает картинку, записанную в память компьютера с номером [n] на поверхности анимационного окна. Она также меняет текущее содержание титульной строки анимационного окна. Новое содержание задается аргументом FT. Картинка будет расположена таким образом, что центр картинки будет смещен из центра области анимационного окна на вектор [xs], [ys]. Здесь есть некоторая особенность, о которой нужно помнить. Анимационное окно имеет вертикальную полосу с названием и крестиком справа. Если вы хотите поместить картинку с размерами W и H полностью в поле окна, то вертикальный размер анимационного окна нужно задавать как H+26, а саму картинку надо поставить на 13 позиций вниз, то есть ys=-13. По горизонтали картинка будет в центре при xs=0. И еще одна особенность. Если картинка не заполняет все анимационное окно, то остальная часть остается белой. Предыдущая картинка в этом окне исчезает полностью. То есть новая картинка на старую не накладывается.

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

Время анимации зависит от числа повторений в цикле. В том числе можно записывать бесконечный или очень большой цикл. В таком режиме единственный способ остановить показ -- закрыть окно кликом на крестике справа в верхней полосе с названием. В этот момент все циклы блокируются таким образом, что повторений не происходит, то есть тело любого цикла выполняется только один раз. Восстановить нормальный порядок позволяет команда #ini. Если [file=nomusic;] или параметр [file] указывает на несуществующий файл, то ничего не происходит. Однако если файл указывает на файл аудио-клипа, то последний будет звучать, но только один раз (без зацикливания). Можно записывать файл с музыкой внутрь jar-файла программы в папку [resources]. Это удобно для модификаций программы в виде спец-окна или проигрывателя, см. главу 25. Для этого перед именем файла надо поставить символ &.

Вообще говоря, одновременное проигрывание музыки и приготовление следующего кадра влияет на качество музыки. Поэтому разумно использовать вариант, когда музыка отсутствует в момент приготовления картинки и играет, когда картинка показывается в течение 5 или 10 секунд. Программу на это время можно останавливать командой #rob. При этом различные картинки могут сопровождаться разной музыкой или речевыми комментариями. Программист может отключить аудиоклип, задавая [file=nomusic;], но одновременно включить его командой #so [op=psf;]. Однако в новых JRE последняя команда не работает, вероятно это ошибка разработчиков. В версии 1.4.2 все работало. Есть еще одна особенность у новых версий, а именно, анимационное окно выставляется прозрачным и оно показывает то, что было на экране до его вызова. Более того, если открыть временно окно другой программы, то часть этого окна так и останется на экране. Мне непонятно зачем это сделано, но бороться с этим можно только одним способом -- поместить фоновую картинку на полный размер окна.

Эта команда также позволяет показывать картинки, которые динамически рисуются в цикле по изменяющимся параметрам. В этом случае если вы не задаете музыкальный файл, то параметр [file=nomusic;] надо ставить, так как на проверку наличия файла уходит время. Ее можно использовать и для создания интерактивных игр, потому что она возвращает информацию о действиях пользователя. Если пользователь в процессе показа нажимал левую клавишу мыши, или просто двигал мышь, или двигал при нажатой клавише, или нажимал клавиши клавиатуры, то вся эта информация может быть получена после выполнения команды. Код нажатой клавиши возвращается в параметр s(2), модификатор (код нажатой клавиши одновременно с нажатием левой клавиши мыши) возвращается в параметр s(1),. Он же и просто сигнализирует о простом клике, параметр s(108) показывает какой клик был сделан, то есть сколько щелчков было произведено одновременно (с короткой паузой). При однократном клике он равен 1, при двойном клике 2 и так далее. Параметры s(102) и s(103) возвращают текущие координаты мыши в поле анимационного окна. Если проводилось перемещение мыши с одновременно нажатой левой клавишей, то координаты в момент отпускания клавиши также возвращаются в параметры s(104) и s(105). Конкретные значения этих параметров описаны в разделе 13 при описании команды #w [op=im;].

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

.

 #ag [op=i;]

которая обнуляет все данные о произведенных действиях, после чего операция [op=m;] снова будет возвращать нули во всех параметрах до тех пор, пока пользователь не произведет следующее действие. Но для создания квази-диалогового режима, когда программа не идет дальше и ждет реакции пользователя, сделана специальная операция

.

 #ag [op=p;]

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

.

 #ag [op=c;]

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

К этой команде добавлена еще одна независимая операция

.

 #ag [op=s;] FT

Она запускает готовую программу слайд-шоу, в которой картинки меняют друг друга с переходами. Особенность этой программы в том, что она может показывать картинки, размещенные не только на локальном компьютере, но и в интернете. Работает она по специальной программе -- протоколу, который должен быть определенным образом приготовлен в файле. Полный путь к этому файлу, а точнее URL, является аргументом этой команды. При этом аргумент для файлов на локальном компьютере должен выглядеть так
File:C:/folder1/folder2/..../file
Но файл протокола может находиться и в интернете, тогда аргумент надо задавать так же, как в браузерах, то есть
http://computer/folder/file
Для задания файла на локальном компьютере, если он расположен в одной из папок внутри папки интерпретатора, полезно иметь возможность получить полный путь к папке интерпретатора vkACL.jar. Этот путь можно получить, используя формат \M . Так, если протокол находится в той же папке, где и запущенная acl-программа и файл протокола имеет название show.vks, то путь легко сформировать следующим образом \M\H/show.vks. Правила, по которым записывается файл протокола, написан в отдельном файле, который можно посмотреть по ссылке
.

Рассмотрим некоторые примеры использования операций данной команды. Пусть картинка bridge.jpg имеет размеры 640*480. Программа

 #ag [op=o; wid=640; hei=506; xs=0; ys=0; file=trippy.mid;] AudioClip\E
 #w [op=im; sav=2; c=0; mo=0; file=bridge.jpg;]
 #ag [op=m; n=2; file=nomusic; xs=10; ys=-30;]
 #rep 1000 #rob [mo=1;le=1000;] #end 
 #ag [op=c;] #ini 

показывает эту картинку в левом верхнем углу эурана и играет аудио-клип в течение 1000 sec. При этом команда #rob не должна держать программу столь долгое время, иначе ее невозможно будет прервать. Вместо этого команда помещается в цикл и держит программу только в течение одной секунды. Закрывая окно пользователь одновременно останавливает музыку. Следующая программа показывает много картинок размером 960*720

 #p [xsh=s(106)/2-482; ysh=s(107)/2-373;]
 #ag [op=o; wid=964; hei=746; file=trippy.mid;] Marmaris\E
 # j=1; #rep 89 # s(3)=1001; #pri 49\Tj 5 e.jpg\E
 #w [op=im; sav=2; c=0; mo=0; file=\T1001 12\E]
 #ag [op=m; n=2; file=nomusic; xs=2; ys=-13;]
 #rep 12 #rob [mo=1; le=500;] #end # j=j+6;
 #end #ag [op=c;] #ini

Она также играет один аудио-клип в цикле. Окно анимации помещается в центре экрана. Окно на 4 пиксела шире картинки, а сама картинка на два пиксела смещена вправо. Такие тонкости тоже целиком в ваших руках. Имена файлов различных картинок составляются путем копирования фрагментов имен файлов из текстового массива, заготовленных заранее. Картинки показываются быстро и не портят музыку.
Более сложная программа может быть сделана в виде специальной процедуры, которую можно оформить в виде супер-команды (см. раздел 3). Ниже показан вызов супер-команды ##mjpgm

 # s(3)=1; #pri movie/marmaris * trippy.mid 0 90 7500 0 \E ##mjpgm

Перед вызовом суперкоманды напечатаны ее входные данные. Это имя папки с файлами, символ * указывает что имена файлов не имеют заголовка, только трехзначные числа. Далее следует имя файла с фоновой музыкой, далее следуют 4 числа: начальный номер видео-файлов, число кадров, время задержки в миллисекундах и начальный номер аудио-файлов. Сама супер-команда записана в файл "mjpgm.acl" в папке "proc". Ниже показан ее текст

 #text [op=trim; b=s(4); le=s(5); n=4001;]
 # A=i(4001); B=i(4002); C=i(4003); D=i(4004); E=i(4005); F=i(4006); N=s(3);
 #read [fir=G; n=4; b=i(4007); le=s(4)+s(5)-i(4007);]
 #d 3 i(1) 200 200 200 #col [b=1; le=1; fir=i(1);]
 #g [op=open; twi=51; the=720; col=1;]
 #g [op=clos; c=0; sav=2;] no\E
 #f [op=fold; file=\TA B\E]
 # J2=J-G; J=G; P=H; I=I/10; &=0;
 #case 0
  #sel [nx=3; ny=1; mo=0; wid=120; hei=40; col=255; tsi=20;] 
  Select variant\E Start|Continue|Exit\E # Z=&;  
  #case 1  # J=G; P=H; M=1; #end |
  #case 2  # &=(J-G)<1; #case 1 # J=J-1; #end | # P=H+G-J; M=1; #end |
  #case 3 # M=0; #end |
  # &=M; #case 1
   #ag [op=o; wid=1024; hei=746; xs=0; ys=0; file=\TE F\E] \TA B\E
   # L=0; &=D; #case 1 # &=t(C); #case 42 # L=1; #end | #end |
   #rep P  # &=L;
    #case 0  #p [file=\TC D\I-3 J; .jpg\E] # J1=J+J2; #pri \TC D\I-3 J1;\E  #end |
    #case 1  #p [file=\I-3 J; .jpg\E] # J1=J+J2; #pri \I-3 J1;\E  #end |  
    #w [op=im; mo=0; sav=3; c=0;]
    #ag [op=m; n=3; xs=0; ys=-13; file=nomusic;]
    #f [op=size; file=\Ts(4) s(5) .wav\E] # &=s(1)<1;
    #case 1 
     #sou [op=psf; n=1; c=2; siz=500; sty=0; mo=0; le=99;] \Ts(4) s(5) .wav\E
    #end |
    #rep 10 #rob [mo=1; le=I;] #end
    # O=-484; #p [op=m; n=2; ysh=0; file=nomusic;]  
    #rep 10  # Q=O;
     #rep 2 #ag [xsh=Q;] #rob [mo=1; le=15;] # Q=-Q; #end # O=O+51;
    #end
    # J=J+1; 
   #end  #ag [op=c;] #ini 
  #end |
  # &=(2-Z)<0; 
 #end 

Эта программа обрабатывает входные данные из последней записи в текстовый массив, вынимает из нее нужные имена и числа. Затем она готовит картинку в виде полоски светло-серого цвета. Затем организует бесконечный цикл (вертушку). Это позволяет прервать демонстрацию в любой момент, а потом продолжить ее с прерванного места. Выход также осуществляется через кнопку меню. Показ анимации начинается обычным образом. А при показе кадров делается проверка на наличие шапки в имени файлов. Если *, то имя файла формируется без шапки - только трехзначное число. Имя звукового файла отличается только расширением ".wav" вместо ".jpg". При показе кадра аудиоклип не запускается, но затем запускается командой #so при условии, что файл существует. После запуска звукового файла делается пауза а затем картинка динамически замазывается серым цветом (полоска серого цвета замазывает картинку кусками в цикле). После этого происходит переход к следующему кадру. Можно делать и более фасонную смену кадров. Однако использование многих копий картинки в цикле будет мешать музыке. Так что требуется экспериментальный подбор. К сожалению обработка картинок в языке Java делается довольно медленно.

Использование этой команды для программирования анимационных игр целиком зависит от фантазии программистов. Можно рисовать и перерисовывать разные картинки на которых выставлять псевдо-кнопки и псевдо-меню, а также движущиеся объекты. Можно делать нечто вроде шашек или шахмат, то есть перемещать фигуры после серьезного анализа ситуации и многое другое. Примеры можно посмотреть в программе [pro/game.acl] или в списке встроенных программ.