Примечание: в связи с выходом новой версии программы руководство было дополнено.
Не умеете рисовать и лень изучать какие-то программы, но хотите сделать мультик? Вы можете его написать. Всё просто.
character Petya { body = gray eyes = green } scene { Petya->right(200) }
Сначала создаётся персонаж. Имя может быть любым — английским, русским (если не лень переключать раскладку), числом (если не запутаетесь) или вообще каким-нибудь набором символов. Между фигурными скобками задаются свойства персонажа — цвет тела (gray, серый) и цвет глаз (green, зелёный). Цвет можно писать как английском словом (green), так и кодом (#00FF00). Можно для красоты ставить пробелы в начале каждой строки, находящейся внутри блока, можно не ставить. Внутри блока scene создаётся сама анимация, в данном случае персонаж Petya перемещается вправо на 200 пикселей.
character Petya { } scene { Petya->right(200, 2) Petya->left(20, 0.5) }
Как видите, свойства персонажа можно не указывать — будут установлены значения по умолчанию. Здесь Петя сначала переместится вправо на 200 пикселей за 2 секунды, а затем влево на 20 пикселей за полсекунды. Если количество секунд не указывать, используется свойство персонажа speed, по умолчанию установленное в 250 (вы можете переопределить).
character Petya { bodySize = 50 ; размер тела (точнее, радиус шарика) eyeSize = 5 ; размер глаз x = 0 ; координата x в начале мультфильма body = gray ; цвет тела eyes = aqua ; цвет глаз speed = 250 ; скорость (250 пикселей в секунду) } scene { Petya->right(200, 2) Petya->left(20, 0.5) }
Здесь показаны все имеющиеся у персонажей свойства и их значения по умолчанию, а также комментарии — часть строки после точки с запятой, которая будет проигнорирована программой.
background { ratio = 3 ; отношение skyColor = #9CE8F2 ; цвет неба groundColor = #C4EDBD ; цвет земли }
Здесь и ниже также показаны значения по умолчанию. Небо занимает 1/ratio (здесь — треть) места. При ratio = 1 не отображается земля, при ratio = 0 не отображается небо.
settings { fps = 24 ; кадров в секунду, изменять не рекомендуется width = 1200 ; ширина мультфильма height = 900 ; высота мультфильма pageColor = black ; цвет страницы (на сам мультфильм не влияет; после окончания мультфильма возвращается прежний цвет) }
А теперь попробуем сделать что-то с двумя персонажами.
character 1 { } character 2 { body = black x = 500 } scene { 1->right(200) 2->left(200) }
Здесь сначала персонаж 1 пойдёт направо, а затем персонаж 2 налево. Но что делать, если мы хотим, чтобы они шли друг к другу одновременно? Достаточно добавить пару слов:
character 1 { } character 2 { body = black x = 500 } scene { together 1->right(200) 2->left(200) together_end }
А теперь сделаем общение персонажей при помощи надписей:
character 1 { } character 2 { body = black x = 500 } scene { text = Привет! Как дела? together 1->right(200) 2->left(200) together_end write_clear }
Над персонажами будет написана сия фраза, а после того, как они встретятся, она исчезнет благодаря команде write_clear. Можно изменять настройки надписей:
write { text = "" ; текст color = black ; цвет x = 10 ; координата X y = 700 ; координата Y size = 30 ; размер font = Arial ; шрифт style = normal ; normal — обычный, italic — курсив, bold — жирный }
Координаты x и y — это координаты нижней левой точки текста. Т. е. при x и y, равным 0, текст видно не будет.
И напоследок примерчик чуть посложнее:
character Transaction { body = black eyes = lime x = 50 } character Systempaw { body = gray eyes = yellow x = 500 } write { color = gray } scene { Systempaw->left(200, 1) text = Ты не захватишь лес, Транзакция. wait = 2 ; ничего не делать 2 секунды } write { color = green } scene { text = Ты так наивен, Системолап. }
Всё, что написано выше, для второй версии программы также верно, но есть ряд нововведений.
Petya { body = gray eyes = green } Petya->right(200)
Некоторые слова, как видите, в новой версии можно опускать, сокращая таким образом объём кода. Слово character стало необязательным, и, соответственно, не рекомендуется использовать для имени персонажа ключевые слова (settings, write, camera и др.). Оборачивать действия в блок scene стало также необязательно.
Petya.body = gray Petya.eyes = green Petya->right(200)
Этот код делает абсолютно то же, что и код выше. Рекомендуем использовать такую сокращённую запись в том случае, если не требуется указывать более одного-двух свойств.
Big.bodySize = 100 Big->bodySize(1000, 3)->left(800, 3)->down(200, 3)->eyeSize(100, 3)->body(darkred, 3)
Анимировать стало возможно любые свойства любых объектов (не совсем любые, а только числовые и цветовые, но это почти все). Принцип тот же — знак -> указывает, что это анимация, bodySize (первая анимация в примере) указывает анимируемое свойство, 1000 — значение, к которому его нужно привести за 3 секунды. Также у персонажей появилось свойство y и возможность его анимировать через down и up.
Можно также указывать не значение, к которому нужно привести, а разницу с нынешним (только для числовых свойств; для цветовых, разумеется, нельзя):
settings->width(+100)->height(-200)
Здесь ширина увеличится на 100 пикселей и затем высота уменьшится на 200. Кстати, если количество секунд, за которое должна выполниться анимация, не указано, используется либо свойство speed (установлено по умолчанию только у персонажей, но вы можете поставить у других объектов сами), либо анимация выполняется ровно за одну секунду, если оно не установлено.
Big.bodySize = 100 Big->bodySize(1000, 3)->x(-800, 3)->y(-200, 3)->eyeSize(100, 3)->body(darkred, 3)
Показан изменённый код примера выше. Как видите, left, right, down и up — лишь синонимы для более удобного анимирования свойств x и y.
Big.bodySize = 100 repeat 5 { Big->bodySize(+50, 1) wait = 1 }
Появились циклы. В данном случае код в блоке repeat повторится 5 раз. Очевидно, есть смысл использовать цикл, только если вы используете анимацию или команду wait (которые повторяются).
; Пример 1 Big.bodySize = 100 together Big->bodySize(250, 3)->body(black, 3) together_end
; Пример 2 Big.bodySize = 100 Big->bodySize(250, 3)->body(black, 3)
Возможно, это не очевидно сразу, но примеры несколько разные, хоть здесь и анимируется лишь один персонаж. В первом случае персонаж одновременно будет увеличиваться и становиться чёрным, а во втором — сначала увеличится, а потом уже станет чёрным.
1.body = gray 1.x = 0 2.body = green 2.x = 150 3.body = white 3.x = 300 4.body = yellow 4.x = 450 5.body = black 5.x = 600 camera->right(200)
Если передвигать объект camera, будет как бы передвигаться фон. В данном случае — персонажи уйдут налево, и не придётся каждого отдельно анимировать. В следующих версиях, вероятно, появятся предметы и прочие прелести, так что камера будет ещё более нужной.
text = Привет! write.x = 500 write->x(-100)
У координат текста возможны отрицательные значения. Например, x=-100 при ширине 1200 будет означать, что x=1100. Т. е. текст появится с другой стороны. В этом примере координата x будет анимирована со значения 500 до 400. Но что делать, если нужно анимировать до значения -100? Помимо варианта написать -600, можно написать необязательный по умолчанию знак =:
text = Привет; а ты кто? write.x = 500 write->x(=-100)
И тут же демонстрируется, помимо решения предыдущей, новая проблема. Слова «; а ты кто?» не отобразятся, т. к. это комментарий. Чтобы точка с запятой не считалось за знак комментария, добавьте перед ней \ (это, кстати, называется экранированием):
text = Привет\; а ты кто?
В новой версии также появились возможности по изменению и анимированию рта персонажа. Для этого есть целых четыре свойства, которые мы рассмотрим по отдельности. Первое, mouth, указывает цвет. Интереснее второе — mouthForm. При чётных значениях рот является линией, при нечётных — кружочком. Это удобно для анимирования разговора:
Big { bodySize = 100 mouth = #37252B mouthSize = 0.3 mouthThickness = 7 } together Big->mouthForm(20, 4)->down(40, 4) together_end Big.mouth = black Big.mouthThickness = 1
Здесь же показаны ещё два свойства — mouthSize (по умолчанию значение 0.2) указывает длину линии рта или радиус окружности, mouthThickness — толщину линии (на окружность не влияет).
Напоследок покажем, как можно анимировать прыжок:
Big.bodySize = 100 together Big->right(200, 0.5)->up(400, 0.5) together_end together Big->right(200, 0.5)->down(400, 0.5) together_end
Или туда-сюда:
Big.bodySize = 100 repeat 10 { together Big->right(200, 0.5)->up(400, 0.5) together_end together Big->right(200, 0.5)->down(400, 0.5) together_end together Big->left(200, 0.5)->up(400, 0.5) together_end together Big->left(200, 0.5)->down(400, 0.5) together_end }
Свойство mouthForm стало проще анимировать благодаря появлению синонима:
Big.bodySize = 100 Big.speakSpeed = 5 text = Привет! Big->speak(5) ; всё равно, что: ; Big->mouthForm(+26, 5)
В speak нужно указывать только кол-во секунд. При этом анимируется свойство mouthForm — оно увеличивается на кол-во секунд * speakSpeed (и если получилось нечётное число, то +1, чтобы после разговора персонаж не стоял с открытым ртом). По умолчанию speakSpeed равно пяти.
В новой версии свойства стали регистронезависимыми, т. е., например, можно писать как speakSpeed, так и speakspeed (или даже sPeAkSpEeD). Всё остальное (объекты, имена персонажей и предметов и т. д.) по-прежнему регистрозависимое.
Также появились предметы, хотя использоваться они могут далеко не только для создания предметов.
item.type cat { url = http://catwar.su/cw3/koloroj/0/bazoj/1.png } item Ololostar.type = cat
В нижнем левом углу появится котик. Собственно, сначала нужно объявить новый тип предметов — коты. Указав адрес предмета, можно создавать сколько угодно предметов с таким типом.
item.type cat { url = http://catwar.su/cw3/koloroj/0/bazoj/1.png } item cat1 { type = cat } item cat2 { type = cat x = 200 } item cat3 { type = cat x = 400 }
Свойства можно указывать всему типу (или даже всем предметам, поменяв свойство объекта item), а можно переопределять у конкретных предметов.
Есть свойство fixed. Если оно равно 1, то предмет не будет передвигаться вместе с камерой (удобно для фонов):
item.type cat { url = http://catwar.su/cw3/koloroj/0/bazoj/1.png } item 1 { type = cat fixed = 1 } item 2 { type = cat x = 200 } camera->left(200)
Первый котик, в отличие от второго, застынет.
У предметов есть много свойств, позволяющих вырезать, растягивать и всячески развлекаться с картинками:
item.type cat { url = http://catwar.su/cw3/koloroj/0/bazoj/1.png } item 1 { type = cat x = 10 ; координаты предметы y = 10 width = 50 ; ширина и высота предмета height = 50 sx = 10 ; из исходного изображения будет браться область, начиная с 10х10 sy = 10 sWidth = 50 ; из исходного изображения будет взят кусок размером 50х50 sHeight = 50 }
Чтобы это лучше понять, можете поиграться с циферками.
Поддерживается прозрачность, не поддерживаются, увы, анимированные картинки. Однако способ анимировать предметы всё же есть.
Это картинка называется спрайтом. Рисуется несколько кадров, и затем они слепляются в одно изображение (вручную или с помощью онлайн-сервиса). А в самом мультфильме в один момент времени используется первая часть картинки, в другой — вторая.
item.type sprite { url = http://savepic.su/4728843.png } item Ololo { type = sprite width = 100 sWidth = 100 } repeat 10 { wait = 0.5 item Ololo.sx = 100 wait = 0.5 item Ololo.sx = 0 }
Появились, во-первых, более удобные возможности для анимирования своих предметов. Чтобы понять, как это работает, вам нужно внимательно изучить предыдущий пример со спрайтами.
item.type sprite { url = http://savepic.su/4728843.png } item Ololo { type = sprite fWidth = 100 } item Ololo->frame(+20, 10)
Свойство fWidth (буква f обозначает frame, т. е. ширина кадра) меняет одновременно два свойства: width и sWidth. Можно было бы самому задать значения этим свойствам, разницы нет, кроме того, что с fWidth на строчку меньше.
frame, соответственно, анимирует на деле свойство sx. Увеличение frame на единицу — это увеличение sx на sWidth. Если кадров, как здесь, два, то +20 означает, что анимация повторится 10 раз.
Также появилось примитивненькое недо3D. У персонажей, предметов и камеры появилось, помимо x и y, свойство z.
item.type sprite { url = http://savepic.su/4728843.png } item Ololo { type = sprite width = 100 swidth = 100 } together item Ololo->frame(+20, 10)->z(+100, 10) together_end together item Ololo->frame(+20, 10)->z(-100, 10) together_end
Ololo будет сначала 10 секунд удаляться от нас, а затем 10 секунд к нам возвращаться. Аналогично можно было бы передвигать камеру относительно Ololo, а не наоборот.
Появились звуки. Одновременно может проигрываться сколь угодное количество звуков, только давайте им разные названия (здесь название music).
sound music { src = http://адрес_к_файлу_со_звуком/ ; обратите внимание: не url, как у изображений, а src loop = 0 ; 0 - проиграть 1 раз; 1 - циклически повторять pause = 0 ; если вы захотите остановить проигрывание через некоторое время, поменяйте это свойство на 1 time = 10 ; начать с десятой секунды volume = 1 ; громкость (от 0 до 1, т. е. дробные числа) }
Есть некоторые сложности: перед началом мультфильма все изображения и звуки сначала загружаются, поэтому если звуки весят много, зрителям вашего творчества придётся ждать некоторое время. К тому же, не все форматы поддерживаются всеми браузерами.
Также появились команды skip и skip_end. Они удобны при создании более или менее продолжительных мультфильмов, когда сделано незначительное изменение и нужно посмотреть, как получилось.
Big.bodySize = 100 skip Big->body(black, 1) ; эта анимация выполнится мгновенно, несмотря на то что указана продолжительность 1 секунда skip_end Big->body(white, 1)