Функция random и анимация глаз

Функция random, пожалуй, одна из самых используемых функций. Сейчас речь пойдёт об анимации глаз персонажа, а именно, будем делать так, чтобы он моргал в разное время. Это можно сделать и обычным способом, как делают аниматоры – размещают на таймлайне несколько анимаций моргания, сделав между ними промежуток с разным количеством кадров. А все можно сделать намного проще, используя as3.

Самый простой способ – это использовать random и обработчик событий ENTER_FRAME. Но об этом позже, сейчас сделаем некоторые приготовления. Для начала нам нужен глазастый персонаж. Мы возьмём оленя, а вы, я уверен, нарисуете своего неповторимого героя. Персонажа оборачиваем в клип (F8), разбиваем на части и распределяем по слоям.

Итак, имеем примерно вот такую структуру:

 

Глаза тоже оборачиваем в клип и внутри делаем анимацию моргания (случайное моргание выбрано в рамках данного урока, у вас это может быть удивление, испуг и т. п.). Для тех, кто не знает – как анимировать глаза.

Этому клипу назначаем имя c_eyes в Instance name на панели Properties

Рассматривая исходный файл, вы можете заметить, что все клипы, которые я именую, начинаются с приставки "с_" (сокращённо от clip). Это нужно для того, чтобы лучше ориентироваться в коде и не искать откуда взялась та или иная переменная, а знать что это клип созданный во флеше. Некоторые люди используют приставку "mc_" (MovieClip), а иные пишут вообще без приставок. Это всё договорённости.

Создаём новый слой и в первом кадре пишем код:

  1. c_eyes.stop(); 
  2. // останавливаем анимацию
  3. var k = 1; 
  4. // начальное значение
  5. addEventListener(Event.ENTER_FRAME, Update); 
  6. // добавляем слушатель событий
  7. function Update(e:Event):void {
  8.       if (--k<=0) { 
  9. // если --к ноль
  10.             c_eyes.gotoAndPlay(1); 
  11. // проигрываем анимацыю
  12.             k = Math.floor(Math.random()*100+30); 
  13. // генерируем новое к [30..100]
  14.       }
  15.       if(c_eyes.currentFrame == c_eyes.totalFrames) 
  16. // если последний кадр анимации
  17.            c_eyes.gotoAndStop(1); 
  18. // возвращаемся на начало
  19. }

Получаем оленя моргающего через определённый, каждый раз разный, промежуток времени. Чтобы лучше было видно, что время разное, я добавил шкалу:

Пару слов о том, как это работает. Каждый раз, когда олень моргает, генерируется случайное число k от 30 до 100. Это число определяет задержку в кадрах, во время которой персонаж не моргает. Анимация в это время не проигрывается, и мы видим только первый кадр. С каждым кадром значение k уменьшается на 1 и когда достигает нуля, начинает проигрываться анимация и генерируется новое число k. Когда анимация моргания отыграла, то мы возвращаемся на первый кадр и опять ждём пока k не превратиться в 0. И так далее.

Что делать, если нужно анимировать несколько частей тела? Все то же самое. Разберём на примере уха оленя. Оборачиваем ухо в клип и внутри делаем анимацию. Именуем этот клип c_ear. Меняем код в верхнем кадре на следующий:

  1. c_eyes.stop();
  2.  
  3. var k = 1;
  4.  
  5. // то же самое для уха
  6.  
  7. c_ear.stop();
  8.  
  9. var k1 = 1; // начальное значение
  10.  
  11. addEventListener(Event.ENTER_FRAME, Update);
  12.  
  13. function Update(e:Event):void {
  14.  
  15. if (--k<=0) {
  16.  
  17.        c_eyes.gotoAndPlay(1);
  18.  
  19.        k = Math.floor(Math.random()*100+30);
  20.  
  21. }
  22.  
  23. if(c_eyes.currentFrame == c_eyes.totalFrames)
  24.  
  25.        c_eyes.gotoAndStop(1);
  26.  
  27. // обработчик для уха, такой же самый.
  28.  
  29. if (--k1<=0)
  30.  
  31. {
  32.  
  33.        c_ear.gotoAndPlay(1)
  34.  
  35.        k1 = Math.floor(Math.random()*100+30);
  36.  
  37. }
  38.  
  39. if(c_ear.currentFrame == c_ear.totalFrames)
  40.  
  41.        c_ear.gotoAndStop(1);
  42.  
  43. }

Анимация:

Как видим, всё то же самое. Обработчик событий остался один, добавилась новая переменная k1 (можно использовать и k, только тогда ухо будет дёргаться синхронно к морганию). И в обработчике появился блок аналогичный предыдущему.

Небольшое дополнение:

Я приверженец того, чтобы весь код писать в одном кадре, а не разбрасывать его по отдельным клипам. Это существенно упрощает работу с исходником. Например, когда мне скидывают проект (особенно если это as2), то иногда, даже при наличии исходного файла, мне приходится использовать декомпиляторы, чтобы увидеть, где же спрятан код.

Тем не менее, есть такая возможность, писать для каждого клипа свой код и свой обработчик событий, использовать шаблон, так сказать. Такую штуку как раз очень любят аниматоры. Поменять нужно следующее: клип c_eyes обернуть в ещё один клип и уже внутри него уже создать новый слой. На нём написать универсальный код:

  1. var clip = c_eyes;
  2. var k = 1;
  3. clip.stop();
  4. addEventListener(Event.ENTER_FRAME, Update);
  5. function Update(e:Event):void {
  6. if (--k<=0) {
  7.        clip.gotoAndPlay(1)
  8.        k = Math.floor(Math.random()*100+30);
  9. }
  10. if(clip.currentFrame == clip.totalFrames)
  11.        clip.gotoAndStop(1);
  12. }

В случае, когда нужно добавить анимацию, например для уха, повторяем процедуру, описанную выше для c_ear. Копируем этот же код и меняем в первой строчке c_eyes на c_ear.

Дело сделано. Эксперементируйте!

Также вы можете скачать исходник (Cs5).

 

Автор урока: Андрей Барвинко

Графика и анимация: flash-animated.com

Комментарии
Аватар пользователя IgorKup

Доброго времени суток. такой вопрос
Раньше использовал АS2.0, а сейчас АS3.0 (попробую объяснить если будет понятно конечно) Вообщем создавал допустим "звездочку" делал ее крутящейся и она потом исчезала (получался эффект блеска) для нее я писал (по уроку АS2.Innocent код - в 1м кадре- gotoAndPlay(random(100)); и в последнем кадре: gotoAndPlay(2); затем мог размножать звездочки по проекту и они "как бы поблескевали) *появлялись, в разные промежутки времени (получалось своего рода сверкание такое). Теперь же в AS3.0 написание такого кода не срабатывает и все звездочки сверкают в одно и тоже время, все одинаково, а не как бы каждая в своё время! Я так понял что изменили команду - random.
Если Вы примерно поняли меня, о чем я написал, то скажите пожалуйста как мне надо написать код в 1м кадре и последнем? Спасибо большое

Аватар пользователя flahhi

Попробуйте использовать Math.random()*100 вместо random(100). Вдруг поможет))

Аватар пользователя IgorKup

Неа Smile всё равно всё звезды прокручиваются одновременно
Я уже перепробовал по разному:
gotoAndPlay(Math.random():100);
gotoAndPlay Math.random():100 ;
gotoAndPlay(Math.random()*100);
gotoAndPlay Math.random()*100;
не получается!!! Smile Значит как то по другому надо писать.

Аватар пользователя flahhi

А, ну да... Его же еще округлить надо... Вот так правильно - gotoAndPlay(Math.floor(Math.random()*100));

Аватар пользователя IgorKup

Ураааа, спасибо огроменное - так легко стало сразу Smile Всё получилось, наконец та. А то у меня уже голова разбухла и во сне снится Smile

Аватар пользователя Den_l

мне понравилось простота и понятность кода только с рисованием и разбивка на части пока что страдает у меня

Аватар пользователя Oksana

в ближайшее время ждите урок по разбивке на части персонажа.

Аватар пользователя Anyoneelselikeyou

Упс, небольшая опечатка: случайное число k от 30 до 100 генерируется не k = Math.floor(Math.random()*100+30); (trace(k); проверила) А вот так k = Math.round(Math.random()*70+30); 70 = конечное число диапазона минус начальное т.е. 100-30; round чтобы 100 включительно; Здесь это непринципиально, и так отлично всё работает, просто вот столкнулась с проектом где нужна была точность, может надо будет ещё кому-нить....

Что бы вы сделали, если бы точно знали что всё получится?...

Аватар пользователя flahhi

Совершенно верно. Не заметил) Вы молодец что разобрались!)

Аватар пользователя Anyoneelselikeyou

