Рішення проблеми продуктивності під flash

Спочатку робота над грою «Грибник» йшла швидко і прогресивно. Я дуже радів технології Flash благородія її простоті використання, і був сповнений оптимізму. Але пізніше я з жахом виявив, що Flash насилу видає належну кількість кадрів, коли об'єктів стає більше сотні.

А в грі повинна бути карта розміром 20х20 клітинок, та й ще з кількома шарами. Тобто об'єктів на карті тільки в одному шарі може бути легко до 300 шт. А деякі об'єкти ще і з анімацією, що ще гірше для продуктивності, тому що анімація типу Motion і Shape Tween програмна. А це означає, що кожен кадр не тільки просто рендерится, але і виробляється ще маса розрахунків за межами мого коду для розрахунку проміжних кадрів в MovieClip`ах. І навіть хитрий рендер в Flash, який перемальовує тільки оновлені ділянки екрану - не рятує ситуацію.

Ось тут - то мій оптимізм трохи згас. Я був засмучений. Невже така чудова технологія, як Flash, годиться тільки для банерів і примітивних ігор !?

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

Вихід безумовно є - відмовитися від використання векторної графіки, перевівши всі в растрову графіку. З растровою графікою комп'ютера безумовно легше проводити розрахунки і виконувати рендер, так як це всього лише масив пікселів з найпростішої інформацією. Піймавши себе на цій думці я на мить злякався: «це те, чому пішов, до того в результаті і прийшов». І почав уже було уявляти, як я це все буду експортувати в растр, а потім назад збирати MovieClip'и з растровими картинками вручну. Ось тут-то все основні плюси векторної графіки: якість в будь-якому розмірі і мінімум місця для зберігання даних - починають згасати. Але рішення безумовно має бути.

У Flash є спеціальна опція «cache as bitmap», яку можна встановлювати для окремих кліпів - це означає, що кліп десь в пам'яті зберігається у вигляді растрової картинки і більш не перераховується як векторне зображення. Мої експерименти показали, що це дає приріст продуктивності, але для повного щастя його явно не достатньо. Причина швидше за все в тому, що час від часу ці «кешированниє» кліпи знову оновлюються за рахунок чого можуть виникати гальма. Та й кількість об'єктів як і раніше залишається колишнім, що продовжує викликати проблеми з продуктивністю.

Зізнатися я практично не знайомий з внутрішньою будовою Flash але в ході практичних експерементів з'ясувалося що для Flash додатки швидше обробляти одну велику картинку ніж безліч маленьких кліпів. Чому це так, я здогадуюся, але описувати не буду, так як це буде нудно і нудно і можливо я взагалі помиляюся в своїх здогадах. Тільки така велика картинка повинна складатися не з маси вкладених кліпів, а з одного великого бітмапами. Простіше кажучи, якщо в грі планується безліч різних об'єктів (кліпів), то їх варто розділити на групи (передній план, задній план, динамічні об'єкти і т.п.), потім один раз їх все «отрендеріть» в один великий бітмапами, який згодом використовувати як задник, а всі оригінальні об'єкти видалити.

Рішення проблеми продуктивності під flash

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

Це все звичайно здорово і настрій моє вже покращився, адже продуктивність такими, що не хитрими способами вдалося підняти майже в двоє. Але проблема до кінця не вирішена, бо левову частку продуктивності як і раніше їсть «векторна анімація». Починаю вже замислюватися про те, а що якщо приблизно так само, але у вигляді масиву растрових картинок зберігати окремі кадри з MovieClip`ов, а потім їх, як в старі добрі часи, виводити в потрібному місці з потрібним кадром. І не встиг я ще цю думку до кінця перетравити, як виявив, що і цей «велосипед» вже винайдений до мене, йому лише треба відрегулювати «педалі» та «сидушку».

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

Сам клас з реалізацією конвертації векторної анімації в растр для AS3 можна скачати тут. В архіві з кодами є приклад як використовувати.

Корисна штука AS3 Bitmap Cached Animations :) Дякую.
Хотілося б зауважити про cache as bitmap.
Такі об'єкти дійсно вважаються дуже швидко, але є багато обмежень на використання. Не коштує його використовувати якщо:
є зміна вмісту мувіка (внутрішня анімація), мувик буде перемальовуватись.
мувик повертається або масштабується, мувик буде перемальовуватись.
якщо кешована картинка буде великий, а вектор, з якого вона складається, дуже простий (на її відображення піде купа оперативки, щоб відбудувати бітмапи).

А з анімацією треба поекспериментувати :)

До речі у хитри якраз з цього є тема.
І дам посилання на тому ж сайті що і ти даси тільки там можна подивитися тест як працюють різні техніки.
1. uncached
2. cached as frames
3. cached on spritesheet

Перші дві зрозумілі, а ось третій так і не зрозумів. Але він показує середню швидкість, тому напевно не варто на ньому морочитися.

var someArray: Array = new Array ();
for (var i: int = 0; i .
ми пишемо:
var someArray: Array = new Array ();
var len: int = someArray.length;
for (var i: int = 0; i .

пишемо:
someConditions. result. result

або
i = i + 1; міняємо на i ++;

або i = i + someVal; міняємо на i + = someVal;

і т.д. Думаю мене зрозуміли :)))
)

@ Сашка, про cache as bitmap - все вірно, казуальна опція для домогосподарок :) Кешіруя графіку і анімацію в бітмапи вручну теж слід контролювати обсяг використовуваної оперативної пам'яті, так як без неї в цих випадках ніяк. І якщо обсяги анімацій і графіки великі, то можливо варто виконувати кешування тільки тієї графіки, яка необхідна для поточного рівня, це з економить пам'ять і час очікування гравця при запуску гри;)

@VirtualMaestro, тільки в цьому прикладі хитрий як раз пропонує конвертувати графіком в ручну від чого відразу виникають дві проблеми: час на конвертацію при будь-яких виправлень і велику вагу флешки.

Зізнаюся з cached on spritesheet я теж не до кінця розібрався. Але мені здалося, що цей метод розбиває кожен кадр на тайли. Навіщо це потрібно я не зрозумів. Оскільки продуктивність від даного прийому дійсно сумнівна я особисто не став заморочуватися :)

З приводу технічної оптимізації коду із задоволенням дам пару цікавих посилань про те як оптимально слід писати код:
- Підвищення продуктивності AS3 додатків
- Efficient Programming Practices
Тільки звичайно слід враховувати, що якщо весь код написати з урахуванням цих прийомів, то не факт, що на ділі вдасться отримати хоча б на 1-2 фпс більше. Так що все залежить від складності програми та в простих іграх / додатках такі хитрощі можуть взагалі не дати ефекту. Просто слід ці прийоми запам'ятати і використовувати як стандартний підхід в своїй роботі;)

Дякую за посилання особливо за другу (першу як то проходив :)), реально почерпнув нові методи (думав що все знаю про масивах :) наївний).
Хороші праці оптимізації коду писав Кріс Касперски (там не тільки оптимізація. Його праці не про флеш - нижче до процесорів (АСМ)) запам'яталася особливо робота з циклами (чудеса розгортки та інше).
Цикли, мені здається, одна з найбільших бід всіх критичних (та й не тільки) додатків.

Якщо процес конвертації оформити як завантаження флешки, то користувач зовсім нічого не помітить :)
Практично у всіх іграх у Nitrome так і зроблено :)

Схожі статті