My:Abs — различия между версиями

Материал из synset
Перейти к: навигация, поиск
(Менеджирование сцен)
 
(не показаны 202 промежуточные версии этого же участника)
Строка 1: Строка 1:
{{TOCright}}
+
'''Название''' «Кровавая Графиня»
  
Список начальных задач для редактора уровней.  
+
[[Файл:gerb.png|right|200px]]
Необходимо этот список откорректировать, расширить и проставить ориентировочные сроки выполнения задач.  
+
'''История'''
 +
* [http://ru.wikipedia.org/wiki/%D0%91%D0%B0%D1%82%D0%BE%D1%80%D0%B8,_%D0%95%D0%BB%D0%B8%D0%B7%D0%B0%D0%B2%D0%B5%D1%82%D0%B0 Эржебет Бато'ри], Венгрия, 7 августа 1560 - 21 августа 1614 (54 года)
 +
* Венчалась в 11 лет, замуж вышла в 15. Пять детей (Анна, Екатерина, Миклош, Урсула и Павел)
 +
* Муж - Ференц Надашди. Всё время проводил в военных походах против турок, был прозван «Чёрный бей» («Чёрный витязь»); умер в 1604 г.
 +
*[http://ru.wikipedia.org/wiki/%D0%A7%D0%B0%D1%85%D1%82%D0%B8%D1%86%D0%BA%D0%B8%D0%B9_%D0%B7%D0%B0%D0%BC%D0%BE%D0%BA Чахтицкий замок] в словацких Малых Карпатах расположен на холме 375 м над уровнем моря
 +
* [http://ru.wikipedia.org/wiki/%D0%A0%D0%BE%D0%B4_%D0%91%D0%B0%D1%82%D0%BE%D1%80%D0%B8 Герб]: 3 горизонтальных зуба дракона, который держит щит и обвивает шею своим хвостом
 +
*  29 декабря 1610 г  палатин Венгрии граф Дьёрдю Турзо  ворвался в замок Елизаветы Батори и, как утверждают, застиг её с подручными прямо на месте преступления — пытающими очередных жертв.
 +
* Остаток жизни Елизавета провела в заточении в подземной темнице собственного Чахтицкого замка, где она прожила три с лишним года и умерла в ночь на 21 августа 1614 г.
  
==  Менеджирование сцен ==
+
'''Легенда''' «Кровавая Графиня»
 +
* 650 убитых девушек из крови которых Батори делала омолаживающую ванну
 +
* [http://foxalesya.mindmix.ru/1052-299-jerzhebet-batori-elizaveta-batori.zhtml Говорят, что до сих пор по ночам из проклятого замка раздаются стоны, приводящие в ужас округу]
  
* Создание окна древовидного списка сцен (добавление, перенос, переименование). Группировка списка сцен делается для удобства пользователя и не имеет отношения к логике взаимодействия сцен и лейаутов.  
+
[[Файл:bathory_face.png|right|200px]]
* Задание размеров экрана (лейаута). Выбирается из списка. В список можно добавлять лейауты с указанием их размеров. При установлении данного лейаута, появляется область редактирования, отмеченная рамкой с прямоугольной сеткой.
+
[[Файл:bathory_vedma.png|right|200px]]
* Создание новой сцены, задание ее размеров. Активная сцена отображается в виде рамки на лейауте. Начальное положение сцены по центру лейаута, затем она может быть мышью перемещена по нему. Для размера сцены по умолчанию используются параметры последней созданной сцены (последовательное создание однотипных сцен).
+
'''Фильм''' «[http://rutracker.org/forum/viewtopic.php?t=3387944 Кровавая графиня - Батори]»  (Юрай Якубискоб, 2008)
* Создание окна опций с закладками (лейаут, сцена...). В опциях сетка вкл/выкл., задается ширина и высота ячейки сетки; изменяется размер лейаута; размер текущей сцены.
+
* Занималась цилительством, препарировала трупы.
 +
* Был роман с придворным итальянским художником [http://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D1%80%D0%B0%D0%B2%D0%B0%D0%B4%D0%B6%D0%B8%D0%BE Караваджио].
 +
* Муж в отместку пытался отравить Караваджио, но вино выпила Эржебет
 +
* Эржебет спасает ведьма Дарвулия (правый глаз зеленый, левый - голубой), которая становится советницей Эржебет.
 +
* Ведьма, знала тайну "здоровой крови" и давала Эржебет напиток, сохраняя её молодость. Возможно Дарвулия убила несколько девушек.
 +
* После смерти мужа на Эржебет и её земельные владения стал претендовать [http://ru.wikipedia.org/wiki/%D0%A2%D1%83%D1%80%D0%B7%D0%BE,_%D0%94%D1%8C%D1%91%D1%80%D0%B4%D1%8C Дьёрдя Турзо], соратник мужа и их сосед.
 +
* Жена Турзо, помогая мужу, начинает подставлять Эржебет, убивая девушек. Параллельно, католическая церковь множит слухи (Эржебет протестанка).
 +
* Постепенно от снадобья Дарвулии Эржебет начинает терять рассудок; у неё видения. В приступе помешательства Эржебет убивает ножницами свою служанку Сару, которая нечайно ранила Эржебет, подстригая её.
 +
* Осознав, что во всем виновато снадобье ведьмы, Эржебет  заточила Дарвулию в подземелье. В последствии, над мертвым телом Дарвулии, Эржебет просит у неё прощения 
 +
* У Эржебет  была ванна, заполненная отварами трав, которые имели красноватый цвет
 +
* Сжигает своё лицо, вырезанное из полотна Караваджио, когда тот умирает.
 +
* По сфабрикованным обвинениям Турзо, была заточена, а её служанки сожжены (предварительно им отрубили пальцы). В заточении Эржебет  умирает.
 +
* Хотя Турзо виновен в её смерти, он любил её до конца жизни. Считал достойным соперником. Через сюжет проходит его игра с Батори в шахматы, в которой она его обыграла. "Она выиграла эту партию." Через 2 года он умер.
  
=== Замечания ===
+
{|
 +
|
 +
'''Цитаты'''
 +
* "Чем больше легенд, тем меньше доказательств."
 +
* "Все должны состариться, кроме лиц на холстах."
 +
* "Картина это нарисованное стихотворение."
 +
* "Картина сохранит, то, что время уничтожит."
 +
* "Нет ничего вечного, даже лиц на картинах."
 +
* "Список Ваших жертв? - Вылеченных жерв!"
 +
* "Почему меня покидают все, кого я люблю?"
 +
* "Умная женщина может стать для мужчины гибелью."
 +
|
 +
|
 +
'''Символы - предметы''':
 +
* нож с двумя выскакивающими лезвиями - рана как укус вампира;
 +
* белая маска в которой Батори спала;
 +
* веницианская роза ("голубая, как небо Венеции") - символ Караваджио;
 +
* гербарий (книга) лечебных трав Батори;
 +
* круглое зеркало ведьмы, дающее картины будущего;
 +
* шахматы - большие, по пояс фигуры;
 +
* книга с историей Батори, которую вел монах;
 +
* «Турзо» - надпись кровью, которую умирая, сделала ведьма;
 +
|}
 +
----
  
* Все окна не модальные, находящиеся поверх приложения; за основу взять интерфейс любого граф.редактора (flash и т.п.)
 
* Внутри сцены может быть размещена другая сцена (древесная иерархия вложенности); координаты сцен относительно их родителя.
 
* В активной сцене можно просмотреть список подсцен и объектов которые с ними связаны.
 
* На лейауте может находиться несколько сцен.
 
* Одна и та же сцена может находиться на разных лейаутах в различных местах.
 
* У сцены кроме уникального имени есть ее тип ("поисковая область", "инвентарь" и т.п.). Тип выбирается из listbox-а и может быть туда добавлен. Тип нужен для групповых операций. Например задать одинаковые координаты в лейауте всем сценам данного типа.
 
* Каждая корневая (лежащая на лейауте) сцена помнит свои положения на лейаутах различного типа, на которых она "просматривалась".
 
  
== Простой редактор ==
+
'''Машина состояний''' (state machine) является универсальным объектом для программирования
 +
в редакторе сцен сложного поведения объектов. Для машин с типовым набором состояний и поведений, в дальнейшем будут вводиться отдельные объекты.
  
* Перетаскивание из редактора ресурсов (РР) одного объекта на сцену. Если координаты объекта не определены, по умолчанию центрируется относительно сцены
+
Логика поведения машины состояний разбивается
* Перетаскивание на сцену папки - группы объектов.
+
на отдельные узлы (состояния). Объект всегда находится строго в одном состоянии.
* Вокруг объектов на сцене рисуются рамки (откл/вкл в опциях).
+
Переход из одного состояния в другое происходит либо в результате внешнего воздействия на объект, либо в результате окончания некоторых процессов протекающих внутри объекта.
* При клике на объкт появляется рамка другого цвета (активный объект). Этот объкт можно двигать мышкой по сцене.
 
* У каждого объекта есть тип и зависящие от типа свойства. Тип и свойства интерпретируются вьювером, поэтому жестко заданы (не добавляются пользователем).
 
* У каждого следующего добавляемого объекта тип устанавливается по у молчанию как у предыдущего. У активного могут быть изменены.
 
* '''Базовые типы''':
 
** '''фон''' (или интерьер) - на события не реагирует
 
** '''поисковый''' - при клике объект у него увеличивается счетчик кликов. Если помечена галочка "удалять" - удаляется со сцены (становится невидимым). У поискового объекта может быть указана сцена и объект на этой сцене с которым данный поисковый объект связан. Интерпретируется вьювером (например, связь поискового объекта и инвентаря).
 
** '''контрол''' - объект обладающий способностью самостоятельно обрабатывать события (типа регулятора громкости, чекбокса и т.п.). При изменении состояния контрола во вьювере будет вызываться событийная функция, которой передается имя контрола и его состояние, которая это изменение обрабатывает. В дальнейшем, возможно, переход на скриптовую обработку.
 
** '''дверь''' - при клике на объект открывается другая сцена. С объектом связывается ее имя. Возможны два режима:
 
*** текущая сцена закрывается, новая открывается
 
*** новая открывается поверх старой в режиме модального окна
 
*  У каждой сцены есть поле - имя сцены которую надо вызвать, если "миссия выполнена". Что это значит интерпретируется вьювером (например, кликнуты все поисковые объекты)
 
  
== Простой вьювер ==
+
Параметры состояний задаются в редакторе сцены. Ниже, вместо скриншотов панели свойств, приводятся
 +
примеры  на языке xml (так, как это выглядит во внутреннем файле сцены).
  
* Реализовать обработку - проигрование текущей сцены и связанной с ней дверями других сцен.
+
== Введение ==
* При открытии сцены счетчики кликов поисковых объектов обнуляются. Если все объекты типа поисковые имеют по одному клику (и/или убраны) - сцена закрывается. Если не указана последующая сцена приложение закрывается. Иначе открывается эта сцена.
+
 
* Реализовать на простой интерфейс и упрощенную игру типа Mysteriez.
+
Внутри каждого состояния (далее тег '''st''') могут находиться 4 вида команд - тегов:
 +
* '''Инициализации''':
 +
** '''init''' - инициализация состояния (координаты и т.п.)
 +
** '''draw''' - установка графического ресурса
 +
** '''set''' - установка состояния другого объекта
 +
 
 +
* '''Процессов''':
 +
** '''time''' - задержка по времени
 +
** '''move''' - движение
 +
** '''alpha''' - изменение прозрачности
 +
** '''scale''' - изменение размера
 +
** '''rot'''  - вращение
 +
** '''spin''' - движение по окружности
 +
** '''phys''' - движение в силовом поле.
 +
 
 +
* '''Воздействия''':
 +
** '''click''' - что делать при клике на объект
 +
 
 +
* '''Проверки''':
 +
** '''if''' - логическое условие перехода
 +
 
 +
Рассмотрим пример простой машины состояний. Пусть объект находится в состоянии st="stop".
 +
При клике на него мышкой, он переходит в состояние st="run"
 +
в котором находится 3000 ms, через которые возвращается в состояние "stop".
 +
В каждом состоянии рисуется своя картинка.
 +
В xml-файле сцены он описывается следующим образом:
 +
<pre class="brush:xml; gutter: false;">
 +
<obj id="1" type="machine" nm="мигалка" w="64" h="64" x="734" y="534" state="stop">   
 +
 
 +
  <st id="stop">                 
 +
      <init  res="101" />          <!-- рисовать граф.ресурс 101 -->
 +
      <click go="run" />            <!-- при клике - идем в состояние run-->
 +
  </st>
 +
 
 +
  <st id="run">                 
 +
      <init res="102" />            <!-- рисовать граф.ресурс номер 102 -->
 +
      <time tm="3000" go="stop" />  <!-- через время tm возвращаемся в stop -->
 +
  </st>
 +
 
 +
</obj>
 +
</pre>
 +
Поле state="stop" при описании свойств объекта (тег obj) задает начальное состояние объекта.
 +
Если его нет - берем первое состояние как начальное.
 +
Наличие поля go="состояние" в любой команде инициирует остановку всех процессов
 +
и изменяет состояние на указанное.
 +
 
 +
== Воздействия и условия ==
 +
 
 +
Если в команде click указано значение go, то происходит переход в новое состояние.
 +
Так, безусловный переход в состояние "run" выглядит следующим образом:
 +
<pre class="brush:xml; gutter: false;">
 +
<click  go="run" />
 +
</pre>
 +
Поля go может и не быть. Тогда, при клике на объект, все процессы внутри состояния (например, перемещения) останавливаются до следующего клика, которым они запускаются снова:
 +
<pre class="brush:xml; gutter: false;">
 +
<click/>
 +
</pre>
 +
Выход из состояния по go в любой команде (не только в click) может делаться по условию.
 +
Различные условия описываются в секциях '''if'''.  Их может быть несколько для различных переходов.
 +
Например, пусть смена состояния происходит, только, если объект номер 2 находится в состоянии "show":
 +
<pre class="brush:xml; gutter: false;">
 +
<click  go="run" if="0"/>      <!-- проверяем первое (нулевое) условие -->
 +
<if  obj="2" st="show"/>
 +
</pre>
 +
Условие может содержать логические теги. Например, если 2-й объект в show '''и''' (3-й в run '''или''' 4-й в slip):
 +
<pre class="brush:xml; gutter: false;">
 +
<if>
 +
  <and  obj="2" st="show">
 +
  <and>
 +
      <or  obj="3" st="run">
 +
      <or  obj="4" st="slip">
 +
  </and>
 +
</if>
 +
</pre>
 +
 
 +
В условиях может проводится и проверка значений параметров данного объекта. Например:
 +
<pre class="brush:xml; gutter: false;">
 +
<if al="1.0" />  <!-- значение прозрачности -->
 +
<if move="5" />  <!-- выполнилась 5-я команда move -->
 +
<if x=">50" / >  <!-- координата > 50 (первый символ строки знак меньше) -->
 +
</pre>
 +
В дальнейшем предполагается вставка простых скриптов, типа:
 +
<pre class="brush:xml; gutter: false;">
 +
<click  go="run" if="x > 10 and y < 100"/>   
 +
</pre>
 +
 
 +
== Повтор команд  ==
 +
 
 +
Все команды могут встречаться при описании данного состояния по несколько раз.
 +
Интерпретация таких повторов зависит от типа команды:
 +
* В последовательности одинаковых команд инициализации (init,init,...) выполняется только первая. Выполнение следующих команд инициируется другими командами (обычно командами процессов).
 +
* Команды процессов выполняются параллельно и независимо. Например, последовательность move, move, move, rot, alpha, alpha выглядит в виде параллельных цепочек, выполняющихся одновременно сверху вниз. В начале функционирования состояния запускается первый move, rot и первая alpha. Когда одна из них выполнится происходит переход на следующую команду '''с таким же''' именем:
 +
          move  rot    alpha
 +
          move        alpha
 +
          move
 +
* Условная проверка (if) производится на выходе из состояния. Выход происходит, если условие выполнилось.
 +
* Каждая команда может управлять номером выполнения команды из списка команд с данным именем. Для этого в ней указывается имя и номер команды, выполнение которой надо запустить.
 +
 
 +
Рассмотрим перемещение персонажа по экрану.
 +
Пусть различные этапы движения персонажа собраны в графическом ресурсе в прямоугольную
 +
таблицу (по строкам расположены кадры движения вперед, поворот и т.п.).
 +
Тогда можно указать  начальный '''с1''', конечный '''c2''' фреймы в строке таблицы  '''r''' (по умолчанию r=0). Движение вправо и вверх можно реализовать двумя способами.
 +
Первый - при помощи последовательности двух состояний (left и up):
 +
<pre class="brush:xml; gutter: false;">
 +
<st id="left">
 +
  <init res="101" c1="0" c2="15" r="0"/> <!-- 16 кадров ходьбы -->
 +
  <move dx="100" tm="500" go="up"/>      <!-- движемся на dx за dt и переход в go -->
 +
</st>
 +
<st id="up">
 +
  <init res="101" c1="0" c2="7" r="1"/>  <!-- 8 кадров подъема вверх -->
 +
  <move dy="100" tm="500"/>              <!-- движемся на dy за dt и стоп -->
 +
</st>
 +
</pre>
 +
Этот же процесс движения можно реализовать как одно состояние:
 +
<pre class="brush:xml; gutter: false;">
 +
<st id="move">
 +
  <init res="101" c1="0" c2="15" r="0" />   
 +
  <move dx="100" tm="500" init="1"/>    <!-- сдвигаемся и вызываем 2-й init -->
 +
  <init res="101" c1="0" c2="7"  r="1" /> 
 +
  <move dy="100" tm="500"/>              <!-- сдвигаемся  и останавливаемся -->
 +
</st>
 +
</pre>
 +
При начале функционирования этого состояния выполняется инициализация с заданием графики (первый init).
 +
Затем происходит горизонтальное перемещение. Когда оно заканчивается выполняется следующая команда
 +
init, см. свойство init="1" в первом move (все команды нумеруются с 0). После этого сразу запускается следующий move.
 +
 
 +
== Инициализация ==
 +
 
 +
При первом попадании в состояние можно установить те или иные параметры объекта.
 +
Например, его начальное положение в этом состоянии и alpha-прозрачность (если они отличны от общих параметров в разделе '''obj'''):
 +
<pre class="brush:xml; gutter: false;">
 +
<init x="100" y="0"  al="0" />
 +
</pre>
 +
Кроме этого, машина состояний может изменять состояния других объектов (не только машин), которые имеют состояния:
 +
<pre class="brush:xml; gutter: false;">
 +
<set obj="2" st="show" />        <!-- перевод объекта 2 в состояние show -->   
 +
</pre>
 +
Команды init и set могут повторяться, но при первом попадании выполняется всегда только первый init и первый set (точнее нулевые, так как нумерация команд идет с 0).
 +
Если необходимо выполнить сразу несколько set-ов, делается это так:
 +
<pre class="brush:xml; gutter: false;">
 +
<set obj="2" st="show" set="1"/>  <!-- второй объект в состояние show и сразу-->   
 +
<set obj="3" st="play" set="2"/>  <!-- третий объект в состояние play и сразу -->   
 +
<set obj="4" st="run"/>          <!-- четвертый объект в run -->   
 +
</pre>
 +
Например, пусть необходимо при заходе в состояние установить 2-й объект в состояние show, затем переместиться на dx и после этого перемещения задать состояние 3-го объекта в play. Делаем это так:
 +
<pre class="brush:xml; gutter: false;">
 +
<set  obj="2" st="show"/>          <!-- второй объект в состояние show, затем -->   
 +
<move dx="100 set="1"/>            <!-- перемещаемся и затем следующий set -->   
 +
<set  obj="3" st="play"/>         
 +
</pre>
 +
Если в начале не нужна установка состояния, вставляем пустую команду set:
 +
<pre class="brush:xml; gutter: false;">
 +
<set/>           
 +
<move dx="100 set="1"/>            <!-- перемещаемся и затем выполняем set -->   
 +
<set  obj="3" st="play"/>         
 +
</pre>
 +
 
 +
== Таймер ==
 +
Время пребывания в данном состоянии задается командой time с параметром tm в ms:
 +
<pre class="brush:xml; gutter: false;">
 +
<time tm="1000 go="next"/>        <!-- ждем 1000ms и покидаем состояние  -->   
 +
</pre>
 +
Для программирования объектов со случайным поведением можно использовать последовательность команд time с параметром вероятности перехода p:
 +
<pre class="brush:xml; gutter: false;">
 +
<time go="st1" tm="100" p="0.5"/> <!-- через tm с вероятностью 1/2 go to st1 -->   
 +
<time go="st2"/>                  <!-- иначе перейдем в st2 -->   
 +
</pre>
 +
Этот же синтаксис позволяет делать состояния с различным временем жизни:
 +
<pre class="brush:xml; gutter: false;">
 +
<time go="next" tm="100" p="0.5"/> <!-- с вероятностью 1/2 живем 100ms -->   
 +
<time go="next" tm="100"/>        <!-- или 200ms -->   
 +
</pre>
 +
Впрочем, последнюю задачу можно решить при помощи указывания интервала dt внутри которого
 +
произойдет окончание команды. Так, состояние живущее от 800 до 1200ms реализуется следующим образом:
 +
<pre class="brush:xml; gutter: false;">
 +
<time go="next" tm="1000" dt="200"/>   
 +
</pre>
 +
И так, параметры таймера могут быть следующими:
 +
* '''tm''' - длительность выполнения команды в ms
 +
* '''dt''' - интервал tm+/- dt внутри которого, команда может быть случайно прервана (при t>tm+dt прерывается по любому)
 +
* '''p''' - вероятность срабатывания перехода в состояние, указываемое параметром go.
 +
* '''go''' - состояние в которое нужно перейти поле окончания времени и срабатывания условия if (если оно не сработала команда ждет его срабатывания, даже после истечения времени).
 +
* '''if''' - номер команды if.
 +
 
 +
== Движение объекта ==
 +
 
 +
Возможно управление alpha-каналом, перемещением по сцене, вращением и т.п. Всё это команды процессов,
 +
начинающихся выполняться сразу и параллельно.
 +
Например, пусть объект должен переместиться в целевую точку с координатами tx,ty
 +
со скоростью 0.1 пиксель в ms, увеличивая свою непрозрачность с начальной (из раздела init) до ta=1 со скоростью da в ms. При этом он вращается до угла 30 град и уменьшается в 10 раз:
 +
<pre class="brush:xml; gutter: false;">
 +
<move  tx="100" ty="200" v="0.1" />
 +
<alpha ta="1.0" v="0.001"  />
 +
<rot  ta="30"  v="0.001"  />
 +
<scale ts="0.1" v="0.001"  />
 +
</pre>
 +
Любых команд движения может быть несколько. Например, пусть в данном состоянии объект должен двигаться по квадрату, пока мы на него не кликнем:
 +
<pre class="brush:xml; gutter: false;">
 +
<init  x="0"  y="0"  />                  <!-- левый верхний угол -->
 +
<move  tx="10" ty="0"  v="0.1" />        <!-- вправо --> 
 +
<move  tx="10" ty="10" v="0.1" />        <!-- вниз -->
 +
<move  tx="0"  ty="10" v="0.1" />        <!-- влево -->
 +
<move  tx="0"  ty="0"  v="0.1" move="0"/> <!-- вверх и повтор команд move -->
 +
<click go="next"/>
 +
</pre>
 +
Флаг move="0" в последней команде move означает, повторный запуск проигрывания команд move.
 +
 
 +
Все команды движения указывают величину изменения и её динамику. Величина может быть абсолютной (целевое значение) и относительной (на сколько измениться от текущего значения). Аналогично длительность команды можно указать явно, задавая время dt или не явно при помощи скорости изменения (пикселе в миллисекунду  или углы в миллисекунду). При этом указывается что-то одно.   
 +
Рассмотрим подробнее команды процессов движения.
 +
 
 +
=== move ===
 +
Перемещение по сцене:
 +
* '''tx''', '''ty''' - целевые координаты в px к которым должен переместиться объект
 +
* '''dx''', '''dy''' - величина смещения от текущей в px (если есть - tx,ty игнорируются). Можно задавать смесь tx, dy или dx,ty
 +
*  '''v'''          - скороcть перемещения в px/ms. Для фреймовой анимации, например, ходьбы скорость рассчитывается исходя из длительности одного кадра и числа кадров на фазу движения. Поэтому в этом случае удобнее задавать скорость.
 +
* '''tm''' - время перемещения (если есть, v игнорируется)
 +
 
 +
=== rot ===
 +
Вращение объекта вокруг точки пивота с координатами px,py. Эти координаты задаются относительно верхнего левого угла объекта в общей секции описания параметров объекта или командой init  в данном состоянии.
 +
* '''ta''' - целевой угол поворота объекта
 +
* '''da''' - на сколько надо повернуться (ta игнорируется)
 +
* '''v ''' - скорость поворота в градусах в ms
 +
* '''dt''' - время поворота (v игнорируется)
 +
 
 +
=== spin ===
 +
Движение по окружности. Аналогична rot с точкой пивота вынесенной за объект. Однако, в отличии от rot происходит поступательное движение по окружности без поворота объекта. Пока корректнее обрабатывает область клика на объект [x...x+w, y...y+h] в отличии от rot/
 +
* '''ta''' - целевой угол поворота объекта по окружности от вертикальной оси, направленной вниз (вправо положительные углы, влево - отрицательные).
 +
* '''da''' - на сколько надо повернуться (ta игнорируется); может быть отрицательным
 +
* '''v ''' - скорость поворота в градусах в ms
 +
* '''dt''' - время поворота (v игнорируется)
 +
* '''cx''', '''cy''' - координаты центра окружности
 +
* '''r''' - радиус окружности
 +
 
 +
=== alpha ===
 +
Изменение прозрачности объекта. Меняется от 0 (полностью прозрачен) до 1 (непрозрачен)
 +
* '''ta''' - целевая прозрачность
 +
* '''da''' - на сколько надо изменить прозрачность от текущей (ta игнорируется)
 +
* '''v ''' - скорость изменения прозрачности (в долях единицы в ms)
 +
* '''dt''' - время время изменени (v игнорируется)
 +
=== scale ===
 +
Изменение размеров объекта
 +
 
 +
== Симулирование физики ==
 +
 
 +
Команда phys позволяет имитировать простую физику. В ней задается начальная скорость и действующая на объект сила (ускорение). 
 +
Смоделируем падение объекта до линии ty="0", с последующим его подпрыгиванием три раза с затухающей амплитудой (координата y направлена вниз):
 +
<pre class="brush:xml; gutter: false;">
 +
<init  x="0"    y="0"  />
 +
<phys  vx="0"  vy="0"    ay="9.8" if="y<100"/>  <!-- падаем -->
 +
<phys  vx="0.5" vy="-0.5" ay="9.8" if="y<100"/>  <!-- первый отскок -->
 +
<phys  vx="0.3" vy="-0.3" ay="9.8" if="y<100"/>  <!-- второй отскок -->
 +
<phys  vx="0.1" vy="-0.1" ay="9.8" if="y<100"/>  <!-- третий отскок -->
 +
</pre>
 +
Рассмотрим теперь подпрыгивающий мячик, который при касании с землей деформируется (вертикально сплюскивается). Это можно сделать в 3-е состояния (падаем, касаемся и взлетаем)
 +
<pre class="brush:xml; gutter: false;">
 +
<st id="down">                                  <!-- падаем -->
 +
  <phys  vx="0" vy="0" ay="9.8" ty="100" go="touch"/> 
 +
</st>
 +
<st id="touch">
 +
  <scale ty="0.5" tm="100"/>                    <!-- сжимаемся -->
 +
  <scale ty="1.0" tm="100"/>                    <!-- разжимаемся -->
 +
</st>
 +
<st id="up">                                    <!-- взлетаем -->
 +
  <phys  vx="0.1" ay="9.8" ty="0" go="down"/> 
 +
</st>
 +
</pre>
 +
Естественно, необходимо рассчитать начальную скорость взлета, равную v=sqrt(2*ay*h), где h-высота падения.
 +
 
 +
== Примеры ==
 +
 
 +
=== Часы с маятником ===
 +
 
 +
Есть 2 машины: стрелка и маятник в виде шарика, качающегося под стрелкой. При клике на шарик, часы останавливаются. При еще одном клике - опять начинают идти.
 +
Просто тикающую стрелку можно сделать из одного состояния "run":
 +
<pre class="brush:xml; gutter: false;">
 +
<obj id="1" nm="стрелка" res="1" x="0" y="0" w="10" h="100" px="5" py="100" >
 +
  <st id="run">
 +
    <rot da="30" tm="100"/>          <!-- поворот на 30 град. за 100 ms -->
 +
    <rot tm="900" rot="0"/>          <!-- задержка 900 ms и зацикливание rot-эйтов-->
 +
  </st>
 +
</obj>
 +
</pre>
 +
Однако, мы хотим останавливать часы только в состоянии окончания движения стрелки (после поворота от цифры к цифре). Кроме этого, нужна синхронность стрелки и маятника (т.е. стрелка поворачивается, когда маятник достигает максимального отклонения вправо). Поэтому:
 +
<pre class="brush:xml; gutter: false;">
 +
<obj id="1" nm="стрелка" res="1" x="0" y="0" w="10" h="100" px="5" py="100" >
 +
  <st id="stop" >                  <!-- просто рисуем res c текущими параметрами -->
 +
  </st>
 +
  <st id="run">                    <!-- поворачиваем на 30 град. вокруг (px,py) -->
 +
    <rot da="30" tm="100" go="stop"/>
 +
  </st>
 +
</obj>
 +
</pre>
 +
Картинку шарика маятника будем не вращать относительно вынесенной за него точки пивота,
 +
а двигать по окружности, т.к. он должен принять на себя клик в своем текущем положении.
 +
Простая реализация может выглядеть так:
 +
<pre class="brush:xml; gutter: false;">
 +
<obj id="2" nm="шарик" res="1" x="" y="" cx="5" cy="100" >
 +
 
 +
  <st id="run">                   
 +
    <set obj="1" st="run"/>    <!-- запускание поворота стрелки -->
 +
    <spin ta="60"  v="0.24"/> <!-- вправо до 60 град. со скоростью va -->
 +
    <spin ta="-60" v="-0.24"/><!-- отклоняемся влево -->
 +
    <spin ta="60"  v="0.24"/> <!-- снова вправо -->
 +
    <spin set="0"  spin="0"/>  <!-- поворот стрелки, зацикливаем качание -->
 +
     
 +
    <click/>                  <!-- при клике - пауза до следующего клика -->
 +
  </st>
 +
 
 +
</obj>
 +
</pre>
 +
Скорость поворота по окружности (град/ms) вычисляется исходя из амплитуды в 60 град.
 +
Четыре таких амплитуд (качание влево-вправо) должны произойти за 1000 ms. Поэтому v=60*4/1000 = 0.24.
 +
 
 +
Добавим маятнику физичности. Мы ходим, чтобы после остановки и последующего клика
 +
он падал "вниз", а не продолжал свое движение.
 +
<pre class="brush:xml; gutter: false;">
 +
<obj id="2" nm="шарик" res="1" x="" y="" cx="5" cy="100">
 +
  <st id="right">                      <!-- движемся cправа -->
 +
    <set />                          <!-- первый раз стрелку не трогаем -->
 +
    <set obj="1" st="run"/>          <!-- переключаем из spin -->
 +
 
 +
    <spin ta="60" v="0.24" set="1"/> <!-- отклонившись, включаем стрелку-->
 +
    <spin ta="0"  v="-0.24" go="left" />
 +
 
 +
    <click spin="1"/>
 +
  </st>
 +
 +
  <st id="left">                      <!-- движемся влево -->                 
 +
    <spin ta="-60" v="-0.24" />      <!-- до 60 град. со скоростью v -->
 +
    <spin ta="0"  v="0.24" go="right" />
 +
 
 +
    <click spin="1"/>
 +
  </st>
 +
 
 +
</obj>
 +
</pre>

Текущая версия на 13:11, 4 ноября 2012

Название «Кровавая Графиня»

Gerb.png

История

  • Эржебет Бато'ри, Венгрия, 7 августа 1560 - 21 августа 1614 (54 года)
  • Венчалась в 11 лет, замуж вышла в 15. Пять детей (Анна, Екатерина, Миклош, Урсула и Павел)
  • Муж - Ференц Надашди. Всё время проводил в военных походах против турок, был прозван «Чёрный бей» («Чёрный витязь»); умер в 1604 г.
  • Чахтицкий замок в словацких Малых Карпатах расположен на холме 375 м над уровнем моря
  • Герб: 3 горизонтальных зуба дракона, который держит щит и обвивает шею своим хвостом
  • 29 декабря 1610 г палатин Венгрии граф Дьёрдю Турзо ворвался в замок Елизаветы Батори и, как утверждают, застиг её с подручными прямо на месте преступления — пытающими очередных жертв.
  • Остаток жизни Елизавета провела в заточении в подземной темнице собственного Чахтицкого замка, где она прожила три с лишним года и умерла в ночь на 21 августа 1614 г.

Легенда «Кровавая Графиня»

Bathory face.png
Bathory vedma.png

Фильм «Кровавая графиня - Батори» (Юрай Якубискоб, 2008)

  • Занималась цилительством, препарировала трупы.
  • Был роман с придворным итальянским художником Караваджио.
  • Муж в отместку пытался отравить Караваджио, но вино выпила Эржебет
  • Эржебет спасает ведьма Дарвулия (правый глаз зеленый, левый - голубой), которая становится советницей Эржебет.
  • Ведьма, знала тайну "здоровой крови" и давала Эржебет напиток, сохраняя её молодость. Возможно Дарвулия убила несколько девушек.
  • После смерти мужа на Эржебет и её земельные владения стал претендовать Дьёрдя Турзо, соратник мужа и их сосед.
  • Жена Турзо, помогая мужу, начинает подставлять Эржебет, убивая девушек. Параллельно, католическая церковь множит слухи (Эржебет протестанка).
  • Постепенно от снадобья Дарвулии Эржебет начинает терять рассудок; у неё видения. В приступе помешательства Эржебет убивает ножницами свою служанку Сару, которая нечайно ранила Эржебет, подстригая её.
  • Осознав, что во всем виновато снадобье ведьмы, Эржебет заточила Дарвулию в подземелье. В последствии, над мертвым телом Дарвулии, Эржебет просит у неё прощения
  • У Эржебет была ванна, заполненная отварами трав, которые имели красноватый цвет
  • Сжигает своё лицо, вырезанное из полотна Караваджио, когда тот умирает.
  • По сфабрикованным обвинениям Турзо, была заточена, а её служанки сожжены (предварительно им отрубили пальцы). В заточении Эржебет умирает.
  • Хотя Турзо виновен в её смерти, он любил её до конца жизни. Считал достойным соперником. Через сюжет проходит его игра с Батори в шахматы, в которой она его обыграла. "Она выиграла эту партию." Через 2 года он умер.

Цитаты

  • "Чем больше легенд, тем меньше доказательств."
  • "Все должны состариться, кроме лиц на холстах."
  • "Картина это нарисованное стихотворение."
  • "Картина сохранит, то, что время уничтожит."
  • "Нет ничего вечного, даже лиц на картинах."
  • "Список Ваших жертв? - Вылеченных жерв!"
  • "Почему меня покидают все, кого я люблю?"
  • "Умная женщина может стать для мужчины гибелью."

Символы - предметы:

  • нож с двумя выскакивающими лезвиями - рана как укус вампира;
  • белая маска в которой Батори спала;
  • веницианская роза ("голубая, как небо Венеции") - символ Караваджио;
  • гербарий (книга) лечебных трав Батори;
  • круглое зеркало ведьмы, дающее картины будущего;
  • шахматы - большие, по пояс фигуры;
  • книга с историей Батори, которую вел монах;
  • «Турзо» - надпись кровью, которую умирая, сделала ведьма;


Машина состояний (state machine) является универсальным объектом для программирования в редакторе сцен сложного поведения объектов. Для машин с типовым набором состояний и поведений, в дальнейшем будут вводиться отдельные объекты.

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

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

Введение

Внутри каждого состояния (далее тег st) могут находиться 4 вида команд - тегов:

  • Инициализации:
    • init - инициализация состояния (координаты и т.п.)
    • draw - установка графического ресурса
    • set - установка состояния другого объекта
  • Процессов:
    • time - задержка по времени
    • move - движение
    • alpha - изменение прозрачности
    • scale - изменение размера
    • rot - вращение
    • spin - движение по окружности
    • phys - движение в силовом поле.
  • Воздействия:
    • click - что делать при клике на объект
  • Проверки:
    • if - логическое условие перехода

Рассмотрим пример простой машины состояний. Пусть объект находится в состоянии st="stop". При клике на него мышкой, он переходит в состояние st="run" в котором находится 3000 ms, через которые возвращается в состояние "stop". В каждом состоянии рисуется своя картинка. В xml-файле сцены он описывается следующим образом:

<obj id="1" type="machine" nm="мигалка" w="64" h="64" x="734" y="534" state="stop">     
  
   <st id="stop">                   
      <init  res="101" />           <!-- рисовать граф.ресурс 101 -->
      <click go="run" />            <!-- при клике - идем в состояние run-->
   </st>

   <st id="run">                   
      <init res="102" />            <!-- рисовать граф.ресурс номер 102 -->
      <time tm="3000" go="stop" />  <!-- через время tm возвращаемся в stop -->
   </st>

</obj>

Поле state="stop" при описании свойств объекта (тег obj) задает начальное состояние объекта. Если его нет - берем первое состояние как начальное. Наличие поля go="состояние" в любой команде инициирует остановку всех процессов и изменяет состояние на указанное.

Воздействия и условия

Если в команде click указано значение go, то происходит переход в новое состояние. Так, безусловный переход в состояние "run" выглядит следующим образом:

<click  go="run" /> 

Поля go может и не быть. Тогда, при клике на объект, все процессы внутри состояния (например, перемещения) останавливаются до следующего клика, которым они запускаются снова:

<click/> 

Выход из состояния по go в любой команде (не только в click) может делаться по условию. Различные условия описываются в секциях if. Их может быть несколько для различных переходов. Например, пусть смена состояния происходит, только, если объект номер 2 находится в состоянии "show":

<click  go="run" if="0"/>      <!-- проверяем первое (нулевое) условие --> 
<if  obj="2" st="show"/> 

Условие может содержать логические теги. Например, если 2-й объект в show и (3-й в run или 4-й в slip):

<if>
   <and  obj="2" st="show">
   <and>
      <or  obj="3" st="run">
      <or  obj="4" st="slip">
   </and>
</if> 

В условиях может проводится и проверка значений параметров данного объекта. Например:

<if al="1.0" />  <!-- значение прозрачности -->
<if move="5" />  <!-- выполнилась 5-я команда move -->
<if x=">50" / >  <!-- координата > 50 (первый символ строки знак меньше) -->

В дальнейшем предполагается вставка простых скриптов, типа:

<click  go="run" if="x > 10 and y < 100"/>     

Повтор команд

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

  • В последовательности одинаковых команд инициализации (init,init,...) выполняется только первая. Выполнение следующих команд инициируется другими командами (обычно командами процессов).
  • Команды процессов выполняются параллельно и независимо. Например, последовательность move, move, move, rot, alpha, alpha выглядит в виде параллельных цепочек, выполняющихся одновременно сверху вниз. В начале функционирования состояния запускается первый move, rot и первая alpha. Когда одна из них выполнится происходит переход на следующую команду с таким же именем:
         move  rot    alpha
         move         alpha
         move
  • Условная проверка (if) производится на выходе из состояния. Выход происходит, если условие выполнилось.
  • Каждая команда может управлять номером выполнения команды из списка команд с данным именем. Для этого в ней указывается имя и номер команды, выполнение которой надо запустить.

Рассмотрим перемещение персонажа по экрану. Пусть различные этапы движения персонажа собраны в графическом ресурсе в прямоугольную таблицу (по строкам расположены кадры движения вперед, поворот и т.п.). Тогда можно указать начальный с1, конечный c2 фреймы в строке таблицы r (по умолчанию r=0). Движение вправо и вверх можно реализовать двумя способами. Первый - при помощи последовательности двух состояний (left и up):

<st id="left">
   <init res="101" c1="0" c2="15" r="0"/> <!-- 16 кадров ходьбы -->
   <move dx="100" tm="500" go="up"/>      <!-- движемся на dx за dt и переход в go --> 
</st>
<st id="up">
   <init res="101" c1="0" c2="7" r="1"/>  <!-- 8 кадров подъема вверх -->
   <move dy="100" tm="500"/>              <!-- движемся на dy за dt и стоп --> 
</st>

Этот же процесс движения можно реализовать как одно состояние:

<st id="move">
   <init res="101" c1="0" c2="15" r="0" />    
   <move dx="100" tm="500" init="1"/>     <!-- сдвигаемся и вызываем 2-й init --> 
   <init res="101" c1="0" c2="7"  r="1" />  
   <move dy="100" tm="500"/>              <!-- сдвигаемся  и останавливаемся --> 
</st>

При начале функционирования этого состояния выполняется инициализация с заданием графики (первый init). Затем происходит горизонтальное перемещение. Когда оно заканчивается выполняется следующая команда init, см. свойство init="1" в первом move (все команды нумеруются с 0). После этого сразу запускается следующий move.

Инициализация

При первом попадании в состояние можно установить те или иные параметры объекта. Например, его начальное положение в этом состоянии и alpha-прозрачность (если они отличны от общих параметров в разделе obj):

<init x="100" y="0"  al="0" /> 

Кроме этого, машина состояний может изменять состояния других объектов (не только машин), которые имеют состояния:

<set obj="2" st="show" />         <!-- перевод объекта 2 в состояние show -->    

Команды init и set могут повторяться, но при первом попадании выполняется всегда только первый init и первый set (точнее нулевые, так как нумерация команд идет с 0). Если необходимо выполнить сразу несколько set-ов, делается это так:

 
<set obj="2" st="show" set="1"/>  <!-- второй объект в состояние show и сразу-->    
<set obj="3" st="play" set="2"/>  <!-- третий объект в состояние play и сразу -->    
<set obj="4" st="run"/>           <!-- четвертый объект в run -->    

Например, пусть необходимо при заходе в состояние установить 2-й объект в состояние show, затем переместиться на dx и после этого перемещения задать состояние 3-го объекта в play. Делаем это так:

<set  obj="2" st="show"/>          <!-- второй объект в состояние show, затем -->    
<move dx="100 set="1"/>            <!-- перемещаемся и затем следующий set -->    
<set  obj="3" st="play"/>           

Если в начале не нужна установка состояния, вставляем пустую команду set:

<set/>             
<move dx="100 set="1"/>            <!-- перемещаемся и затем выполняем set -->    
<set  obj="3" st="play"/>           

Таймер

Время пребывания в данном состоянии задается командой time с параметром tm в ms:

<time tm="1000 go="next"/>        <!-- ждем 1000ms и покидаем состояние  -->    

Для программирования объектов со случайным поведением можно использовать последовательность команд time с параметром вероятности перехода p:

<time go="st1" tm="100" p="0.5"/> <!-- через tm с вероятностью 1/2 go to st1 -->    
<time go="st2"/>                  <!-- иначе перейдем в st2 -->    

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

<time go="next" tm="100" p="0.5"/> <!-- с вероятностью 1/2 живем 100ms -->    
<time go="next" tm="100"/>         <!-- или 200ms -->    

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

<time go="next" tm="1000" dt="200"/>    

И так, параметры таймера могут быть следующими:

  • tm - длительность выполнения команды в ms
  • dt - интервал tm+/- dt внутри которого, команда может быть случайно прервана (при t>tm+dt прерывается по любому)
  • p - вероятность срабатывания перехода в состояние, указываемое параметром go.
  • go - состояние в которое нужно перейти поле окончания времени и срабатывания условия if (если оно не сработала команда ждет его срабатывания, даже после истечения времени).
  • if - номер команды if.

Движение объекта

Возможно управление alpha-каналом, перемещением по сцене, вращением и т.п. Всё это команды процессов, начинающихся выполняться сразу и параллельно. Например, пусть объект должен переместиться в целевую точку с координатами tx,ty со скоростью 0.1 пиксель в ms, увеличивая свою непрозрачность с начальной (из раздела init) до ta=1 со скоростью da в ms. При этом он вращается до угла 30 град и уменьшается в 10 раз:

<move  tx="100" ty="200" v="0.1" />
<alpha ta="1.0" v="0.001"  />
<rot   ta="30"  v="0.001"  />
<scale ts="0.1" v="0.001"  />

Любых команд движения может быть несколько. Например, пусть в данном состоянии объект должен двигаться по квадрату, пока мы на него не кликнем:

<init  x="0"   y="0"  />                  <!-- левый верхний угол -->
<move  tx="10" ty="0"  v="0.1" />         <!-- вправо -->   
<move  tx="10" ty="10" v="0.1" />         <!-- вниз -->
<move  tx="0"  ty="10" v="0.1" />         <!-- влево -->
<move  tx="0"  ty="0"  v="0.1" move="0"/> <!-- вверх и повтор команд move -->
<click go="next"/> 

Флаг move="0" в последней команде move означает, повторный запуск проигрывания команд move.

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

move

Перемещение по сцене:

  • tx, ty - целевые координаты в px к которым должен переместиться объект
  • dx, dy - величина смещения от текущей в px (если есть - tx,ty игнорируются). Можно задавать смесь tx, dy или dx,ty
  • v - скороcть перемещения в px/ms. Для фреймовой анимации, например, ходьбы скорость рассчитывается исходя из длительности одного кадра и числа кадров на фазу движения. Поэтому в этом случае удобнее задавать скорость.
  • tm - время перемещения (если есть, v игнорируется)

rot

Вращение объекта вокруг точки пивота с координатами px,py. Эти координаты задаются относительно верхнего левого угла объекта в общей секции описания параметров объекта или командой init в данном состоянии.

  • ta - целевой угол поворота объекта
  • da - на сколько надо повернуться (ta игнорируется)
  • v - скорость поворота в градусах в ms
  • dt - время поворота (v игнорируется)

spin

Движение по окружности. Аналогична rot с точкой пивота вынесенной за объект. Однако, в отличии от rot происходит поступательное движение по окружности без поворота объекта. Пока корректнее обрабатывает область клика на объект [x...x+w, y...y+h] в отличии от rot/

  • ta - целевой угол поворота объекта по окружности от вертикальной оси, направленной вниз (вправо положительные углы, влево - отрицательные).
  • da - на сколько надо повернуться (ta игнорируется); может быть отрицательным
  • v - скорость поворота в градусах в ms
  • dt - время поворота (v игнорируется)
  • cx, cy - координаты центра окружности
  • r - радиус окружности

alpha

Изменение прозрачности объекта. Меняется от 0 (полностью прозрачен) до 1 (непрозрачен)

  • ta - целевая прозрачность
  • da - на сколько надо изменить прозрачность от текущей (ta игнорируется)
  • v - скорость изменения прозрачности (в долях единицы в ms)
  • dt - время время изменени (v игнорируется)

scale

Изменение размеров объекта

Симулирование физики

Команда phys позволяет имитировать простую физику. В ней задается начальная скорость и действующая на объект сила (ускорение). Смоделируем падение объекта до линии ty="0", с последующим его подпрыгиванием три раза с затухающей амплитудой (координата y направлена вниз):

<init  x="0"    y="0"  />
<phys  vx="0"   vy="0"    ay="9.8" if="y<100"/>   <!-- падаем -->
<phys  vx="0.5" vy="-0.5" ay="9.8" if="y<100"/>   <!-- первый отскок -->
<phys  vx="0.3" vy="-0.3" ay="9.8" if="y<100"/>   <!-- второй отскок -->
<phys  vx="0.1" vy="-0.1" ay="9.8" if="y<100"/>   <!-- третий отскок -->

Рассмотрим теперь подпрыгивающий мячик, который при касании с землей деформируется (вертикально сплюскивается). Это можно сделать в 3-е состояния (падаем, касаемся и взлетаем)

<st id="down">                                  <!-- падаем -->
   <phys  vx="0" vy="0" ay="9.8" ty="100" go="touch"/>   
</st>
<st id="touch">
   <scale ty="0.5" tm="100"/>                    <!-- сжимаемся -->
   <scale ty="1.0" tm="100"/>                    <!-- разжимаемся -->
</st>
<st id="up">                                     <!-- взлетаем -->
   <phys  vx="0.1" ay="9.8" ty="0" go="down"/>   
</st>

Естественно, необходимо рассчитать начальную скорость взлета, равную v=sqrt(2*ay*h), где h-высота падения.

Примеры

Часы с маятником

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

<obj id="1" nm="стрелка" res="1" x="0" y="0" w="10" h="100" px="5" py="100" >
  <st id="run">
     <rot da="30" tm="100"/>          <!-- поворот на 30 град. за 100 ms -->
     <rot tm="900" rot="0"/>          <!-- задержка 900 ms и зацикливание rot-эйтов-->
  </st>
</obj>

Однако, мы хотим останавливать часы только в состоянии окончания движения стрелки (после поворота от цифры к цифре). Кроме этого, нужна синхронность стрелки и маятника (т.е. стрелка поворачивается, когда маятник достигает максимального отклонения вправо). Поэтому:

<obj id="1" nm="стрелка" res="1" x="0" y="0" w="10" h="100" px="5" py="100" >
  <st id="stop" >                   <!-- просто рисуем res c текущими параметрами -->
  </st>
  <st id="run">                     <!-- поворачиваем на 30 град. вокруг (px,py) -->
     <rot da="30" tm="100" go="stop"/>
  </st> 
</obj>

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

<obj id="2" nm="шарик" res="1" x="" y="" cx="5" cy="100" >

  <st id="run">                    
     <set obj="1" st="run"/>    <!-- запускание поворота стрелки -->
     <spin ta="60"  v="0.24"/> <!-- вправо до 60 град. со скоростью va -->
     <spin ta="-60" v="-0.24"/><!-- отклоняемся влево -->
     <spin ta="60"  v="0.24"/> <!-- снова вправо -->
     <spin set="0"  spin="0"/>  <!-- поворот стрелки, зацикливаем качание -->
      
     <click/>                   <!-- при клике - пауза до следующего клика -->
  </st> 

</obj>

Скорость поворота по окружности (град/ms) вычисляется исходя из амплитуды в 60 град. Четыре таких амплитуд (качание влево-вправо) должны произойти за 1000 ms. Поэтому v=60*4/1000 = 0.24.

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

<obj id="2" nm="шарик" res="1" x="" y="" cx="5" cy="100">
  <st id="right">                      <!-- движемся cправа -->
     <set />                           <!-- первый раз стрелку не трогаем -->
     <set obj="1" st="run"/>           <!-- переключаем из spin -->

     <spin ta="60" v="0.24" set="1"/> <!-- отклонившись, включаем стрелку-->
     <spin ta="0"  v="-0.24" go="left" /> 

     <click spin="1"/>
  </st>
 
  <st id="left">                       <!-- движемся влево -->                  
     <spin ta="-60" v="-0.24" />      <!-- до 60 град. со скоростью v -->
     <spin ta="0"   v="0.24" go="right" /> 

     <click spin="1"/>
  </st> 

</obj>