Падав новорічний сніг, Програми для роботи з графікою, Програмні керівництва, статті

Попередня підготовка та створення заготовки листівки на Flash


Мені був потрібен справжній новорічний снігопад, і малювати кожну сніжинку мені здалося нерозумним, тому я написав універсальний скрипт снігу, який би враховував фізику падаючих сніжинок. Сніжинку я вирішив зробити більше схожою на сніжок, ніж на сніжинку, т.к. коли йде справжній снігопад, форму сніжинки все одно не розрізниш, і ми швидше бачимо сніжні пластівці.


Нижче я буду детально пояснювати, як написати цей скрипт, використовуючи “Flash MX 2004”, але загальні принципи залишаються незмінними, і Ви можете досить легко модифікувати його для інших мов, скажімо для JavaScript. Для полегшення програмування і переносимості коду програма на ActionScript буде винесена в окремий файл і підключена до основного мультфільму за допомогою директиви # include.



Малюємо новорічну листівку






 

Залишилося її зберегти. Так як у нас буде декілька файлів в проекті, то найкраще створити окрему папку “snow” і вже в ній зберегти листівку під ім’ям snow.fla. Ура, готово! З попередньою підготовкою закінчено, і в наступній частині переходимо до суті, тобто до програмування і розбору алгоритму поведінки сніжинок.


Алгоритм поведінки сніжинок



Перед тим як зайнятися безпосередньо фізикою снігопаду, давайте створимо зовнішній файл, в якому і будуть знаходитися всі необхідні функції. Запустіть ваш улюблений текстовий редактор (наприклад, UltraEdit, але зійде і Блокнот) і збережіть поки що порожній файл під ім’ям snow.as. Пам’ятайте, ми вже під’єднали цей файл в першому фреймі нашої листівки? Далі ми почнемо поступово заповнювати цей файл необхідними функціями і змінними.


Фізика поведінки сніжинок

Почнемо з самого простого – подумаємо, а як же поводиться сніжинка? У самому простому випадку, коли немає ніяких додаткових факторів, що впливають, вона, як і всі інші предмети на планеті, падає вниз під дією сили тяжіння. Давайте врахуємо це, ввівши постійну складову силу (Gravity), спрямовану вниз:


/ / Постійна складова швидкості падіння сніжинки
_global.snowflake_y_gravity = 15;

В даному коді я визначив глобальну змінну snowflake_y_gravity. Зауважте, що для визначення глобальної змінної у флеш необхідно створювати її як змінну об’єкта _global. Тоді дана змінна у нас буде доступна в будь-якому місці нашого мультфільму.


Навіть у дуже спокійному повітрі постійно виникають різноманітні невеликі вихори. Спробуйте підкинути в повітря будь дуже легкий предмет – пір’їнка або шовкову хустку – і Ви побачите, що горизонтально вниз він ніколи не впаде. Наша сніжинка навіть легше пір’їнки, і тому за рахунок цих мікровіхрей вона може зміщуватися не тільки вліво або вправо щодо вертикального падіння, але навіть іноді і трошки вгору. Ми врахуємо подібні мікровіхрі, ввівши змінні зсуву по вертикалі (Yshift ) І горизонталі (Xshift ). А саму величину зміщення будемо обчислювати як випадкове число між нулем і максимально можливим зміщенням.


/ / Максимальний зсув сніжинки по осі X і по осі Y
_global.snowflake_x_shift = 10;
_global.snowflake_y_shift = 10;

Але, крім вихорів, трапляються і справжні вітри. Особливо це відчувається в заметіль! Вітер ми врахуємо подібно гравітаційної силі – як постійно діючу силу в горизонтальному напрямку (Wind). Знак цієї сили буде вказувати напрямок вітру.


/ / Швидкість вітру
_global.wind_x_speed = 0;

Снігові пластівці бувають як маленькими, так і великими – за рахунок злипання декількох сніжинок разом. Ми врахуємо цей фактор як випадкове зміна розміру сніжинки (Sizeshift) Щодо якогось базового розміру.


