Now loading...

4 月 26

理想的にはクラス内のプロパティは全てprivateにして、クラス外部からプロパティに直接アクセスさせず、かわりにgetter/setterメソッドと呼ばれる関数を用いてプロパティの参照や変更を行うことがOOPで推奨されてるらしい。直接アクセスされて不都合がある理由はよくわからんが、こういった慣例には従っておいた方がよいだろう。

オブジェクト指向プログラミングを実践する際には、クラスのプロパティに直接アクセスすることは推奨されません。クラスではよく、特定のプロパティの読取り用のアクセスに”get”メソッド、書込み用のアクセスに”set”メソッドを定義するということが行われます。

FN0311009 - 黙示的なget/setメソッド - Flash : テクニカルノート

ところでこのsetter/getterメソッドで使う関数名、なんと操作したいプロパティ名と同じ関数名をつけれない。これじゃ使い物にならんがな、と思ってたけどKeith Petersがプロパティ名の頭にアンダースコア(”_”)をつける方法で解決してた。例えばmessageというプロパティにsetter/getterメソッドを用いる場合、こんな感じ。

package{
    public class SomeClass{

        private var _message:String;

        public function SomeClass(){
            //Some codes here.
        }

        public function set message(s:String):void{
            _message = s;
        }

        public function get message():String{
            return _message;
        }
    }
}

これで、クラス外部でこのプロパティ値を変更したい場合はsetter関数経由で

var sc:SomeClass = new SomeClass();

//same as sc.message("Shut the fuck up!!");
sc.message = "Shut the fuck up!!";

クラス外部でこのプロパティ値を参照したい場合はgetter関数経由で

//same as trace(sc.message());
trace(sc.message);

なるほど、getter/setterメソッドを用いる場合のプロパティにはアンダースコアを付けるように決めてしまえば、以下のようにソースを見て混乱することもないし、しかもAS2をやってる人には馴染み深いしね。いいチップだ。

getter メソッドと setter メソッドは便利ですが、多用しすぎるとコードの保守が困難になる場合もあるので注意が必要です。

adobe - getter メソッドと setter メソッドについて

Tags: ,

4 月 08

行列で書くとわかりやすい。ColorMatrixFilter(引数a0 - a19の計20個!)による元のピクセル値(R, G, B, alpha)とフィルター処理後のピクセル値(R_new, G_new, B_new, alpha_new)の関係は以下の通り。

theDisplayObject(DisplayObjectのサブクラス or BitmapDataクラス)に上記フィルターをかける場合は以下の通り。


import flash.filters.ColorMatrixFilter;

var matrix:Array = new Array();
matrix = matrix.concat([a0,a1,a2,a3,a4]);	//R
matrix = matrix.concat([a5,a6,a7,a8,a9]);	//G
matrix = matrix.concat([a10,a11,a12,a13,a14]);	//B
matrix = matrix.concat([a15,a16,a17,a18,a19]);	//alpha
var f:ColorMatrixFilter = new ColorMatrixFilter(matrix);
theDisplayObject.filters = [f];

ColorMatrixFilter クラスを使用すると、入力イメージの各ピクセルの RGBA カラー値とアルファ値に 4 × 5 マトリックス変換を適用することで、新しい RGBA カラー値とアルファ値から成る結果を作成できます。

ColorMatrixFilter - ActionScript 3.0 コンポーネントリファレンスガイド

[関連リンク]
幕末古写真ジェネレータをハックする - てっく煮ブログ

Tags: ,

4 月 01

定義を誤解しやすい

Adobe - ActionScript 3.0 コンポーネントリファレンスガイドの説明によると、フィルター処理に使われる式は以下のとおり。


dstPixel[x, y] = srcPixel[x + ((componentX(x, y) - 128) * scaleX) / 256,
y + ((componentY(x, y) - 128) * scaleY) / 256)]

ごちゃごちゃしている部分をdx, dy(dx, dyの中身については後ほど説明するとしてここでは何らかの変位量と思ってもらえればok)に書き換えて見やすくするとこんな感じ。


dstPixel[x, y] = srcPixel[x + dx, y + dy]

ここでdstPixelとsrcPixelを一般的な形で説明すると

  • dstPixel[x, y]はx-y座標(x, y)におけるフィルター処理後の表示画像のピクセル値
  • srcPixel[x, y]はx-y座標(x, y)におけるフィルター処理前の表示画像のピクセル値

