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

Материал из synset
Перейти к: навигация, поиск
(Редактор сцен)
 
(не показаны 302 промежуточные версии этого же участника)
Строка 1: Строка 1:
В хидене присутствует статический фон и объекты. Объекты могут быть:  
+
'''Название''' «Кровавая Графиня»
* статически "вплетены" в фон (подобно Mysteriez) и необходимо только задание области для клика на них.
+
 
* всегда быть в одном и том-же месте, но удаляться при клике (отделяться от бекграунда)
+
[[Файл: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 года)
В данной игровой сессии объекты могут быть не "кликательными" и быть составной фона, в другой "кликательными". У объектов может быть различный z-порядок.
+
* Венчалась в 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 года он умер. 
 +
 
 +
{|
 +
|
 +
'''Цитаты'''
 +
* "Чем больше легенд, тем меньше доказательств."
 +
* "Все должны состариться, кроме лиц на холстах."
 +
* "Картина это нарисованное стихотворение."
 +
* "Картина сохранит, то, что время уничтожит."
 +
* "Нет ничего вечного, даже лиц на картинах."
 +
* "Список Ваших жертв? - Вылеченных жерв!"
 +
* "Почему меня покидают все, кого я люблю?"
 +
* "Умная женщина может стать для мужчины гибелью."
 +
|
 +
|
 +
'''Символы - предметы''':
 +
* нож с двумя выскакивающими лезвиями - рана как укус вампира;
 +
* белая маска в которой Батори спала;
 +
* веницианская роза ("голубая, как небо Венеции") - символ Караваджио;
 +
* гербарий (книга) лечебных трав Батори;
 +
* круглое зеркало ведьмы, дающее картины будущего;
 +
* шахматы - большие, по пояс фигуры;
 +
* книга с историей Батори, которую вел монах;
 +
* «Турзо» - надпись кровью, которую умирая, сделала ведьма;
 +
  |}
 +
----
 +
 
 +
 
 +
'''Машина состояний''' (state machine) является универсальным объектом для программирования
 +
в редакторе сцен сложного поведения объектов. Для машин с типовым набором состояний и поведений, в дальнейшем будут вводиться отдельные объекты.
  
Редактор ресурсов является самостоятельным приложением (использующим стандартный GUI) которое хранит и менеждирует '''все''' графические ресурсы проекта (бекграунды, небольшие статические картинки, анимированные клипы). Со временем должен стать универсальным инструментом для различных задач фреймворка. Сам по себе он не является редактором сцен, так как подобный редактор зависит от типа игры. Решает задачу уникальности имён объектов (ресурсов). В нём не создаётся атлас текстур (редактор ни чего не знает о расшаривании).
+
Логика поведения машины состояний разбивается
 +
на отдельные узлы (состояния). Объект всегда находится строго в одном состоянии.
 +
Переход из одного состояния в другое происходит либо в результате внешнего воздействия на объект, либо в результате окончания некоторых процессов протекающих внутри объекта.
  
Перенесение объектов в другие модули=приложения (редакторы сцены, интерфейса)
+
Параметры состояний задаются в редакторе сцены. Ниже, вместо скриншотов панели свойств, приводятся
осуществляется по drag-and-drop.
+
примеры  на языке xml (так, как это выглядит во внутреннем файле сцены).  
При этом "переносится" информация о ресурсе, но не сами графические файлы.
 
  
С одной и той же базой ресурсов могут одновременно работать различные экземпляры приложения (несколько художников, редакторов сцен и т.д.). Окно редактора ресурсов должно изменять свой размер, иметь галочку  "быть сверху".
+
== Введение ==
  
=== Загрузка графики ===
+
Внутри каждого состояния (далее тег '''st''') могут находиться 4 вида команд - тегов:
[[File:open_graph_res.jpg|250px|right]]
+
* '''Инициализации''':  
Можно загружать различные виды сырых графических ресурсов. Их тип указывается в окне загрузки. Это может быть:
+
** '''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>
  
[[File:ACDSee.jpg|200px|right]]
+
</obj>
Ресурсы группируются в древовидной структуре (подобно ACDSee Pro). Стоит использовать стандартные контролы (TreeView и т.п.). Пример дерева:
+
</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 и покидаем состояние -->   
Сообщения об использовании ресурса или его освобождении другими приложениями могут посылаться, например, по TCP протоколу.
+
</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-высота падения.
  
Объект можно перемещать по сцене, изменить его z-координату.
+
== Примеры ==
  
Объект на сцену перетаскивается по drag-and-drop из редактора ресурсов.
+
=== Часы с маятником ===
При перетаскивании  бекграунда с нажатой клавишей (например, shift) перетаскивается не только бекграунд но и объекты которые были с ним связаны при загрузке в режиме "фон и объекты".
 
  
=== Область ===
+
Есть 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" />
она перетаскивается вместе с ним.
 
  
Аналогично с областью (при клик на сцене должен быть нажать Ctrl). Дополнительно возможно изменить её размер.
+
    <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>