/ / Ширина і висота сніжинки
_global.snowflake_width = 11;
_global.snowflake_height = 10;
/ / Максимальне зміна розмірів сніжинки
_global.snowflake_size_shift = 2;

Для більшого реалізму давайте врахуємо також і простір вглиб. Коли снігові пластівці близько до нас, то ми бачимо їх більш чіткими, а коли вони далеко, то здаються розмитими. Ми врахуємо цей ефект як випадкове зміна прозорості сніжинки (Alphashift) – Чим вона більш прозора, тим далі перебуває.


/ / Максимальне зміна прозорості сніжинки
_global.snowflake_alpha_shift = 10;

Мабуть, ми врахували всі основні фактори, що діють на сніжинку. Давайте підсумуємо і напишемо остаточну функцію розрахунку нового положення сніжинки (X0, Y0) Щодо її попереднього місцезнаходження (X1, Y1):


    X1 = X0 + Gravity + Rnd(2 * Xshift) – Xshift
    Y1 = Y0 + Wind + Rnd(2 * Yshift) – Yshift

Розмір нової сніжинки і її прозорість ми також будемо розраховувати, грунтуючись на попередньому стані сніжинки, за такими формулами:


    W1 = W0 + Rnd(2 * Sizeshift) – Sizeshift
    H1 = H0 + Rnd(2 * Sizeshift) – Sizeshift

    Alpha1 = Alpha0 + Rnd(2 * Alphashift) – Alphashift


У всіх формулах при розрахунку випадкових величин я подвоював значення, тому що зрушення може відбуватися як в позитивну, так і в негативну сторону. А для того щоб потім вирівняти становище, розмір або прозорість сніжинки – вичитав величину зсуву. Цей спосіб як раз і дозволяє нам врахувати зсув значення в обидві сторони.


Ініціалізація снігопаду

Так як снігопад у нас складається з багатьох сніжинок, то ми повинні відслідковувати стан кожної сніжинки до тих пір, поки вона остаточно не впаде або не вилетить за межі снігопаду. Для зберігання цієї інформації ми організуємо масив сніжинок, причому інформація про всі п’яти параметрах кожної сніжинки також буде зберігатися в масиві.


/ / Кількість падаючих сніжинок
_global.num_snowflakes = 30;
/ / Масив, який зберігає опис сніжинок
_global.snowflakes = new Array(num_snowflakes);
for (i=0; i<num_snowflakes; i++) {
snowflakes[i] = new Array(0,0,0,0,0);
}

Для урахування того факту, що сніжинка досягла землі або вилетіла за межі снігопаду, нам необхідно визначити координати габаритного прямокутника, що визначає снігопад. Координати лівого верхнього будуть (0,0), а координати правого нижнього кута співпадуть з шириною і висотою нашої листівки.


/ / Ширина і висота снігопаду
_global.snow_width = 640;
_global.snow_height = 300;

Перед тим як ми почнемо перетворювати снігопад, нам необхідно заповнити масив сніжинок початковими даними, а також програмно згенерувати мувікліп для всіх сніжинок. Ми оформимо дану процедуру у вигляді функції init_snowflakes ():


///////////////////////////////////////////////////////////////////////////////
// // / / Функція ініціалізації сніжинок / /
// //
///////////////////////////////////////////////////////////////////////////////
function init_snowflakes() {
for (i=0; i<num_snowflakes; i++) {
/ / Створюємо новий примірник сніжинки
snow.attachMovie(“snowflake”, “snowflake_”+i, i);
/ / Ініціалізували сніжинку початковими значеннями
snowflakes[i][0] = random(snow_width);
snowflakes[i][1] = random(snow_height);
snowflakes[i][2] = snowflake_width;
snowflakes[i][3] = snowflake_height;
snowflakes[i][4] = random(30);
}
}

