FrocessingではじめるActionScriptドローイング

第3回アニメーションとイベント処理

前回は基本描画APIを使って静止画を描くプログラムを紹介しましたが、今回はアニメーションやマウスイベントなどを使った動的なグラフィックの描画について解説します。また、曲線の描画、乱数の利用についても解説します。

動きのあるグラフィックの描画

まずは、以下のプログラムリスト1と実行結果をご覧ください。前回解説したキャンバスの回転の例TransformSampleに動きを加えたものです。

リスト1 AnimationSample
package {
  import frocessing.display.F5MovieClip2D;
  [SWF(width=465,height=465,backgroundColor=0x000000)]
  public class AnimationSample extends F5MovieClip2D
  {
    private var n:int;
    private var r:Number;
    private var a:int;
    
    //描画プログラムの初期化(ADDED_TO_STAGE)
    public function setup():void   //・・・・・(3)
    {
      n = 30;
      r = 2*Math.PI/n;
      a = 0;
      colorMode( HSV, n, 1, 1 );
      rectMode( CENTER );
      noStroke();
    }
    
    //一定間隔で描画を実行する(ENTER_FRAME)
    public function draw():void    //・・・・・(1)
    {
      //キャンバスをステージの中心へ移動
      translate( 465/2, 465/2 );
      
      //キャンバスを角度a*r回転
      rotate( r * a );             //・・・・・(2)
      
      //描画
      for ( var i:int = 0; i < n; i++ ) {
        rotate( r );
        fill( i, 1, 1 );
        rect( 150, 0, 36, 10, 4, 4 );
      }
      a++;
    }
  }
}
図1 リスト1(AnimationSample)の実行結果

描画関数 draw

前回までは描画プログラムをコンストラクタ内に記述していましたが、リスト1ではdraw()関数内に場所を変えています(1)[1]⁠。draw()は一定の時間間隔で繰り返し実行される特別な関数です。時間間隔はフレームレートで指定した値によって決まります。フレームレートが30であれば間隔は1/30秒です。

public function draw():void { }

グラフィックはdraw()が実行される度にクリアされ、毎回新しく描画されることになります。リスト1ではキャンバスの回転角度を変化させることでグラフィックに動きを与えています(2)。

drawの制御

draw()は自動的に繰り返し実行されますが、次の関数で停止・再開を制御できます。

noLoop()  //draw()を停止
loop()    //draw()を再開

draw()の描画プログラムを明示的に実行する場合はredraw()を使います。

redraw()  //draw()による描画を実行

初期化関数 setup

リスト1のsetup()はプログラムの表示時に実行されます(3)。繰り返し実行する必要がない初期化の処理などを記述します。

public function setup():void { }

draw()はsetup()の実行後に開始されます。

イベントとの対応

setup()とdraw()は自動的にFlashのイベントに割り当てられます。次の表で関数と対応するイベントを確認してください。

表1 イベントとの対応
関数名イベント
drawEvent.ENTER_FRAME
setupEvent.ADDED_TO_STAGE

※クラス内でこれらの関数を実装する場合はpublic属性を指定する必要があります。

マウスとキーボードの処理

AS3でマウスやキーボードのイベント処理を行う場合はイベントリスナーを記述する必要がありますが、Frocessingではイベントに対応した名前で関数を記述するだけでイベントを受け取ることができます。AS2のイベント処理と同じようなものです。

イベント関数

次のFlashはリスト1にマウスイベント処理を行うプログラムリスト2を追加したものです。マウスを押すとアニメーションが停止し、離すと再開されます。

リスト2 マウスイベント処理
・・・
//MOUSE_DOWNイベント時に実行
public function mousePressed():void {
  noLoop();
}

//MOUSE_UPイベント時に実行
public function mouseReleased():void {
  loop();
}
・・・
図2 リスト2(AnimationSample2)を追加した実行結果

マウス・キーボードイベントに対応した関数は次の6つです。

※関数名はProcessingに準じているためFlashのイベント名と異なります。

表2 マウス・キーボードのイベント関数
関数名イベント
mousePressedMouseEvent.MOUSE_DOWN
mouseReleasedMouseEvent.MOUSE_UP
mouseClickedMouseEvent.CLICK
mouseMovedMouseEvent.MOUSE_MOVE
keyPressedKeyboardEvent.KEY_DOWN
keyReleasedKeyboardEvent.KEY_UP

マウス・キーボードのプロパティ

次のプロパティは、よく使われるマウスとキーボードの状態を示します。

表3 マウス・キーボードのプロパティ
プロパティ状態
isMousePressedマウスが押されている(Boolean)
pmouseX直前のマウス座標(Number)
pmouseY直前のマウス座標(Number)
isKeyPressedキーが押されている(Boolean)
keyCode最後に押されたキーコード(uint)

曲線の描画

Graphicsクラスでは2次ベジェ曲線(curveTo)を使って曲線を描画することができますが、描きたい曲線によってはプログラムが冗長になる場合があります。Frocessingは2次ベジェ曲線に加えて、3次ベジェ曲線、スプライン曲線のAPIが提供されており、場合によって使い分けることができます。

今回はスプライン曲線について解説します。

スプライン曲線

