My:Abs — различия между версиями
WikiSysop (обсуждение | вклад) (→Badoo) |
WikiSysop (обсуждение | вклад) |
||
(не показано 705 промежуточных версий этого же участника) | |||
Строка 1: | Строка 1: | ||
− | + | '''Название''' «Кровавая Графиня» | |
− | * [http:// | + | [[Файл:gerb.png|right|200px]] |
− | * [http:// | + | '''История''' |
+ | * [http://ru.wikipedia.org/wiki/%D0%91%D0%B0%D1%82%D0%BE%D1%80%D0%B8,_%D0%95%D0%BB%D0%B8%D0%B7%D0%B0%D0%B2%D0%B5%D1%82%D0%B0 Эржебет Бато'ри], Венгрия, 7 августа 1560 - 21 августа 1614 (54 года) | ||
+ | * Венчалась в 11 лет, замуж вышла в 15. Пять детей (Анна, Екатерина, Миклош, Урсула и Павел) | ||
+ | * Муж - Ференц Надашди. Всё время проводил в военных походах против турок, был прозван «Чёрный бей» («Чёрный витязь»); умер в 1604 г. | ||
+ | *[http://ru.wikipedia.org/wiki/%D0%A7%D0%B0%D1%85%D1%82%D0%B8%D1%86%D0%BA%D0%B8%D0%B9_%D0%B7%D0%B0%D0%BC%D0%BE%D0%BA Чахтицкий замок] в словацких Малых Карпатах расположен на холме 375 м над уровнем моря | ||
+ | * [http://ru.wikipedia.org/wiki/%D0%A0%D0%BE%D0%B4_%D0%91%D0%B0%D1%82%D0%BE%D1%80%D0%B8 Герб]: 3 горизонтальных зуба дракона, который держит щит и обвивает шею своим хвостом | ||
+ | * 29 декабря 1610 г палатин Венгрии граф Дьёрдю Турзо ворвался в замок Елизаветы Батори и, как утверждают, застиг её с подручными прямо на месте преступления — пытающими очередных жертв. | ||
+ | * Остаток жизни Елизавета провела в заточении в подземной темнице собственного Чахтицкого замка, где она прожила три с лишним года и умерла в ночь на 21 августа 1614 г. | ||
− | + | '''Легенда''' «Кровавая Графиня» | |
− | * | + | * 650 убитых девушек из крови которых Батори делала омолаживающую ванну |
− | * [http:// | + | * [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) является универсальным объектом для программирования | |
+ | в редакторе сцен сложного поведения объектов. Для машин с типовым набором состояний и поведений, в дальнейшем будут вводиться отдельные объекты. | ||
+ | Логика поведения машины состояний разбивается | ||
+ | на отдельные узлы (состояния). Объект всегда находится строго в одном состоянии. | ||
+ | Переход из одного состояния в другое происходит либо в результате внешнего воздействия на объект, либо в результате окончания некоторых процессов протекающих внутри объекта. | ||
− | + | Параметры состояний задаются в редакторе сцены. Ниже, вместо скриншотов панели свойств, приводятся | |
− | + | примеры на языке 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> | ||
+ | |||
+ | </obj> | ||
+ | </pre> | ||
+ | Скорость поворота по окружности (град/ms) вычисляется исходя из амплитуды в 60 град. | ||
+ | Четыре таких амплитуд (качание влево-вправо) должны произойти за 1000 ms. Поэтому v=60*4/1000 = 0.24. | ||
+ | |||
+ | Добавим маятнику физичности. Мы ходим, чтобы после остановки и последующего клика | ||
+ | он падал "вниз", а не продолжал свое движение. | ||
+ | <pre class="brush:xml; gutter: false;"> | ||
+ | <obj id="2" nm="шарик" res="1" x="" y="" cx="5" cy="100"> | ||
+ | <st id="right"> <!-- движемся cправа --> | ||
+ | <set /> <!-- первый раз стрелку не трогаем --> | ||
+ | <set obj="1" st="run"/> <!-- переключаем из spin --> | ||
+ | |||
+ | <spin ta="60" v="0.24" set="1"/> <!-- отклонившись, включаем стрелку--> | ||
+ | <spin ta="0" v="-0.24" go="left" /> | ||
+ | |||
+ | <click spin="1"/> | ||
+ | </st> | ||
+ | |||
+ | <st id="left"> <!-- движемся влево --> | ||
+ | <spin ta="-60" v="-0.24" /> <!-- до 60 град. со скоростью v --> | ||
+ | <spin ta="0" v="0.24" go="right" /> | ||
+ | |||
+ | <click spin="1"/> | ||
+ | </st> | ||
+ | |||
+ | </obj> | ||
+ | </pre> |
Текущая версия на 13:11, 4 ноября 2012
Название «Кровавая Графиня»
История
- Эржебет Бато'ри, Венгрия, 7 августа 1560 - 21 августа 1614 (54 года)
- Венчалась в 11 лет, замуж вышла в 15. Пять детей (Анна, Екатерина, Миклош, Урсула и Павел)
- Муж - Ференц Надашди. Всё время проводил в военных походах против турок, был прозван «Чёрный бей» («Чёрный витязь»); умер в 1604 г.
- Чахтицкий замок в словацких Малых Карпатах расположен на холме 375 м над уровнем моря
- Герб: 3 горизонтальных зуба дракона, который держит щит и обвивает шею своим хвостом
- 29 декабря 1610 г палатин Венгрии граф Дьёрдю Турзо ворвался в замок Елизаветы Батори и, как утверждают, застиг её с подручными прямо на месте преступления — пытающими очередных жертв.
- Остаток жизни Елизавета провела в заточении в подземной темнице собственного Чахтицкого замка, где она прожила три с лишним года и умерла в ночь на 21 августа 1614 г.
Легенда «Кровавая Графиня»
- 650 убитых девушек из крови которых Батори делала омолаживающую ванну
- Говорят, что до сих пор по ночам из проклятого замка раздаются стоны, приводящие в ужас округу
Фильм «Кровавая графиня - Батори» (Юрай Якубискоб, 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>