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

Материал из synset
Перейти к: навигация, поиск
 
(не показано 175 промежуточных версий этого же участника)
Строка 1: Строка 1:
== Лейауты ==
+
'''Название''' «Кровавая Графиня»
  
{| class="wikitable sortable" style="float:right; text-align: center; width: 50%"
+
[[Файл:gerb.png|right|200px]]
|-
+
'''История'''
!w || h || w/h || 1024/w || Устройство
+
* [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. Пять детей (Анна, Екатерина, Миклош, Урсула и Павел)
|480 || 320 || 1.50 || 2.13 || iphone
+
* Муж - Ференц Надашди. Всё время проводил в военных походах против турок, был прозван «Чёрный бей» («Чёрный витязь»); умер в 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 м над уровнем моря
|480 || 320 || 1.50 || 2.13 || android  старые
+
* [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 г  палатин Венгрии граф Дьёрдю Турзо ворвался в замок Елизаветы Батори и, как утверждают, застиг её с подручными прямо на месте преступления — пытающими очередных жертв.
|800 || 480 || 1.67 || 1.28 || android  типично
+
* Остаток жизни Елизавета провела в заточении в подземной темнице собственного Чахтицкого замка, где она прожила три с лишним года и умерла в ночь на 21 августа 1614 г.
|-
+
 
|800 || 480 || 1.67 || 1.28 || android планшеты
+
'''Легенда''' «Кровавая Графиня»
|-
+
* 650 убитых девушек из крови которых Батори делала омолаживающую ванну
|854 || 480 || 1.78 || 1.20 || android телефоны
+
* [http://foxalesya.mindmix.ru/1052-299-jerzhebet-batori-elizaveta-batori.zhtml Говорят, что до сих пор по ночам из проклятого замка раздаются стоны, приводящие в ужас округу]
|-
+
 
|960 || 640 || 1.50 || 1.07 || iphone
+
[[Файл:bathory_face.png|right|200px]]
|-
+
[[Файл:bathory_vedma.png|right|200px]]
|960 || 540 || 1.78 || 1.07 || android новые
+
'''Фильм''' «[http://rutracker.org/forum/viewtopic.php?t=3387944 Кровавая графиня - Батори]»  (Юрай Якубискоб, 2008)
|-
+
* Занималась цилительством, препарировала трупы.  
|1024 || 768 || 1.33 || 1.00 || ipad
+
* Был роман с придворным итальянским художником [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 Караваджио].  
|-
+
* Муж в отместку пытался отравить Караваджио, но вино выпила Эржебет
|1024 || 600 || 1.71 || 1.00 || android планшеты
+
* Эржебет спасает ведьма Дарвулия (правый глаз зеленый, левый - голубой), которая становится советницей Эржебет.
|-
+
* Ведьма, знала тайну "здоровой крови" и давала Эржебет напиток, сохраняя её молодость. Возможно Дарвулия убила несколько девушек.
|1024 || 768 || 1.33 || 1.00 || android планшеты
+
* После смерти мужа на Эржебет и её земельные владения стал претендовать [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 Дьёрдя Турзо], соратник мужа и их сосед.
|-
+
* Жена Турзо, помогая мужу, начинает подставлять Эржебет, убивая девушек. Параллельно, католическая церковь множит слухи (Эржебет протестанка).
|1280 || 800 || 1.60 || 0.80 || android планшеты
+
* Постепенно от снадобья Дарвулии Эржебет начинает терять рассудок; у неё видения. В приступе помешательства Эржебет убивает ножницами свою служанку Сару, которая нечайно ранила Эржебет, подстригая её.
|}
+
* Осознав, что во всем виновато снадобье ведьмы, Эржебет  заточила Дарвулию в подземелье. В последствии, над мертвым телом Дарвулии, Эржебет просит у неё прощения 
Лейауты являются различными вариантами геометрических размеров экранов устройств.
+
* У Эржебет  была ванна, заполненная отварами трав, которые имели красноватый цвет
Возможны ситуации:
+
* Сжигает своё лицо, вырезанное из полотна Караваджио, когда тот умирает.
* Лейауты отличаются шириной и/или высотой
+
* По сфабрикованным обвинениям Турзо, была заточена, а её служанки сожжены (предварительно им отрубили пальцы). В заточении Эржебет  умирает.
* только ориентацией (вертикальная-горизонтальная)
+
* Хотя Турзо виновен в её смерти, он любил её до конца жизни. Считал достойным соперником. Через сюжет проходит его игра с Батори в шахматы, в которой она его обыграла. "Она выиграла эту партию." Через 2 года он умер. 
* маштабом (ширина и высота отличается в 2 раза)
 
  
Целесообразно покрывать 3 базовых отношения w/h:
 
 
{|  
 
{|  
| '''1.33''' || 1024x768 || других нет
+
|
|-
+
'''Цитаты'''
| '''1.50''' || 960x640, 480x320 || 2-кратная разница
+
* "Чем больше легенд, тем меньше доказательств."
|-
+
* "Все должны состариться, кроме лиц на холстах."
| '''1.67''' || 800x480, 960x540(-60), 854x480(-54), 1024x600(-24), 1280x800(-32)  
+
* "Картина это нарисованное стихотворение."
|}
+
* "Картина сохранит, то, что время уничтожит."
Остальные добивать интерфейсными полосками слева-справа или сверху-снизу. Полоска может быть одна (типа кепшен окна) с линком на сайт. Плюс 2ориентации, итого 6 лейаутов.
+
* "Нет ничего вечного, даже лиц на картинах."
 +
* "Список Ваших жертв? - Вылеченных жерв!"
 +
* "Почему меня покидают все, кого я люблю?"
 +
* "Умная женщина может стать для мужчины гибелью."
 +
|
 +
|
 +
'''Символы - предметы''':
 +
* нож с двумя выскакивающими лезвиями - рана как укус вампира;
 +
* белая маска в которой Батори спала;
 +
* веницианская роза ("голубая, как небо Венеции") - символ Караваджио;
 +
* гербарий (книга) лечебных трав Батори;
 +
* круглое зеркало ведьмы, дающее картины будущего;
 +
* шахматы - большие, по пояс фигуры;
 +
* книга с историей Батори, которую вел монах;
 +
* «Турзо» - надпись кровью, которую умирая, сделала ведьма;
 +
  |}
 +
----
 +
 
 +
 
 +
'''Машина состояний''' (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-файле сцены он описывается следующим образом:
 +
<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>
  
Для хиденов область поиска объектов имеет универсальное w/h и горизонтальную ориентацию.
+
</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 -->
  
[[File:EditorHiddenData.png|right]]
+
    <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" />
  
1. Все типы лейаутов сразу заданы (кол-во 2-6).
+
    <click spin="1"/>
Если нужно добавить лейаут в готовый проект, это осуществляется копированием уже существующего.
+
  </st>
  
2. При создании сцены
+
</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>