ActionScript 3.0で始めるオブジェクト指向スクリプティング

第62回 Starlingフレームワークで動的に置いたビットマップをドラッグする

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

今回は,Starlingフレームワークに[ライブラリ]のビットマップからつくったインスタンスを置き,マウスでドラッグしてみる。どちらも少し定義済みActionScript 3.0の場合とは勝手が違う。ふたつに分けて進めていこう。

Starlingフレームワークに[ライブラリ]のビットマップを表示する

まずは準備として,⁠ライブラリ]のビットマップにクラス(Pen)を設定しておく図1)⁠そして,インスタンスをFlashのタイムラインに動的に置くスクリプトから,先に確かめておこう。すでに第34回「3次元空間における回転」ビットマップのインスタンスを動的に配置するで説明した処理のおさらいだ。

図1 ⁠ライブラリ]のビットマップにクラスを設定する

図1 [ライブラリ]のビットマップにクラスを設定する

図1 [ライブラリ]のビットマップにクラスを設定する

[ライブラリ]のビットマップ(クラスPen)は,ActionScript 3.0ではBitmapDataのサブクラスになる。そして,BitmapDataインスタンス(myBitmapData)はそのままタイムラインには置けない。そのため,Bitmapクラスのコンストラクタメソッドに引数として渡したうえで,Bitmapインスタンス(instance)DisplayObjectContainer.addChild()メソッドでタイムラインに加えるのだった。

var myBitmapData:BitmapData = new Pen();
var instance:Bitmap = new Bitmap(myBitmapData);
addChild(instance);

Starlingフレームワークではどうなるか。第1に,starling.display.DisplayObjectのサブクラスでなければ,Starlingのステージ(Stage3D)には置けない。そこで,Bitmapクラスに替えてStarlingのImageクラスを使う。コンストラクタメソッドの引数は,やはりビットマップイメージのオブジェクトだ。ただし第2に,BitmapDataオブジェクトは引数に使えない。Image()コンストラクタには,Textureクラスのオブジェクトを渡さなければならない表1)⁠

表1 ビットマップイメージをステージに表示するために用いるクラス

役割クラス
ActionScript 3.0定義済みStarlingフレームワーク
ビットマップイメージをもつflash.display.BitmapDatastarling.textures.Texture
ビットマップをステージに表示するflash.display.Bitmapstarling.display.Image

だが,使いたいのは[ライブラリ]のビットマップつまりBitmapDataインスタンスだ。この場合には,静的メソッドTexture.fromBitmapData()を用いればよい。引数のBitmapDataオブジェクトをTextureオブジェクトに変換して返してくれる。⁠ライブラリ]のビットマップをTextureオブジェクトに換え,Imageインスタンスに入れてStarlingフレームワークのステージに置くクラス定義(MySprite)がつぎのスクリプト1だ。

スクリプト1 Starlingフレームワークに[ライブラリ]のビットマップを置く

// ActionScript 3.0クラス定義ファイル: MySprite.as
package  {
  import flash.display.BitmapData;
  import starling.display.Sprite;
  import starling.display.Image;
  import starling.textures.Texture;
  import starling.events.Event;
  public class MySprite extends Sprite{
    private var instance:Image;
    public function MySprite() {
      addEventListener(Event.ADDED_TO_STAGE, initialize);
    }
    private function initialize(eventObject:Event):void {
      var myBitmapData:BitmapData = new Pen();
      var myTexture:Texture = Texture.fromBitmapData(myBitmapData);
      instance = new Image(myTexture);
      addChild(instance);
      instance.x = stage.stageWidth / 2;
      instance.y = stage.stageHeight / 2;
      instance.pivotX = instance.width / 2;
      instance.pivotY = instance.height / 2;
    }
  }
}

これで[ライブラリ]に納めたビットマップのイメージが,ステージ中央に表示される図1)⁠前掲スクリプト1は,Imageインスタンスをつくるまでの処理を除けば,前回の「StarlingフレームワークでStage3Dを試す」で定義したクラスと基本的に変わらない。もちろん,前回述べたとおり,FLAファイルにはつぎのフレームアクションが書かれていて,⁠パブリッシュ設定]も正しく行われているものとする。

