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

Материал из synset
Перейти к: навигация, поиск
(Примеры)
(Часы с маятником)
Строка 213: Строка 213:
 
     <spin set="0"  spin="0">    <!-- запускаем поворот стрелки, зацикливаем качание -->
 
     <spin set="0"  spin="0">    <!-- запускаем поворот стрелки, зацикливаем качание -->
 
        
 
        
     <click go="wait">           <!-- при клике -->
+
     <click tm="100000000">     <!-- при клике делаем паузу до следующего клика -->
 
   </st>  
 
   </st>  
  
  <st id="wait">                <!-- шарик остановился, ждем окончания поворота стрелки--> 
 
    <time go="stop">            <!-- сразу переходим --> 
 
    <wait obj="1" st="stop">    <!-- дожидаемся окончания поворота стрелки -->
 
  </st>
 
 
</obj>
 
</obj>
 
</pre>
 
</pre>

Версия 09:51, 13 октября 2011

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

Введение

В xml-файле машина состояний состоит из разделов st для каждого состояния объекта, внутри которых находятся все или часть следующих базовых тегов:

  • init - что делать при инициализации состояния
  • draw - как рисовать объект в этом состоянии
  • click - что делать при клике
  • wait - ожидание в течении некоторого времени или

Кроме этих тегов, существуют также теги управления движением:

  • move - как двигаться
  • scale - как изменять размеры
  • spin - как вращаться

и теги проверки и задания состояния других объектов:

  • wait - жать, пока другой объект не окажется в неком состоянии
  • set - перевести объект в фиксированное состояние

Все теги могут встречаться при описании данного состояния по несколько раз (см.ниже)

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

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

   <st id="run">                    <!-- реакция на клик - другая картинка-->
      <draw res="102" />            <!-- рисовать граф.ресурс номер 102 -->
      <wait tm="3000" go="wait" />  <!-- через время tm переходим в wait -->
   </st>

</obj>

Условные переходы

Любой тег может содержать свойство go="новое состояние" которое означает переход к новому состоянию после завершения выполнения данного тега. Подобный переход может сопровождаться условием пребывании некоторого объекта в фиксированном состоянии. Например, пусть переход по клику разрешен, только если, если объект c id=2 находится в состоянии "show". Тогда:

<click  go="run" obj="2" st="show"/> 

Если нужно отслеживать состояние нескольких объектов, то делаем несколько секций click:

<click  go="run" obj="2" st="show"/> 
<click  go="run" obj="3" st="play"/> 

В этом случае работает логическое или (или 2-й объект в st=show или 3-й в st=play). В случае логического и формат следующий:

<click  go="run" >
   <and obj="2" st="show"/>
   <and obj="3" st="run"/>
</click> 
<click  go="run" obj="4" st="play"> 

Т.е. (2-й в show и 3-й в run) или (4-й в play).

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

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

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

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

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

Анимация объекта

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

<draw res="101" c1="0" c2="15" r="0" />    <!-- 16 кадров нулевой строки -->

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

<move  tx="100" ty="200" v="0.1" />
<alpha ta="1.0" da="0.001"  />
<spin  ta="0.1" da="0.001"  />
<scale ts="0.1" ds="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" loop />  <!-- вверх и повтор -->
<click  go="next"/> 

Флаг loop в последнем теге loop означает, повтор проигрывания тегов move.

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

<draw res c1="0" c2="15" c="10" r="0" /> <!-- анимация движения вправо -->   
<draw res c1="0" c2="15" c="10" r="1" /> <!-- анимация движения вниз -->   
<move  tx="10"  ty="0"  v="0.1" draw/>   <!-- вправо -->
<move  tx="10"  ty="0"  v="0.1"/>        <!-- вниз -->

Флаг draw означает, что по окончании движения происходит перывание выполнения тега draw и переход к следующему тегу в списке тегов draw. Аналогично можно прервать тег вращения spin и т.д.

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

Тег move может быть в нескольких форматах

  • (tx,ty,v,a) - где (tx,ty) - целевая точка, v-скорость a-ускорение движения к ней.
  • (vx,vy,ax,ay) - где (vx,vy) - начальная скорость, (ax,ay) - ускорение (сила) действующая на объект.

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

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

Документация

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

Любой тег изменения (wait, move, spin, alpha, scale) может иметь параметр перехода в новое состояние (go="состояние"). Переход произойдет, если закончится данное изменение (временная пауза, движение и т.д.) и выполнится условие перехода, проверяющееся в каких состояниях находятся другие объекты.

wait tm

Временная задержка

  • tm - время в ms задержки; может отсутствовать, тогда сразу происходит проверка условия по объектам.

Примеры:

<-- Ждем время tm и переходим в состояние go: -->
<wait  tm="1000" go="click"/> 

<-- Ждем пока объект obj не окажется в состоянии st, затем переходим в состояние go: --> 
<wait  obj="36" st="end" go="click"/> 

<-- Сначала ждем время tm, а затем состояния объекта: --> 
<wait  tm="1000" obj="36" st="end" go="click"/>

<-- Дожидаемся пока несколько объектов окажутся в своих состояниях: --> 
<wait  tm="1000"  go="click">
  <and obj="36" st="run">
  <and obj="37" st="slip">
</wait>
<-- (первый объект можно засунуть в wait, как в примерах ранее)-->

Временная задержка

move tx ty v

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


Примеры

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

Есть 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="stop" >                <!-- рисуем неподвижный res c текущими параметрами -->
     <click go="run">
  </st>

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

</obj>

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

<obj id="2" nm="шарик" res="1" x="" y="" cx="5" cy="100" state="right">
  <st id="right">                    <!-- движемся cправа -->
     <spin ta="60" va="0.24" >       <!-- отклоняемся до 60 град. со скоростью va -->
     <spin ta="0"  va="0.24" go="left"> 
     <click go="stop_right">
  </st>
 
  <st id="left">                      <!-- движемся влево -->                  
     <spin ta="-60"  va="0.24" go="right">  <!-- отклоняемся на 60 град. со скоростю va -->
     <click go="stop">
     <wait obj="1" st="wait">        <!-- дожидаемся окончания поворота стрелки -->
     <set obj="1" st="stop">
  </st> 

  <st id="stop_right">
     
  </st> 

  <st id="stop_left">
     
  </st> 

</obj>