プログラマのためのFlash遊び方

第7回 Flashでジェネレータを作ってみよう

この記事を読むのに必要な時間:およそ 5 分

位置とサイズの更新

update()メソッドは表示オブジェクトの位置やサイズを更新します。コンストラクタから1回呼ばれたあとは,テキスト入力欄の文字が変更されるたびに呼び出されます。

udpate()メソッドの実装は次のようになっています。

// 表示を更新する
private function update():void {
    // 文字列の更新
    previewText.text = inputText.text;            --(1)

    // 最後の1文字の色を変更する
    var tf:TextFormat = new TextFormat();                    
    tf.color = 0xfd1e73;                                     |(2)
    previewText.setTextFormat(tf, inputText.text.length - 1);
    
    // ハイライトのサイズを変更する
    hilight.width = previewText.textWidth;         (3)
    hilight.height = previewText.textHeight * 1.5; 

    // バッジの位置を移動する
    badge.x = previewText.textWidth + 20;         --(4)

    updateReflection();                           --(5)
}

上記コード中の行末の注釈は次のとおりです。

(1)
プレビュー文字をテキスト入力欄に入力された文字列に変更します。
(2)
setTextFormat()メソッドを利用して,最後の1文字を0xfd1e73(ピンク色)に変更しています。
(3)
明るくするハイライトをプレビュー文字の大きさに合わせて拡大しています。
(4)
BETAのバッジを文字列の右側に移動しています。
(5)
反射効果を更新します。

反射効果の描画

udpateReflection()メソッドではBitmapDataクラスを利用して反射効果を描画してます。BitmapDataクラスは読んで字のごとく,ビットマップ画像を扱うためのクラスです。

Flashはベクターグラフィックのイメージが強いので,ビットマップという言葉には違和感があるかもしれません。BitmapDataはピクセル単位で見た目を修正できるので,ベクターだけでは難しい効果を実現することができます。

BitmapDataオブジェクトの作成

まず,BitmapDataオブジェクトを作成します。コンストラクタには画像の縦横のサイズを指定します。

var bmd:BitmapData = new BitmapData(preview.width, previewText.height * 2);

ここでは,プレビュー表示2つ分の領域を持ったBitmapDataを作成しています。

次に,fillRect()メソッドで,全体を白色(0xffffffff)に塗ったあと,draw()メソッドでプレビュー表示をBitmapDataオブジェクトに描画しています。

bmd.fillRect(bmd.rect, 0xffffffff);
bmd.draw(preview);

プレビュー表示には,⁠プレビュー文字」⁠明るくするハイライト」⁠BETAのバッジ」の3つが格納されているため,これら3つの内容がBitmapDataに描画されます。ここで描画したピクセル情報は反射効果を表示するために一時的なデータとして利用します。

テキストの高さを取得

プレビュー文字のすぐ下に反射効果を表示したいので,getColorBoundsRect()メソッドを使って正確にテキストの高さを調べます。

var textHeight:int = bmd.getColorBoundsRect(0xffffffff, 0xffffffff, false).bottom;

例えば,Gとgでは文字の下端が異なります。そこで,getColorBoundsRect()メソッドで白色(0xffffffff)を含まない範囲を取得します。その範囲の下端(bottom)の値をtextHeight変数に格納しています。TextFieldクラスのtextHeightプロパティでは,ここまで細かい高さを取得することはできません。

反射の描画

準備は完了しました。文字のすぐ下に上下反転させながら描画していきます。

// 映り込みを描画していく
for(var i:int = 0; i < textHeight; i++) {
    var multiplier:uint = Math.max(0, i/ textHeight * 64);
    bmd.merge(bmd, new Rectangle(0, i, preview.width, 1), 
        new Point(0, textHeight * 2 - i + 2), 
        multiplier, multiplier, multiplier, 256);
}

for文を利用して,上から1ラインずつ転送しています。文字の下ほど濃く,上に行くほど薄く表示されるように,multiplierの値を調整しています。

merge()は,コピー元のピクセルとコピー先のピクセルを合成するメソッドです。

merge(
    sourceBitmapData:BitmapData,  // 転送元の BitmapData
    sourceRect:Rectangle,         // 転送元の範囲
    destPoint:Point,              // 転送先の座標
    redMultiplier:uint,           // 赤チャンネルに乗算する数値
    greenMultiplier:uint,         // 緑チャンネルに乗算する数値
    blueMultiplier:uint,          // 青チャンネルに乗算する数値
    alphaMultiplier:uint          // αチャンネルに乗算する数値
  ):void

redMultiplier~alphaMultiplierのパラメータは,RGBと透明度のそれぞれのチャンネルごとに,転送元と転送先のどちらの色を強く出すかを0~256の範囲で指定します。

反射効果が描画できたら,上半分のプレビュー表示をそのまま転写したデータは不要です。fillRect()メソッドを利用して白色で塗りつぶしておきます。

// 反射以外を削除
bmd.fillRect(new Rectangle(0, 0, preview.width, textHeight), 0xffffffff);

消さずに残しておいてもよさそうなのですが,実はBitmapDataに文字列を描画すると元の文字列よりもギザギザに描画されてしまいます。ギザギザが残っていると汚いので消しておきます。

メモリへの配慮

あとはBitmapDataを表示するだけですが,その前に,前回のupdateReflection()呼び出しで表示したBitmapDataを破棄しておきます。

if(reflection.bitmapData) {
    reflection.bitmapData.dispose();
}

基本的に,ActionScript 3.0では不要になったメモリはガーベッジコレクタが廃棄してくれます。ただ,BitmapDataオブジェクトは消費するメモリ量が多いので,手動でメモリを解放するdispose()メソッドが用意されています。

BitmapDataの表示

前回のメモリも廃棄できたところで,今回作成したBitmapDataオブジェクトを表示します。

reflection.bitmapData = bmd;

BitmapオブジェクトのbitmapDataプロパティに指定すれば,Bitmapオブジェクトの中身としてBitmapDataオブジェクトの内容が表示されます。

まとめ

今回はジェネレータのソースコードを詳しく流れを見てきました。今までのサンプルに比べて,だいぶ複雑な構成になっています。コードの分量は多いですが,新しい文法は登場していません。この連載を通じて解説した内容が理解できていれば,基本的なプログラミングには困らないと思います。

今後は,皆さんの力で,Flex 3リファレンスガイドを見たり,分からない内容を検索したりしながら,色々なクラスの使い方をマスターしていってくださることを期待しています。

今回でActionScript 3.0の解説は終わりです。次回は,Flex 3フレームワークについて簡単にご説明します。

著者プロフィール

最田健一(さいたけんいち)

有限会社 CO-CONV勤務のプログラマ。京都在住の京都好き。趣味で ActionScript 3.0やFlex 2を触っていたら,いつの間にか仕事でも使うことになっていた。個人ブログは「てっく煮ブログ」。

URLhttp://tech.nitoyon.com/