在flash中重新绘制数百个粒子的有效方法?

在flash中重新绘制数百个粒子的有效方法?,flash,actionscript,graphics,performance,particles,Flash,Actionscript,Graphics,Performance,Particles,我刚刚开始学习flash/actionscript 3,并决定编写一个简单的粒子模拟器 最初的设计只是用一束粒子填充屏幕,如果你点击的话,这些粒子会从光标上散开 这是可行的,但有点反应迟钝。我正在使用graphics.drawCircle()绘制粒子,每个粒子都是从Sprite继承的 鼠标单击事件的侦听器: private function mouseClick(e:MouseEvent):void { trace("click"); var now:Date = new Dat

我刚刚开始学习flash/actionscript 3,并决定编写一个简单的粒子模拟器

最初的设计只是用一束粒子填充屏幕,如果你点击的话,这些粒子会从光标上散开

这是可行的,但有点反应迟钝。我正在使用graphics.drawCircle()绘制粒子,每个粒子都是从Sprite继承的

鼠标单击事件的侦听器:

private function mouseClick(e:MouseEvent):void
{
    trace("click");
    var now:Date = new Date();
    trace("Before: "+now.getTime());
    for each (var p:Particle in particleList)
    {
        var dist:Number = distance(e.localX,e.localY,p.x,p.y);
        if (dist < 50)
        {
            var xVel:Number = p.x - e.localX;
            var yVel:Number = p.y - e.localY;

            xVel *=  Math.max(0,50 - dist) * 0.05;
            yVel *=  Math.max(0,50 - dist) * 0.05;
            p.xVel +=  xVel;
            p.yVel +=  yVel;
        }
    }

    var later:Date = new Date();
    trace("After: "+later.getTime());
    trace("Total: "+(later.getTime()-now.getTime()));

    //e.
}
专用函数mouseClick(e:MouseEvent):void
{
跟踪(“点击”);
var now:日期=新日期();
trace(“Before:+now.getTime());
对于每个(变量p:粒子列表中的粒子)
{
var dist:Number=距离(e.localX,e.localY,p.x,p.y);
如果(距离<50)
{
var xVel:Number=p.x-e.localX;
变量yVel:Number=p.y-e.localY;
xVel*=数学最大值(0,50-距离)*0.05;
yVel*=数学最大值(0,50-距离)*0.05;
p、 xVel+=xVel;
p、 yVel+=yVel;
}
}
var later:日期=新日期();
跟踪(“在:+later.getTime()之后);
跟踪(“总计:+(稍后的.getTime()-now.getTime());
//e。
}
在粒子中,有一个帧侦听器,它每帧运行一次:

public function loop(e:Event):void
{
    if (xVel != 0 || yVel != 0 || setup)
    {
        setup = false;
        x +=  xVel;
        y +=  yVel;


        if (x < 0)
        {
            x = 0;
            xVel =  -  xVel;
        }
        if (x > stageRef.stageWidth)
        {
            x = stageRef.stageWidth;
            xVel =  -  xVel;
        }
        if (y < 0)
        {
            y = 0;
            yVel =  -  yVel;
        }
        if (y > stageRef.stageHeight)
        {
            y = stageRef.stageHeight;
            yVel =  -  yVel;
        }


        graphics.clear();
        graphics.lineStyle(.25,0xFFFFFF,0.5);
        graphics.drawCircle(0,0,1);

        xVel *=  Engine.friction;
        yVel *=  Engine.friction;
    }

    if (xVel < 0.01 && xVel > -0.01)
    {
        xVel = 0;
    }

    if (yVel < 0.01 && yVel > -0.01)
    {
        yVel = 0;
    }
}
公共函数循环(e:事件):无效
{
如果(xVel!=0 | | yVel!=0 | |设置)
{
设置=假;
x+=xVel;
y+=yVel;
if(x<0)
{
x=0;
xVel=-xVel;
}
如果(x>stageRef.stageWidth)
{
x=阶段F.stageWidth;
xVel=-xVel;
}
if(y<0)
{
y=0;
yVel=-yVel;
}
如果(y>stageRef.stageHeight)
{
y=分段高度F.分段高度;
yVel=-yVel;
}
graphics.clear();
图形.线型(.25,0xFFFFFF,0.5);
图形绘制圆(0,0,1);
xVel*=发动机摩擦系数;
yVel*=发动机摩擦系数;
}
如果(xVel<0.01&&xVel>-0.01)
{
xVel=0;
}
如果(yVel<0.01&&yVel>-0.01)
{
yVel=0;
}
}

我应该如何提高效率?我计划稍后进行碰撞检测和其他物理交互,即使没有我打算稍后添加的大量数字处理代码,这也已经有点慢了。

对于太多的形状,使用图形相当慢。。。在代码中没有太多更改的情况下,您可以尝试在每一帧的BitmapData中绘制形状(或者先在单个形状中绘制形状,或者在多个形状中绘制形状,然后使用BitmapData绘制,然后清除所有图形)。我认为你应该有一点进步。基本代码如下:

for(...) {
   shape.graphics.drawCircle(0,0,1);
}
bitmapData.draw(shape);
shape.graphics.clear();
另一方面,我所知道的1像素粒子的最快方法是为每个粒子使用BitmapData和setPixel:

bitmapData.fillRect(bitmapData.rect, 0);
bitmapData.lock();
for(...) {
   bitmapData.setPixel(x,y,0xFFFFFF);
}
bitmapData.unlock();
对于更大或更复杂的粒子,我听说copyPixels是一个不错的选择,但您需要事先对所有不同的粒子进行blitt(虽然我对这一点没有太多经验,但我发现在很多情况下,使用BitmapData绘制,甚至将每个BitmapData放在不同的sprite中会更好):


我希望这会有所帮助。

在Actionscript中拥有大量粒子的最好、最快的方法是将它们blit到bitmapdata。我有点喜欢粒子,我真的很喜欢这种方法。 下面是一个关于如何使用酷炫的粒子效果时钟的教程


复制像素仅适用于矩形像素,不是吗?若粒子有透明边,那个么它必须被绘制,而不仅仅是复制。我应该只有一个bitmapdata实例,对吗?不是一个一个。您的屏幕是在大位图数据上绘制的,粒子只是其中的一个像素。IMHO,最快的选项是@Cay答案中的setPixel方法。如果需要更大的粒子,可以为每个粒子设置三/四/任意像素。但如果粒子非常大,请使用
BitmapData.draw
bitmapData.fillRect(bitmapData.rect, 0);
for(...) {
   bitmapData.copyPixels(myParticle10, myParticle10.rect, new Point(tx, ty));
}