0

2クラスあります。流体をシミュレートします。どちらのクラスも非常に簡単で短いですが、2 秒実行すると、シミュレーションが非常に遅くなり、メモリ リークのように見えます。しかし、このコードにリークは見られません。

なぜこのようなことが起きているのか、わかる方いましたら教えてください。

FluidLayer.as

package  {
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.display.BitmapData;
import flash.filters.BlurFilter;
import flash.display.Bitmap;
import flash.geom.Point;
import flash.geom.ColorTransform;
import flash.display.IBitmapDrawable;
import flash.events.Event;
import flash.display.MovieClip;


public class FluidLayer extends MovieClip {

    private var canvas:Sprite;
    private var b:Bitmap;
    private var blur:BlurFilter = new BlurFilter(20,20,3);  
    private var bmd1:BitmapData;

    public function FluidLayer() {
        canvas = new Sprite();

        for(var i:int = 0;i < 600;i++){

            var p:Particle = new Particle();
            canvas.addChild(p);
            p.x = stage.stageWidth * Math.random();
            p.y = stage.stageHeight* Math.random();
            p.initi(stage);
        }

        canvas.filters = new Array(blur);
        addEventListener(Event.ENTER_FRAME, render);


    }


    private function render(e:Event):void{

        remove();

        b = new Bitmap(makeFluid(canvas),"auto", true);
        b.alpha = 0.7;
        addChild(b);

    }

    private function makeFluid(o:Sprite):BitmapData{

        bmd1 = new BitmapData(stage.stageWidth, stage.stageHeight, true);
        bmd1.draw(o,null,null,null,null,true);
        bmd1.threshold(bmd1, bmd1.rect, new Point(0,0), ">", 0XFF2b2b2b, 0x55FFFF, 0xFFFFFF, false);

        return bmd1;
    }


    private function remove():void{
            if(numChildren > 1)
            removeChildAt(1);

            if(bmd1){ 
                bmd1.dispose();
                bmd1 = null;
            }
    }

}}

Particle.as

package  {

import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Stage;


public class Particle extends MovieClip {

    private var speedX:int;
    private var speedY:int;
    private var _s:Stage;       

    public function Particle() {
        this.graphics.beginFill(0x00CCFF);
        this.graphics.drawCircle(0,0,Math.random() * 30);

        speedX = Math.random() * 10 - 5;
        speedY = Math.random() * 10 - 5;

        this.addEventListener(Event.ADDED_TO_STAGE, initi);

    }

    public function initi(s:Stage):void{
        this._s = s;
        addEventListener(Event.ENTER_FRAME, render);
    }       

    private function render(e:Event):void{

        this.x += Math.random()*speedX;
        this.y += Math.random()*speedY;


        if(this.x > _s.stageWidth || this.y > _s.stageHeight){

            //this.x =  Math.random()*_s.stageWidth;
            //this.y =  Math.random()*_s.stageHeight;

            removeEventListener(Event.ENTER_FRAME, render);
            this.parent.removeChild(this);
        }
    }
}}
4

3 に答える 3

0

元のスローダウンは、キャンバス上のぼかしフィルターのようです。(フィルターをコメントアウトして証拠を確認してください)

フィルターをレンダリングするためのフラッシュ (CacheAsBitmap および Bitmap Filter バッファー) によるビットマップの自動作成により、メモリ リークが発生する可能性があります。

簡単な修正のために、キャンバスを作成した後に次の行を追加してみてください。

canvas.scrollRect = new Rectangle(0,0,stage.stageWidth,stage.stageHeight);

scrollRect でキャンバスのサイズを制限することで、この再割り当てを停止しています。

ただし、流体はもはやステージの端には行きません。これは、描画とビットマップの割り当てルーチンで回避でき、寸法とオフセットを増やします。それを試してみますが、部分的にぼかしフィルターの量に関連しています。

これらのアイデアを Andreas のコードの非常に優れたアイデアに適応させることをお勧めします。

于 2013-08-15T00:12:09.213 に答える
0

bmd1.dispose(); を呼び出す必要があります。そうしないと、メモリからビットマップが解放されません。

