Эффективный способ перерисовать сотни частиц во flash?

#flash #actionscript #graphics #performance #particles

#flash #actionscript #графика #Производительность #частицы

Вопрос:

Я только начинаю изучать 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.
}
  

В Particle есть прослушиватель фреймов, который запускает этот каждый фрейм:

 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 amp;amp; xVel > -0.01)
    {
        xVel = 0;
    }

    if (yVel < 0.01 amp;amp; yVel > -0.01)
    {
        yVel = 0;
    }
}
  

Как мне сделать это более эффективным? Я планирую позже выполнять обнаружение столкновений и другие физические взаимодействия, и это уже немного медленно, даже без большого кода для обработки чисел, который я собираюсь добавить позже.

Комментарии:

1. ИМХО, самый быстрый вариант — метод SetPixel из ответа @ Cay. Если вам нужны частицы несколько большего размера, вы можете установить три / четыре / сколько угодно пикселей для каждой. Но если частицы действительно большие, используйте BitmapData.draw .

Ответ №1:

Использование графики довольно медленно для слишком большого количества фигур… Без особых изменений в вашем коде вы могли бы попробовать каждый кадр рисовать свои фигуры в BitmapData (либо сначала нарисуйте их в одной фигуре, либо во многих фигурах, а затем используйте BitmapData draw с последующей очисткой всей вашей графики). Я думаю, вы должны добиться небольшого улучшения. Основной код заключается в следующем:

 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, но вам нужно предварительно стереть все ваши разные частицы (у меня не так много опыта в этом, и я обнаружил много ситуаций, когда было лучше использовать BitmapData draw или даже иметь каждый BitmapData в другом спрайте):

 bitmapData.fillRect(bitmapData.rect, 0);
for(...) {
   bitmapData.copyPixels(myParticle10, myParticle10.rect, new Point(tx, ty));
}
  

Я надеюсь, что это поможет.

Комментарии:

1. Копипиксели будут хороши только для прямоугольных, не так ли? Если частица имеет прозрачные края, ее нужно нарисовать, а не просто скопировать.

2. У меня должен быть только 1 экземпляр bitmapdata, верно? Не по одной на частицу

3. Только один. Ваш экран отрисован на больших bitmapdata, particle — это всего лишь пиксель на нем.

Ответ №2:

Лучший и быстрый способ получить огромное количество частиц в Actionscript — это перенести их в bitmapdata. Я своего рода помешан на частицах, и мне действительно нравится этот метод. Вот руководство о том, как это сделать, с классно выглядящими часами с эффектом частиц.

http://plasticsturgeon.com/2010/08/make-super-cool-as3-particle-effects-for-flash-games-with-bitmapdata/