Flashでアイコンエディタの外観を作る
まず、新規Flashドキュメントを作成し、「icon.fla」という名前でプロジェクトを保存してください。そして、アイコンエディタの外観を作っていきます。
ここで作成するアイコンエディタは、アイコンを描画する「main_canvas_mc」、色を選択するパレット「palette_mc」、保存を行う「save_btn」、選択用カーソルの「select_mc」と4つのムービークリップ(ボタン)で構成されます。
以下にそれぞれのムービークリップの作り方を説明します。
main_canvas_mc(クラス:MC_CANVAS)
これは、矩形ツールで四角形を描いたものを選択し、右クリックして[シンボルの変換]メニューを選択し、ムービークリップに変換したものです。
このとき、下の図のようにリンケージを設定します。リンケージの[ActionScriptに書き出し]をチェックして、[AS 2.0クラス]の項目に「MC_CANVAS」と入力します。
![シンボルの作成 シンボルの作成](http://cz-cdn.shoeisha.jp/static/images/article/418/symbol.gif)
これにより、MovieClip
を継承したクラスMC_CANVAS
と、このムービークリップが関連付けられます。MC_CANVAS
は、プロジェクトと同じフォルダに「MC_CANVAS.as」という名前で作る必要があります。Javaと同じように、クラス名とファイル名を同じにしなくてはなりません。ファイル「MC_CANVAS.as」の内容は、後で説明します。
シンボルに変換したら、「main_canvas_mc」という名前をつけます。
palette_mc(クラス:MC_PALETTE)
これも上と同じで、矩形ツールで四角形を描いたものをシンボルに変換したものです。リンケージの設定で、[AS 2.0クラス]を「MC_PALETTE」に設定します。
save_btn(クラス:Button)
これは、Flash 8の標準コンポーネントButton
です。メインメニューの[ウィンドウ]-[コンポーネント]をクリックしてコンポーネントを表示し、Button
をステージにドロップして、「save_btn」という名前を付けます。
select_mc(クラス:MovieClip)
これは、パレットで選択している色を表すためのカーソルです。パカパカと点滅するようなムービーを作り、「select_mc」という名前をつけます。
これで外観は完成です。後は、クラスファイルを作成します。
MC_CANVASクラスの作成
クラスMC_CANVAS
は、プロジェクトと同じフォルダに「MC_CANVAS.as」という名前のファイルを作り、その中に記述します。これは、ムービークリップそのものなので、MovieClip
を継承してクラスを作ります。クラスの雛形は次のようになります。
class MC_CANVAS extends MovieClip { }
コンストラクタとonEnterFrame
まずは、MC_CANVAS
のコンストラクタを作成します。
class MC_CANVAS extends MovieClip { function MC_CANVAS() // コンストラクタ { onEnterFrame = onInit; } }
コンストラクタでは、MovieClip
のイベントonEnterFrame
にonInit()
という関数を設定しています。関数onInit()
の内容は以下のとおりです。ここでは、変数の初期化処理などを行っています。
function onInit() { delete onEnterFrame; // 変数の初期化 this.createEmptyMovieClip("canvas_mc", 9999); mouse_down = false; canvas_width = this._width; canvas_height = this._height; // ピクセルの大きさ,色 iconResize(16, 16); // マウスイベントを設定 this.onMouseDown = tileMouseDown; this.onMouseMove = tileMouseMove; this.onMouseUp = tileMouseUp; }
なぜ、コンストラクタの中で初期化処理をしないのかは、コンストラクタの呼ばれるタイミングと関係しています。クラスのコンストラクタは、フレームの最初に呼ばれます。
そのため、コンストラクタの中ではクラスの初期設定だけを行い、他のムービークリップのインスタンスに何かしらの初期化や設定をしたい場合には、onEnterFrame
のイベントで行う必要があります。
しかし、onEnterFrame
のイベントは、フレームごとに発生してしまうので、onInit()
関数の先頭では、「delete onEnterFrame;
」と書いて、再度、初期設定の関数が実行されないようにします。
そして、初期化関数onInit()
の内容ですが、まず変数の初期化を行い、次に描画用ムービークリップcanvas_mc
を作成します。そして、関数iconResize()
ではアイコンデータを初期化して、タイルの描画を行います。その後、マウスイベントを設定しています。
なお、関数iconResize()
を呼ぶとき、引数を「32, 32」で渡すと、32ドットアイコンを作成できるように工夫しています。
アイコンの1ドットを描画する
アイコンの1ドット分のタイルは、Drawing APIを利用して描画しています。以下がその関数の内容です。
function tileDraw(x:Number, y:Number) { var col = tile_array[y][x]; var x1 = x * tile_width; var x2 = (x+1) * tile_width; var y1 = y * tile_width; var y2 = (y+1) * tile_width; canvas_mc.lineStyle(1,0); canvas_mc.beginFill(col, 100); canvas_mc.moveTo(x1, y1); canvas_mc.lineTo(x2, y1); canvas_mc.lineTo(x2, y2); canvas_mc.lineTo(x1, y2); canvas_mc.endFill(); }
ここで出てきたcanvas_mc
というのは、初期化関数onInit()
の中で生成した描画用のMovieClip
です。Drawing APIを使った描画では、空のムービークリップを生成し、そこへ描画すると間違いがありません。
マウスイベントの処理
次に、マウスのイベント処理部分は次のようになります。
function tileMouseDown() { if (_xmouse < 0 || _xmouse >= canvas_width) return; if (_ymouse < 0 || _ymouse >= canvas_height) return; mouse_down = true; tileMouseMove(); } function tileMouseUp() { mouse_down = false; } function tileMouseMove() { if (!mouse_down) return; var px = Math.floor(this._xmouse / tile_width); var py = Math.floor(this._ymouse / tile_width); if (px < 0 || px >= tile_xcount) return; if (py < 0 || py >= tile_ycount) return; if (tile_array[py][px] != draw_color) { tile_array[py][px] = draw_color; tileDraw(px, py); } }
関数tileMouseDown()
ですが、これはマウスがクリックされた時に発生するイベントonMouseDown
に設定されている関数です。これは、アイコンの描画部分の上でマウスボタンが押された場合に、クラス変数mouse_down
をtrueに設定します。そして、マウスボタンが離された時に発生するイベントonMouseUp
に設定されているのがtileMouseUp()
関数でmouse_down
をfalseに戻すだけです。
そして、マウスポインタが動いた時に発生するイベントonMouseMove
に設定した関数tileMouseMove()
では、mouse_down
がfalseのときは、すぐに関数を抜けるようになっています。これにより、マウスボタンが押されている間のみ、描画処理を行います。
そして描画の内容ですが、アイコンのパターンデータであるtile_array
の内容を現在のパレットの色に変更し、タイルの描画を行う関数tileDraw()
を呼ぶというものになっています。
また、マウスがムービークリップに被っているかどうか座標を判定するのに、this._width
ではなく、初期化処理でthis._width
を代入した変数canvas_width
を利用している理由は、何かしらのきっかけで、this._width
のサイズが変わってしまうことがあるのを考慮しているためです。