В процесі ініціалізації ми створюємо нові мувікліп, на основі нашої сніжинки, вміщеній в бібліотеці. Пам’ятайте, при збереженні ми назвали її snowflake? Тепер саме цей ідентифікатор використовується для створення нових екземплярів сніжинок. Кожен новий примірник повинен бути прикріплений до вже існуючого об’єкту, і саме точка прив’язки цього об’єкта буде початком координат для нового мувікліп. В якості батьківського об’єкта ми помістили саму ж сніжинку в верхній лівий кут листівки, давши їй ім’я snow. І таким чином забезпечили суміщення координат снігопаду з координатами листівки.


Для створення нового екземпляра мувікліп в ActionScript використовується метод attachMovie (), що викликається з батьківського об’єкта. Синтаксис цієї функції наступний:


my_mc.attachMovie(idName:String, newName:String, depth:Number [, initObject:Object]),

де



  • idName – ідентифікатор об’єкта, з якого створюється новий екземпляр
  • newName – ім’я нового екземпляра створюваного об’єкта
  • depth – Z-координата створюваного мувікліп, що визначає порядок відтворення об’єктів на сцені
  • initObject – об’єкт, атрибути якого будуть присвоєні створюваному мувікліп

Для генерації випадкового цілого числа в ActionScript використовується функція random (). Як параметр їй передається ціле число N, а в якості результату повертається випадкове число R в діапазоні 0 < R < N-1.



Функції розрахунку і відтворення сніжинок



Нам залишилося розібратися з базовими функціями, які здійснюють розрахунок нового місця розташування і розмірів сніжинок, а також власне отрисовку снігопаду. Але перед тим як я опишу ці функції, нам необхідно познайомитися з механізмом програмного керування об’єктами в Flash.


Як Ви, напевно, знаєте, будь-який об’єкт має властивості, змінюючи які ми можемо впливати на його зовнішній вигляд і розташування. У разі створення мультфільму вручну Ви вказуєте значення цих параметрів в панелі “Properties”. Якщо ж нам необхідно змінювати значення програмно, то для цих випадків у ActionScript існує функція setProperty (), синтаксис якої наступний:


setProperty(target:Object, property:Object, value/expression:Object),

де



  • target – ім’я об’єкта, який ми збираємося змінити
  • property – назва змінного параметра
  • value / expression – нове значення або обчислюється вираз, що привласнюється обраному параметру

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


Функція розрахунку нового місця розташування і розмірів сніжинок

Переходимо до розгляду функції, яка буде розраховувати нове місце розташування наших сніжинок. Основну формулу ви вже знаєте, але для коректного розрахунку однієї формули недостатньо. В процесі обчислень нам необхідно також врахувати ті сніжинки, які досягнуть землі або вилетять за межі снігопаду. Для таких сніжинок необхідно буде згенерувати нові початкові параметри і повернути їх в снігопад. Повний лістинг функції, що здійснює всі обчислення з урахуванням перерахованих подій, наведено нижче:


///////////////////////////////////////////////////////////////////////////////
// // / / Функція розрахунку нового положення сніжинок / /
// //
///////////////////////////////////////////////////////////////////////////////
function calculate_snowflakes() {
for (i=0; i<num_snowflakes; i++) {
/ / Обчислюємо новий розмір сніжинки
size = random(2*snowflake_size_shift)-snowflake_size_shift;
/ / Коректуємо параметри сніжинки
snowflakes[i][0] += wind_x_speed + random(2*snowflake_x_shift)
– snowflake_x_shift;
snowflakes[i][1] += snowflake_y_gravity + random(2*snowflake_y_shift)
– snowflake_y_shift;
snowflakes[i][2] += size;
snowflakes[i][3] += size;
snowflakes[i][4] += random(2*snowflake_alpha_shift)-snowflake_alpha_shift;
/ / Коректуємо сніжинки, які вийшли за межі снігопаду
if (snowflakes[i][0] < 0 // snowflakes[i][0] > snow_width //
snowflakes[i][1] < 0 // snowflakes[i][1] > snow_height //
snowflakes[i][4] < snowflake_alpha_shift //
snowflakes[i][2] < snowflake_size_shift) {
/ / Генеруємо нові параметри для сніжинок
snowflakes[i][0] = random(snow_width);
snowflakes[i][1] = random(snow_height);
snowflakes[i][2] = snowflake_width+size;
snowflakes[i][3] = snowflake_height+size;
snowflakes[i][4] = 30 + random(70);
}
}
}