編集:

コードを注意深く調べ、最適化し、いくつかのことをクリーンアップした後、シミュレーションの実行がますます遅くなっていないという結論に達しました。

問題は、粒子の x と y の速度を計算する方法でした。基本的に、すべてが停止するまで速度が低下します。配置した大規模な高品質のぼかしとビットマップの解放の欠如に加えて、ムービーが表示され、実際にはクロールするのが遅くなります.

これが私が修正したあなたのコードです。ベンチマークを行ったところ、15 分後に 10% の CPU または 40k のメモリを超えてピークに達することはありませんでした。

Particle.as

package  {

import flash.display.MovieClip;
import flash.events.Event;
import flash.display.Stage;


public class Particle extends MovieClip {

    private var speedX:int;
    private var speedY:int;  
    private var deleted:Boolean = false;

    public function Particle() {
        this.graphics.beginFill(0x00CCFF);
        this.graphics.drawCircle(0,0,Math.random() * 30);

        //The max prevents particle speed from rounding to zero.
        speedX = Math.ceil(Math.random() * 10 - 5);
        speedY = Math.ceil(Math.random() * 10 - 5);
    }     

    public function render():void{
        //It originally appeared to be slowing down. In-fact, it was.
        x += Math.random() * speedX;
        y += Math.random() * speedY;

        deleted = (x > FluidLayer.w || y > FluidLayer.h);
        //Comment this below if you want particles to be removed once they go out of bounds.
        if(deleted) {
            x = Math.random() * FluidLayer.w;
            y = Math.random() * FluidLayer.h;
            deleted = false;
        }
    }

    public function isDeleted():Boolean {
        return deleted;
    }
}
}

FluidLayer.as

package  {
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.display.BitmapData;
import flash.filters.BlurFilter;
import flash.display.Bitmap;
import flash.geom.Point;
import flash.geom.ColorTransform;
import flash.display.IBitmapDrawable;
import flash.events.Event;
import flash.display.MovieClip;


public class FluidLayer extends MovieClip {

    private var canvas:Sprite;

    private var bitmap:Bitmap;
    private var bitmapData:BitmapData;

    private var particleArray:Array = new Array();

    public static const w:uint = 550;
    public static const h:uint = 400;


    public function FluidLayer() {
        addEventListener(Event.ADDED_TO_STAGE, initialize);
    }

    //By only one event handler to render, we prevent the overhead of 599 bubbling events.
    private function render(e:Event):void {
        for each(var p:Particle in particleArray) {
            p.render();
            //uncomment below if you want particles to become removed when they navigate out of bounds.
            //if(p.isDeleted()) {
                //canvas.removeChild(p);
                //particleArray.splice(particleArray.indexOf(p),1); 
            //}
        }
        bitmapData.fillRect(bitmapData.rect, 0); //clear the bitmapdata
        bitmapData.draw(canvas,null,null,null,null,true);
        bitmapData.threshold(bitmapData, bitmapData.rect, new Point(0,0), ">", 0XFF2b2b2b, 0x55FFFF, 0xFFFFFF, false);
    }


    //We call initialize once the fluid layer has been added to stage 
    //or else stage values will be null.
    private function initialize(e:Event):void {
        canvas = new Sprite();


        //You DEFINITELY want to lower the blur amount here.
        //This is what is ultimately slowing your SWF down to a crawl.
        //canvas.filters = new Array(new BlurFilter(20,20,1));

        for(var i:uint = 0; i < 600; i++) {
            var p:Particle = new Particle();
            p.x = Math.random() * w;
            p.y = Math.random() * h;
            canvas.addChild(p);
            particleArray.push(p);
        }

        //The bitmap and bitmapData only need to be initialized once
        bitmapData = new BitmapData(w, h, true);

        bitmap = new Bitmap(bitmapData, "auto", true);
        bitmap.alpha = 0.7;
        addChild(bitmap);

        addEventListener(Event.ENTER_FRAME, render);
    }


}
}
于 2013-08-14T17:52:37.117 に答える