Цикл в энтерфрейме?
Я оживляю кучу слов в AS3. Поскольку я собираюсь использовать это на мобильном устройстве, я хочу использовать растровые изображения, а не спрайты. Итак, я создал WordObjects, у которых есть свойство.bitmap, к которому я могу получить доступ.
У меня есть следующий код, который запускается по событию click и проходит через массив внутри события enterframe. Это, вероятно, плохая идея, но я не уверен, как это сделать лучше. (Что удивительно, так это то, что он отлично работает во Flashbuilder, но замедляется до сканирования во Flash CS5.)
Есть ли лучший способ сделать это? Я просто хочу эффективный способ анимировать массив растровых изображений.
private function clickhandler (e:MouseEvent){
this.addEventListener(Event.ENTER_FRAME, blowemup);
}
private function blowemup(e:Event){
var newPosition:Number;
for(var i:int=0; i<arrWordObjects.length; i++)
{
newPosition = updatePosition(arrWordObjects[i].bitmap);
arrWordObjects[i].bitmap.x += newPosition;
arrWordObjects[i].bitmap.y += getRandomNumber();
}
}
3 ответа
То, что будет иметь огромное значение, использует for each(Object in Array)
а не стандарт for
петля.
private function blowemup(e:Event):void
{
var newPosition:Number;
var i:ArrWordsObjectClass; // <-- don't know what the class for this is, just replace
for each(i in arrWordObjects)
{
newPosition = updatePosition(i.bitmap);
i.bitmap.x += newPosition;
i.bitmap.y += getRandomNumber();
}
}
for each
цикл напечатан, то есть сэкономлено много времени, где обычно пытались бы решить, что arrWordObjects[i]
это каждая итерация.
Кроме того, обратите внимание: использование одной управляемой функции ENTER_FRAME и циклическая обработка всего в вашем приложении, которое вы хотите обрабатывать каждый кадр, намного эффективнее, чем применение сотен слушателей для объектов.
Обычно я создаю класс обработчика, который содержит ENTER_FRAME и массив, хранящий мои объекты, например:
package
{
import flash.events.Event;
import flash.display.Sprite;
public class Handler extends Sprite
{
// vars
public var elements:Array = [];
/**
* Constructor
*/
public function Handler()
{
addEventListener(Event.ENTER_FRAME, _handle);
}
/**
* Called on each dispatch of Event.ENTER_FRAME
*/
private function _handle(e:Event):void
{
var i:Element;
for each(i in elements)
{
i.step();
}
}
}
}
Затем я создаю базовый класс для всех объектов, которые я хочу обработать, содержащий step()
функция называется выше.
package
{
import flash.display.DisplayObject;
public class Element extends Object
{
// vars
public var skin:DisplayObject;
/**
* Called on each dispatch of Event.ENTER_FRAME at Handler
*/
public function step():void
{
// override me
}
}
}
Теперь просто расширьте Element своими объектами:
package
{
import flash.display.Sprite;
public class MyThing extends Element
{
/**
* Constructor
*/
public function MyThing()
{
skin = new Sprite();
skin.graphics.beginFill(0);
skin.graphics.drawCircle(0,0,40);
skin.graphics.endFill();
}
/**
* Override step
*/
override public function step():void
{
skin.x += 4;
}
}
}
И все началось!
var handler:Handler = new Handler();
var m:MyThing;
var i:uint = 0;
for(i; i<10; i++)
{
m = new MyThing();
m.y = Math.random()*stage.stageHeight;
handler.elements.push(m);
addChild(m.skin);
}
Сколько растровых изображений вы планируете иметь на сцене одновременно?
У меня было 40 900x16px растровых изображений, которые анимировались на сцене на полной скорости и работали на моем iphone с использованием air 2.6.
Я использовал цикл foreach в событии enterframe, которое я добавил по щелчку мышью и удалил, когда анимация была закончена.
Не забудьте скомпилировать его для мобильного телефона с включенным рендерингом GPU. (gpu в вашем app.xml, если вы используете air 2.6)
Это тоже стоит прочитать, это многое объясняет о производительности для мобильных устройств http://help.adobe.com/en_US/as3/mobile/WS901d38e593cd1bac-3d719af412b2b394529-8000.html
Вот основной пример того, что у меня было...
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
[SWF(frameRate="30", backgroundColor="#FF00FF")]
public class Test extends Sprite
{
private var fields:Vector.<Bitmap> = new Vector.<Bitmap>();
public function Test()
{
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;
for(var i:int = 0; i< 37; i++){
var bd:BitmapData = new BitmapData(960, 16, true, 0x000000);
bd.fillRect(new Rectangle(0, 0, 900, 16), Math.round( Math.random()*0xFFFFFFFF ));
var b:Bitmap = new Bitmap(bd);
b.x = 0;
b.y = i*16;
stage.addChild(b);
fields.push(b);
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private var inertia:Boolean = false;
private var yCurrent:Number;
private var ySpeed:Number;
private var startY:Number;
private var cy:Number = 0;
private function onEnterFrame(e:Event):void{
if(!inertia){
ySpeed = (startY - yCurrent) ; // / 16;
startY = yCurrent
} else {
ySpeed *= 0.8;
if(ySpeed < 0.01 && ySpeed > -0.01){
inertia = false;
stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
cy += ySpeed;
if(cy > 640)
cy -= 640;
var ty:Number = cy;
for each(var tf:Bitmap in fields){
tf.y = ty;
ty += 16;
if(ty > 640)
ty -= 640;
}
}
private function onMouseDown(e:MouseEvent):void{
inertia = false;
startY = e.stageY;
yCurrent = e.stageY;
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseMove(e:MouseEvent):void{
yCurrent = e.stageY;
}
private function onMouseUp(e:Event):void{
inertia = true;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
}
Я бы посоветовал взглянуть на запись пользовательского эффекта на веб-сайте Adobe вместо регистрации события ENTER_FRAME. То, что вы там поместили, означает, что этот код будет работать вечно, пока работает программа. Если вы хотите остановить эффект или запустить 10 кадров и остановиться, вам придется написать больше кода. Это становится еще более сложным, если вы хотите применить это к нескольким экземплярам. Вам придется решать проблемы, которые решает инфраструктура пользовательских эффектов.
Я бы прочитал, как написать пользовательские эффекты здесь:
http://livedocs.adobe.com/flex/3/html/help.html?content=createeffects_1.html