プログラミング工房
TOP
Flex基本
開発環境 JavaScript連携 PHP連携1 PHP連携2(AMFPHP) ウィンドウ ボタンスキン 矩形スキン ローカルファイル(テキスト) F5等の対策 ローカルファイル(イメージ) ダウンロード、アップロード 1枚の画像のカラーを変更 時間のかかる計算処理 外部SWFの読込み
Flexで3D
Flexだけで3D Papervision3Dを使ってみる 3Dオブジェクト カメラ、前後判定の工夫しました 自由な形状を作成
Flexでクラス
Class1(白黒ゲームの盤) Class2(白黒ゲームのプレイヤー) Class3(プレイヤーを外部SWF)
PHP
共通関数1
Flexの作品
お問合せの説明 サンプルのソース表示の説明 分子構造の表示(PDBファイル) マンデルブロ集合の画像作成 swf参加型白黒ゲーム(Reversi) ストップウォッチ WEB素材
AIR
AIRを使ってみる ソースファイルのHTML変換を作る
etc.
マンデルブロ集合のギャラリー ジュリア集合のギャラリー wonderflを使ってみました お問合せ

Flex4基本-時間のかかる計算処理

■2011.04.05:作成
■機能アップしたマンデルブロ集合の画像作成プログラム があります。(2011.04.07)
サンプル サンプルのソース

時間のかかる計算処理:マンデルブロ集合の作図

時間のかかる計算処理としてマンデルブロ集合の作図プログラムをサンプルで作成しました。
マンデルブロ集合
サンプル にありますので「描画開始」ボタンを押せばそれなりに動きます。
「イメージ保存」ボタンで作った画像をローカルPCに保存することも出来ます。
こんなイメージを作成することが出来ます。
作成サンプル

ENTER_FRAMEを使って時間のかかる計算処理に対応

マンデルブロ集合の作図には時間がかかります。普通にFlexで作ると計算が終わるまで白い画面の まま動いているのかどうかわからなくなります。
VB.netならばDoEvents()とかを使って対応します。

Flexでは「ENTER_FRAME」を利用すれば対応できます。
関数を「ENTER_FRAME」のイベントに登録しておけば、一定間隔ごとに関数を実行します。
実行中に描画の更新、イベントの受付等を行うことが出来ます。

まず、マンデルブロ集合の作図プログラムの基本的流れ
 Y方向のループ
  X方向のループ
   X、Yでのカラーを求め、描画(多少時間のかかる処理)
  X方向のループend
 Y方向のループend
これを「ENTER_FRAME」に対応した形に変更します。
 Yの初期値セット
 「ENTER_FRAME」に1行描画関数を登録
     :
 1行描画関数
  X方向のループ
   X、Yでのカラーを求め、描画(多少時間のかかる処理)
  X方向のループend
  YのカウントUP
  Yが終了条件なら「ENTER_FRAME」の1行描画関数を削除

実際のソースは以下の様になります。
private function fncDispStart():void {
    //描画に必要なパラメータセット
    intBMw=nsImgW.value;
    intBMh=nsImgH.value;
    intKurikaesi = nsKuri.value;
    uintHassan=cpHassan.selectedColor;
    arrColor = new Array(
        cp0.selectedColor, cp1.selectedColor,
        cp2.selectedColor, cp3.selectedColor,
        cp4.selectedColor, cp5.selectedColor,
        cp6.selectedColor, cp7.selectedColor,
        cp8.selectedColor, cp9.selectedColor,
        cp10.selectedColor, cp11.selectedColor,
        cp12.selectedColor, cp13.selectedColor,
        cp14.selectedColor, cp15.selectedColor);
    var sizW:Number = sdSiz.value * 2.4 / 200;
    var sizH:Number = sizW * intBMh / intBMw;
    xMin=sdxc.value-sizW;
    xMax=sdxc.value+sizW;
    yMin=-sdyc.value-sizH;
    yMax=-sdyc.value+sizH;
    xStep=(xMax-xMin)/intBMw;
    yStep=(yMax-yMin)/intBMh;
    bmItiX=0;
    bmItiY=0;

    // 既存イメージの破棄・新イメージ登録
    while (uiGrf.numChildren) uiGrf.removeChildAt(0);
    bdMandelbrot = new BitmapData(intBMw, intBMh, false, 0xffffff);
    var bm:Bitmap = new Bitmap(bdMandelbrot);
    uiGrf.addChild(bm); 
    //描画サイズ等セット
    uiGrf.width = bdMandelbrot.width;
    uiGrf.height = bdMandelbrot.height;
    grpPreview.width = bdMandelbrot.width;
    grpPreview.height = bdMandelbrot.height;
    //繰り返しイベントに1行描画を登録
    this.addEventListener(Event.ENTER_FRAME, fncMandelbroLine);
}
//マンデルブロ集合1行描画処理
private function fncMandelbroLine(evt:Event):void {
    var b:Number = yMin + bmItiY * yStep;
    for (bmItiX = 0; bmItiX < intBMw; bmItiX++) {   //X方向のループ
        var a:Number = xMin + bmItiX * xStep;
        bdMandelbrot.setPixel(bmItiX, bmItiY, fncGetColor(a,b));
    }
    bmItiY++;   //次の1行にする
    if (bmItiY>=intBMh) {       //描画終了
        //繰り返しイベントの1行描画を削除
        this.removeEventListener(Event.ENTER_FRAME,fncMandelbroLine);
        fncTitle(2);
        bolRun = false;
        fncJyoutai();
    }
    else {
        fncTitle(1);
    }
}
//マンデルブロ集合の1点でのカラー
private function fncGetColor(a:Number, b:Number):uint {
    var uiCol:uint = uintHassan;    //発散しないときのカラー
    var x:Number=0;
    var y:Number=0;
    var i:int = 0;
    for(i=0;i<=intKurikaesi;i++){   //最大繰り返し数繰り返し
        var x2:Number=x*x;
        var y2:Number=y*y;
        var zx:Number=x2-y2-a;
        var zy:Number=2*x*y-b;
        x=zx;
        y=zy;
        if (x2 + y2 >= 4) {
            var id:int = i % arrColor.length;
            uiCol= arrColor[id];
            break;
        }
    }
    return uiCol;
}

処理中止

今回のサンプルは「描画開始」ボタンを描画中(処理中)に「描画中止」ボタンに変更して処理中止が出来るようにしています。

処理の中止は、「ENTER_FRAME」の1行描画関数を削除することで中止することが出来ます。
また、「ENTER_FRAME」に1行描画関数を再登録すれば再開することが出来ます。
//描画開始/描画中止ボタン==============================================
private function onRun():void {
    if (bolRun == false) {  //描画開始
        bolRun = true;
        fncJyoutai();
        fncDispStart();
    }
    else {                  //描画中止
        //繰り返しイベントの1行描画を削除
        this.removeEventListener(Event.ENTER_FRAME,fncMandelbroLine);
        Alert.show("処理を中止してよいですか?",
                    "Mandelbrot", Alert.YES | Alert.NO, this, alertClickRun);
    }
}
// 処理を中止してよいですか?:確認
private function alertClickRun(evt:CloseEvent):void {
    if (evt.detail == Alert.YES) {  //TES(描画中止)
        fncTitle(3);
        bolRun = false;
        fncJyoutai();
    }
    else {                          //NO(描画再開)
        //繰り返しイベントに1行描画を再登録
        this.addEventListener(Event.ENTER_FRAME, fncMandelbroLine);
    }
}

プログラミング工房