Плавная анимация 30-100 объектов на ActionScript 3
Хочу сделать для своей Flash игры анимацию воздушными шариками которые пролетают через экран при успешном прохождении уровня.
Но не получается сделать это плавно и что бы еще и процессор не отжирало сильно.
Шарики у меня это муви клипы, которым я рандомно изменяю размер в большую и меньшую сторону, что бы создать впечатление «разных» шариков. Движение шариков делаю с использованием библиотеки TweenMax.
Но результат меня удручает своим качеством.
вот кусок кода который я использую: public static function randomScale(shape: DisplayObject, ll: Number, ul: Number): void
{
var sc: Number = 1 + Math.random() * ((Math.random() < 0.5) ? 1 : -1);
sc = ((sc < ll) || (sc > ul)) ? 1 : sc;
if (sc != 1)
{
shape.scaleX = sc;
shape.scaleY = sc;
}
}
/**
* Произвести запуск объектов в полет от низа контейнера к верху, можно использовать для оформления прохождения уровня.
*
* @param parent - родительский контейнер внутри которого будут летать объекты.
* @param duration - длительность анимации.
* @param delayMax - максимальная задержка перед анимацией.
* @param deltaX - максимальное отклонение по координате X в лево или право, для придания естественности поведения.
* @param scale - применять изменение масштаба объектов в диапазоне от 0.7 до 1.5.
* @param callback - функция вызываемая по окончанию анимации.
*/
public static function fly(parent: DisplayObjectContainer, shapes: Vector.,
duration: Number, delayMax: Number,
deltaX: uint,
scale: Boolean = false,
callback: Function = null): void
{
// получаем габариты родительского контейнера
var w: uint = parent.width;
var h: uint = parent.height;
var cnt: uint = shapes.length;
// запускаем объекты один за одним
for each (var shape: MovieClip in shapes)
{
// случайное положение объекта
shape.x = Math.round(Math.random() * w);
shape.y = h + 5; // исходно объекты находятся внизу
shape.visible = false;
// изменение масштаба объекта в небольшм диапазоне
if (scale)
{
randomScale(shape, 0.7, 1.5);
}
parent.addChild(shape);
// запускаем анимацию полета
TweenMax.to(shape, duration, // длительность анимации
{delay: delayMax * Math.random(), // произвольная задержка 0...delayMax секунды, что бы выглядело естественно
x: shape.x + (Math.round(Math.random() * deltaX * 2) - deltaX), // точка назначения отличается ± deltaX от исходной
y: -150, // объекты улетают за границу экрана
ease: Linear.easeIn, // объекты летят с линейной скоростью
visible: false, // в конце они становятся невидимыми
onInit: showShape,
onInitParams: [shape],
onComplete: removeShape, // метод для зачистки по окончании анимации
onCompleteParams: [shape]
});
}
function showShape(child: MovieClip): void
{
child.visible = true;
}
/** Зачистка по окончании анимации */
function removeShape(child: MovieClip): void
{
// удаляем объекты из контейнера по окончанию анимации
parent.removeChild(child);
}
}
}
Вы бы показали, что за ролик у вас. Может у вас фон сложный, или может у вас на каждом объекте навешано фильтров, и при каждой незначительной трасформации, каждый объект заново кешируется в битмап. TweenMax не может быть причиной тормозов при 100 объектах (если только не используются плагины).
Ну фон статический, ничего не шевелится и никаких фильтров не навешано.
Про TweenMax согласен — у них в демке тысячами объекты летают.
Может быть наоборот какой блюр навесить на шарики? что бы визуально было «более гладко»?
Только я толком не знаю как его настроить.
Ну так и сделайте в цикле создание мувиков со случайным размером и случайной координатой х, потом к каждому добавьте ENTER_FRAME и соответственно функцию, которая будет случайным образом в каждом кадре менять немного координату х (что бы он как будто от ветра дрожит в легкую) и уменьшать координату у, дабы он вверх летел. Ну и сделайте частоту смены кадров 41 в секунду. Должно получится все плавно и красиво. Можно ещё сам шарик внутри санимировать для реалистичности. Что бы он немного менял форму.
Есть два совета которые помогут вам какую бы анимацию вы не делали
не применяйте то что не видно — если ты смещаете обьект на 10 пиксель за секунду в 100 FPS — каждый раз смешаете на 0.01 — смысла в этом нету, а проц кушает.
Давайте посмотрим глубже.
100 обьектов смешаются на 10 пикселей. В 100 FPS
Вы пробуете это сделать, тормоза, прощай 100 FPS. Цикл…
Теперь давайте не будем смешать их на невидимые растояния. Также каждому дадим некий стартовый «офсет»
В итоге — за каждый тик сместиться только 10 обьектов. В след тик — другие 10.
За «видимый» тик — все.
Утверждение — если разбивать анимацию на части, и не анимировать все обьекты — это поднимет FPS
Поднятие FPS сгладит возможные скачки сдвига обьектов.
И — чем быстрее работает — тем еще более быстрее работает…
Я такую технологию сильно опробовал в свое время на shadow-mapping( через текстуры ) — надо обновлять кубик. Вот полный апдейт 6ти граней тормозил. А если в тик только две грани — нормально. А поднятие FPS не дало заметить что некоторые грани сушествуют немного не в том времени
Пока все экперименты с плавностью свелись к следующему: если делать время «полета» шариков через весь экран более 5 секунд, например 10, то получается плавно, но сильно медленно :(, игрок такие шарики быстро проклинать начнет.
Для обычного, векторного движка флэша анимировать 100 объектов с приличным fps - практически непосильная задача. Переходите на GPU рендеринг, какой-нибудь Starling вам поможет, там тоже есть мувиклипы и TweenMax, так что эту часть кода даже переделывать не придётся.