したがって上式を翻訳すると「位置(x, y)におけるフィルター処理後の画像のピクセル値は、位置(x+dx, y+dy)におけるフィルター処理前の画像のピクセル値を採用している」となる。座標系がフィルター処理後の画像を元にしているところがポイント。「位置(x, y)におけるフィルター処理前の画像のピクセルを(x+dx, y+dy)に移動させてその結果を処理後の画像として採用する」演算ではない。まとめておくとDisplacementMapFilterは

  • (正) 位置(x, y)におけるフィルター処理後の画像のピクセル値に、位置(x+dx, y+dy)におけるフィルター処理前の画像のピクセル値を採用するフィルター
  • (誤) 位置(x, y)におけるフィルター処理前の画像のピクセルを(x+dx, y+dy)に移動させてその結果を処理後の画像として採用するフィルター

となる。ここの仕組みが直感的ではないのでわかりにくい。他にも元画像の位置(x+dx, y+dy)にピクセル情報がないことにはフィルター処理不可能なことがわかる。つまり、元画像のサイズ以上に引き延ばしたりする変形を表現することはできない。

変位(dx, dy)の求め方

フィルター処理前・後のピクセルの変位量の分布さえわかれば意図したフィルター効果を表現できる。具体的な関係式の求め方はpsyark.jp - DMFチュートリアル1がわかりやすい。

置き換えマップイメージ

さて画像は2Dなので各ピクセルごとにx, y方向の2成分の変位量(dx, dy)がわからないといけない。各ピクセルごとの変位情報を(手軽に)2成分もたせるためにはどうすればよいか。そこで登場するのが置き換えマップイメージ。各ピクセルにアルファ、R、G、Bの情報を独立して持たせることができるという画像の性質を利用して、(dx, dy)の変位分布を画像情報として押し込めてしまうわけ。独立して格納したい情報は(dx, dy)の2成分なので、置き換えマップイメージのアルファ、R、G、Bチャンネルの4チャンネルのうちお好みの2チャンネルに格納すればよい(例えばdx情報をR、dy情報をBなど。dx, dyに同じチャンネルを使う場合も含めれば選択肢は4×4=16通りもある)。この中途半端に選択肢の自由度があるところがわかりにくい。([dx, dy]分布情報を格納できれば原理的には二次元配列などでもよいが、配列に格納するのが面倒くさいし、そもそもこのフィルターの演算に採用されていないので意味がない)

Adobeが定義している式に戻ってみると、(dx, dy)は次のような式であることがわかる。


dx = (componentX(x, y) - 128) * scaleX / 256
dy = (componentY(x, y) - 128) * scaleY / 256

ここでcomponentX(x, y)は位置(x,y)におけるマップイメージのdxを格納したチャンネル(つまりアルファ、R、G、Bのどれか)のピクセル値(0-255)、componentY(x, y)は位置(x,y)におけるマップイメージのdyを格納したチャンネルのピクセル値(0-255)が入る。scaleX, scaleYはフィルター使用時に後から好きな値が入れられる(0以上の数値)のでわかりやすくするため1を代入しよう。そうすると、上式は以下のようになる。


dx = (componentX(x, y) - 128) / 256
dy = (componentY(x, y) - 128) / 256

画像の各チャンネルは0-255の数値しかとれないので、この場合変位量は-1/2から1/2の値をとることがわかる。変位幅を大きくしたいならscaleXとscaleYをフィルター利用時に調整すればよい(これは例えば、-10から10までの乱数を得るのに(Math.random()-0.5)*20と書くのに似ているかな)。置き換えマップイメージと変位の関係はmiscellaneous [ActionScript 3.0] DisplacementMapFilterがわかりやすい。

Tags: ,

3 月 24

CircleParticle


CircleParticle(	x:Number, y:Number, radius:Number,
fixed:Boolean = false, mass:Number = 1,
elasticity:Number = 0.3, friction:Number = 0)

x:Number: 初期x座標
y:Number: 初期y座標
radius:Number: 円の半径。ゼロok。
fixed:Boolean: オプショナル。初期位置に固定するかどうか(true=固定、false=非固定)。デフォルトはfalse。
mass:Number: オプショナル。質量。デフォルトは1。
elasticity:Number: オプショナル。弾性率。デフォルトは0.3。
friction:Number: オプショナル。表面摩擦係数。デフォルトは0(減衰無し)。

Tags: ,


Now loading...