スプライン曲線は任意の座標を通る滑らかな曲線を描きたい場合に適しています。ベジェ曲線のようにコントロール点を指定する必要がありません図3)。

図3 2次ベジェ曲線とスプライン曲線
図3 2次ベジェ曲線とスプライン曲線

4点を指定してスプライン曲線を描画します。実際に描画されるのは(x2,y2)、(x3,y3)を結ぶ曲線です。

curve( x0, y0, x1, y1, x2, y2, x3, y3 )

curveVertex

より複数の座標を指定して連続した曲線を描画する場合はcurveVertex()を使いますリスト3⁠。前後に記述するbeignShape()、endShape()は座標の開始と終了を示します。curve()と同様に最初と最後の座標には曲線が描画されない点に注意してください。

リスト3 curveVertex
beginShape();
curveVertex( x0, y0 );
curveVertex( x1, y1 );
curveVertex( x2, y2 );
curveVertex( x3, y3 );
curveVertex( x4, y4 );
・・・
endShape();

第1回で紹介したサンプルコードFrocessingSampleはこの方法で曲線を描画しています。

vertex

vertex()はcurveVertex()と同じように複数の座標を指定する関数で、曲線ではなく直線が描画されますリスト4⁠。GraphicsクラスのmoveTo()、lineTo()に該当します。

リスト4 vertex
beginShape();
vertex( x0, y0 );
vertex( x1, y1 );
vertex( x2, y2 );
・・・
endShape();

次のFlashはマウスドラッグにより曲線(curveVertex)を描画するプログラムです。何かキーを押すと曲線が直線(vertex)となるので違いを確認してみましょう。プログラムはWonderflでご覧ください。

図4 CurveSample

乱数の利用

Frocessingには乱数を発生させる関数が2つ用意されています。random()とnoise()です。

random()は引数で指定した値a~bの範囲で乱数を発生させます。bを省略した場合は0~aの範囲となります。

random( a, b )

noise()はPerlinノイズを発生させます。yとzは省略できます。

noise( x, y, z )

連続的な引数を指定することで自然に変化する乱数を得ることができますリスト6図5⁠。

リスト5 Perlinノイズ
colorMode( RGB, 1.0 );
for ( var i:int = 0; i < 200; i++ ){
  for ( var j:int = 0; j < 200; j++ ) {
    stroke( noise( i*0.02, j*0.02 ) );
    point( i, j );
  }
}
図5 リスト5(Perlinノイズ)の実行結果
図3 2リスト5(Perlinノイズ)の実行結果

第1回で紹介したサンプルコードFrocessingSampleの曲線の動きでnoise()を使用しているので参考にしてください。

ペイントプログラムをつくってみよう

最後に、マウスを使ったペイントプログラムをつくってみましょう。

まずは、次のプログラムリスト6と実行結果をご覧ください。マウスの移動に沿って線を描き、クリックで描画内容をクリアするシンプルなペイントプログラムです。

リスト6 PaintSample
package {
  import frocessing.display.F5MovieClip2DBmp;
  [SWF(width=465,height=465,backgroundColor=0x000000)]
  public class PaintSample extends F5MovieClip2DBmp
  {
    public function setup():void
    {
      //キャンバスのサイズ指定
      size( 465, 465 );     //・・・(1)
      //背景の描画
      background( 0 );      //・・・(2)
      //色指定
      stroke( 255, 0.5 );
    }
    
    public function draw():void
    {
      //マウスが押されているときは描画内容をクリア
      if ( isMousePressed )
        background( 0 );
      
      //直線の描画
      line( pmouseX, pmouseY, mouseX, mouseY );//(3)
    }
  }
}
図6 PaintSample

F5MovieClip2DBmp

リスト6のスーパークラスは、これまで利用していたF5MovieClip2DではなくF5MovieClip2DBmpです。違いはdraw()で描画されたグラフィックが画像データ(BitmapData)に重ねて描画される点です[2]⁠。このクラスを利用することで描画した内容をクリアせずに残すことができます。

リスト6では直線を重ねて描くことでマウスの軌跡を表現しています(3)。

キャンバスのサイズ

size()はキャンバスのサイズを指定します(1)。F5MovieClip2DBmpでは描画される画像データ(BitmapData)のサイズとなります。

size( canvasWidth, canvasHeight )

背景色の指定

background()はキャンバスの背景色を指定します(2)。色の指定方法はstroke()やfill()と同じです色の指定方法⁠。background()を実行すると描画内容はクリアされます。

background(色指定)

描画部分を変えてみる

F5MovieClip2DBmpを利用すれば手軽にペイントプログラムをつくることができます。リスト6の描画部分(直線)に手を加えて、いろいろなペイントプログラムを試してみてください。

次のFlashは直線の描画をrandom()を使った円のパーティクルに変更したものです。プログラムはWonderflでご覧ください。

図7 forked from: PaintSample

まとめ

今回解説したdraw()やイベントの関数を使うことで手早くインタラクティブなプログラムをつくることができます。描画プログラムのプロトタイプなどで利用してみてください。次回はペイントプログラムを発展させる過程を紹介する予定です。

おすすめ記事

記事・ニュース一覧