"Некоторые люди используют приставку "mc_" (MovieClip), а иные пишут вообще без приставок. Это всё договорённости." - Когда-то приучилась писать так "myName_mc" или "myName_btn" (для кнопок), - в этом случае когда код набираешь иногда отображается подсказка дальше по коду (в окне AS в Flash CS5, не знаю как в др.), толку от этой подсказки немного, но приятно когда прога понимает что есть что в этом коде. А за урок спасибо, идея отличная и очень нужная для аниматоров. Но... чувствуется что писал програмист для... (извините если что...) ... програмистов. И уроки рисования для програмистов тоже програмисты пишут, а не художники. Наверное разница в мышлении... Но исходник очень помог бы, будь он в 5 версии. Генератор случайных чисел понимаю, переменные понимаю, а вот условия if как-то не очень... (--k<=0) это как расшифровывается? оК, посмотрю в учебнике.
Я бы просто генерировала каждый раз номер кадра старта анимации (вернее кадры простоя - глаза открыты, что бы не трогать непосредственно цикл моргания). Но тут же смысл поместить весь код в один кадр, для этого нужны все эти if? Урок хорош уже хотя бы тем что обнаружил пробелы в самообразовании, время потрачено не зря, спс.

Что бы вы сделали, если бы точно знали что всё получится?...

Аватар пользователя flahhi

Anyoneelselikeyou пишет:
"Но... чувствуется что писал програмист для... (извините если что...) ... програмистов. И уроки рисования для програмистов тоже програмисты пишут, а не художники. Наверное разница в мышлении...

Очень сложно писать о программировании для людей не связанных с программированием...Наверное это приходит с опытом Smile А разница в мышлении, да, ещё какая Smile
Anyoneelselikeyou пишет:

Генератор случайных чисел понимаю, переменные понимаю, а вот условия if как-то не очень... (--k<=0) это как расшифровывается? оК, посмотрю в учебнике.

--k это то же самое, что k = k-1. Если будете читать книги, - эта штука называется "префиксный декремент".
Итого в условии имеем: если уменьшенное на единицу значение "k" меньше либо равно нулю.

Аватар пользователя Anyoneelselikeyou

Цитата:
--k это то же самое, что k = k-1. Если будете читать книги, - эта штука называется "префиксный декремент".
Итого в условии имеем: если уменьшенное на единицу значение "k" меньше либо равно нулю.

Так и запомним:) спасибо

Что бы вы сделали, если бы точно знали что всё получится?...

Аватар пользователя Oksana

а в cs5 не открылся исходник? перезалью

Аватар пользователя Anyoneelselikeyou

Oksana пишет:

а в cs5 не открылся исходник? перезалью


о, огромное спасибо!

Что бы вы сделали, если бы точно знали что всё получится?...

Аватар пользователя Oksana

перезалила исходник

Аватар пользователя LeeTovetz

Вот это вещь. Огромное спасибо.

моя радость тут ))) http://leetovetz.deviantart.com/gallery/

Аватар пользователя Ptah

Заметил, что чаще всего персонажи моргают когда поворачивают голову. Может есть какая-то заметка о том, где и когда герой должен моргать?

Аватар пользователя Anyoneelselikeyou

http://medvezana.com - Tips&Tricks Шона Келли на русском языке - пункт номер 5

Что бы вы сделали, если бы точно знали что всё получится?...

Аватар пользователя Oksana

спасибо за ссылочку, очень полезный материал.

про моргание - вот более точная ссылка

Автор пишет:

"Мы моргаем по ряду причин, но самым важным для меня являются эти:
1. Мы моргаем, когда переключаем мыслительный процесс.
2. Мы моргаем, чтобы показать или скрыть эмоции.
3. Мы моргаем посередине быстрого поворота головы."

Аватар пользователя Ptah

Спасибо. А рандомная анимация будет бросаться в глаза, как мне кажется.

Аватар пользователя Oksana

думаю, больше  в глаза бросается, когда персонаж моргает через одинаковый промежуток времени

Аватар пользователя LeeTovetz

А мне кажется смотря для чего. Для мультика конечно же не подойдет. там нужен полный контроль над сценой. а для игрушек самый раз.

моя радость тут ))) http://leetovetz.deviantart.com/gallery/

Пожалуйста, оставьте ваш комментарий. Спасибо!
Содержимое этого поля является приватным и не будет отображаться публично.
CAPTCHA
Вопрос для проверки
Заполните поле проверки