// フレームアクション: メインタイムライン
import starling.core.Starling;
var myStarling:Starling = new Starling(MySprite, stage);
myStarling.start();

図2 ビットマップのイメージがステージ中央に表示される

図2 ビットマップのイメージがステージ中央に表示される

定義済みActionScript 3.0のフレームアクションによるドラッグ

ふたつ目の課題はマウスドラッグだ。これも,定義済みActionScript 3.0のフレームアクションによるスクリプティングを先に確かめておこう。タイムラインにはMovieCliipインスタンス(my_mc)が予めおかれているものとする。ドラッグは3つのマウスイベントを組合わせて扱う※1)⁠

  1. InteractiveObject.mouseDownイベント(定数MouseEvent.MOUSE_DOWN)のリスナー
    • InteractiveObject.mouseMoveイベントにドラッグのためのリスナーを加える。
    • InteractiveObject.mouseUpイベントにドラッグ終了のリスナーを加える。
  2. InteractiveObject.mouseMoveイベント(定数MouseEvent.MOUSE_MOVE)のリスナー
    • インスタンスの位置をマウスポインタの座標に追随させる。
  3. InteractiveObject.mouseUpイベント(定数MouseEvent.MOUSE_UP)のリスナー
    • InteractiveObject.mouseMoveイベントのリスナーを除く。
    • InteractiveObject.mouseUpイベントのリスナーを除く。

3つのイベントリスナーで,タイムラインに置かれたインスタンス(my_mc)をドラッグできるように組立てたフレームアクションがつぎのスクリプト2だ。

スクリプト2 タイムラインに置かれたインスタンスをドラッグするフレームアクション

// フレームアクション: メインタイムライン
var nOffsetX:Number;
var nOffsetY:Number;
my_mc.addEventListener(MouseEvent.MOUSE_DOWN, xMouseDown);
function xMouseDown(eventObject:MouseEvent):void {
  nOffsetX = my_mc.mouseX;
  nOffsetY = my_mc.mouseY;
  stage.addEventListener(MouseEvent.MOUSE_MOVE, xDrag);
  stage.addEventListener(MouseEvent.MOUSE_UP, xMouseUp);
}
function xDrag(eventObject:MouseEvent):void {
  my_mc.x += my_mc.mouseX - nOffsetX;
  my_mc.y += my_mc.mouseY - nOffsetY;
}
function xMouseUp(eventObject:MouseEvent):void {
  stage.removeEventListener(MouseEvent.MOUSE_MOVE, xDrag);
  stage.removeEventListener(MouseEvent.MOUSE_UP, xMouseUp);
}

スクリプト2について,ふたつ補っておこう。ひとつ目は,InteractiveObject.mouseMoveInteractiveObject.mouseUpイベントのリスナーをStageオブジェクトに加えたことだ。これは,InteractiveObject.mouseDownイベントと異なり,マウスを素速く動かすと,イベントがドラッグしているインスタンスの外で起こってしまう場合に備えた。

ふたつ目は,InteractiveObject.mouseDownイベントのリスナー関数(xMouseDown)が,インスタンスから見たマウスポインタの座標を変数(nOffsetXとnOffsetY)にとっていることだ。なぜなら,InteractiveObject.mouseMoveイベントのリスナー(xDrag())がただマウス座標にインスタンスの位置を合わせれば,ポインタの先にインスタンスの基準点がきてしまう図3)⁠そうならないためには,はじめにクリックしたインスタンス上の座標を覚えておき,ドラッグするときはその分を補正しなければならないのだ。

図3 補正しないとドラッグしたときインスタンスの基準点がマウスポインタの座標にくる

図3 補正しないとドラッグしたときインスタンスの基準点がマウスポインタの座標にくる 図3 補正しないとドラッグしたときインスタンスの基準点がマウスポインタの座標にくる

※1
これまで【特別編】で解説してきたActionScript 3.0を最適化するという見方でいえば,ドラッグでインスタンスを動かすのはInteractiveObject.mouseMoveよりDisplayObject.enterFrameイベントのリスナーで扱う方が負荷は軽い。この後Starlingフレームワークと比べるために,マウスイベントだけで組み立ててみた。

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書

コメント

コメントの記入