Крім сніжинок, які досягли землі або були понесені за межі снігопаду, нам необхідно також враховувати і ті сніжинки, розміри яких зменшилися до мінімального розміру. Те ж саме стосується і сніжинок, прозорість яких стала менше мінімально допустимої. Тому функція перевірки сніжинок вийшла більш складною, ніж просто перевірка кордонів снігопаду.


Функція відтворення сніжинок

Як ви пам’ятаєте, коли ми створили об’єкт “snow”, ми повісили на нього обробку події onClipEvent (enterFrame). Дана подія викликається кожного разу, коли передається керування даним мувікліп. Ми використовуємо налаштування мультфільму за замовчуванням, тому дана подія буде викликатися 12 раз в секунду і запускати функцію відтворення сніжинок.


///////////////////////////////////////////////////////////////////////////////
// // / / Функція відтворення сніжинок / /
// //
///////////////////////////////////////////////////////////////////////////////
function draw_snowflakes() {
/ / Розраховуємо нове положення сніжинок
calculate_snowflakes();
for (i=0; i<num_snowflakes; i++) {
/ / Міняємо параметри сніжинки
setProperty(snow[“snowflake_”+i],_x,snowflakes[i][0]);
setProperty(snow[“snowflake_”+i],_y,snowflakes[i][1]);
setProperty(snow[“snowflake_”+i],_width,snowflakes[i][2]);
setProperty(snow[“snowflake_”+i],_height,snowflakes[i][3]);
setProperty(snow[“snowflake_”+i],_alpha,snowflakes[i][4]);
}
}

Насамперед ми розраховуємо нове положення сніжинок, а потім виробляємо коригування параметрів, використовуючи функцію setProperty (), яку я описав вище. Всі вбудовані в об’єкт атрибути починаються зі знака підкреслення “_”. Повний список атрибутів може бути дуже великим і залежить від конкретного об’єкта. У нашому ж випадку достатньо знати атрибути, що описують координати об’єкта (_x, _y), його ширину і висоту (_width, _height), а також ступінь прозорості (_alpha). Саме їх ми й коригуємо при відображенні сніжинок.


Підбираємо параметри снігопаду


Для того щоб домогтися реалістичного ефекту, залишилося тільки підібрати значення параметрів в нашій формулі. Параметри, які я використовував при створенні снігопаду, були підібрані досвідченим шляхом. Причому сам скрипт досить універсальний і годиться не тільки для створення падаючого снігу, а й для емуляції багатьох інших атмосферних, і не тільки, явищ. Ось кілька значень параметрів, підібраних мною для створення тих чи інших ефектів:

















































































Назва ефекту Число сніжинок Ширина Висота Gravity Wind Xshift Yshift Sizeshift Alphashift
За замовчуванням 30 11 10 15 0 10 10 2 10
Заметіль 100 11 10 40 50 30 30 4 10
Снігова крупа 80 3 3 15 5 30 30 0 20
Дощ 50 1 150 40 0 30 10 0 10
Дискотека 10 110 100 2 2 30 30 5 10
Бульбашки 30 11 10 -15 0 10 10 4 20


Поекспериментувати з цими параметрами, а також спробувати змінити форму і колір сніжинки, я надаю вам самим. Можливо, ви знайдете нові цікаві ефекти. Тоді можете надіслати мені Ваші параметри – І я додам ефект в таблицю.



Ура, новорічна листівка готова!

Ну що ж, ми зробили все що потрібно! Залишилося тільки зібрати всі функції воєдино і згенерувати SWF-файл. Якщо ви все робили акуратно, то побачите чудовий снігопад. Ось яка листівка вийшла в мене:



Ви можете взяти даний скрипт за основу і створити свою власну новорічну листівку! Додати більш складну анімацію або намалювати свою власну картинку.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*