アプリ版:「スタンプのみでお礼する」機能のリリースについて

初めまして、ACEと言います。

アクションスクリプトの質問になります。

ライブラリ中にあるグラフィックを、切り分けてMC化することは可能でしょうか?

具体的には以下の通りです。

1.ライブラリ中にある画像(400x400)を100x100単位で切り分ける(16個)
2.それぞれを別々のMCにして配置

画像の切り分けができてしまえばあとはattachMovieするだけだと思っているのですが、
画像の切り分けが上手くいきません。

Bitmapクラスを使えばできそうなのですが、、、
参考になるサイト等ご教授頂けたらと思います。

以上。よろしくお願いいたします。

A 回答 (2件)

BitmapData クラスの loadBitmap メソッドで、ライブラリにある”ビットマップシンボル”の絵をビットマップデータとして取り込むことができます。


(グラフィック・ムービークリップシンボルの絵は loadBitmap メソッドでは取り込めません)
このメソッドで取り込んだ絵を、別の BitmapData オブジェクトに copyPixels メソッドで分割コピーする、という方法はいかがでしょう。

BitmapData オブジェクトで管理する絵のデータは内部では配列変数になっていますが、操作するデータの位置を座標や大きさで扱えるように設計されています。
copyPixels メソッドは、指定の座標から任意の大きさの絵のデータを別の BitmapData オブジェクトにコピーするメソッドです。


次のように考えます。

loadBitmap でシンボルの絵を取り込んで作った BitmapData オブジェクトをコピー元にし、この一部分をコピーした BitmapData オブジェクトを 16 個、copyPixels メソッドを使って作成します。

1度 BitmapData オブジェクトを作っておけば、絵のデータは dispose メソッドで破棄するまでメモリの中に残っています。
あとはムービークリップに関連付けて表示するだけですので、attachMovie とは少々使い方が違いますが、何回でも再利用することができます。

-------------------------------------------------------------

loadBitmap メソッドを使うには、リンケージという設定が必要です。
ライブラリにあるビットマップシンボルを選んだ状態で、右クリック( Mac では control +クリック)で出すメニューから「リンケージ...」を選択してください。「リンケージプロパティ」パネルが開きます。

” ActionScript に書き出し”にチェックを入れると、”最初のフレームに書き出し”にも同時にチェックが入ります。
ビットマップシンボルが極端に大容量のものでなければ、最初のフレームに書き出しても支障はないかと思います。
最初のフレームに書き出されると問題がある場合は他のフレームに書き出す方法もありますが、この話は割愛させていただきます。

この2つにチェックが入っていることを確認し、”識別子:”の項目に名前を入力してください。
loadBitmap メソッドでシンボルの絵を取り込む時には、ここで付けた名前を指定します。
仮に” PICTURE ”と付けたとします。


以上で準備は完了です。
次はスクリプトを書きます。

*****************************

ライブラリに、リンケージ識別子” PICTURE ”と付けた、400 × 400 ピクセルのビットマップシンボルがあるとします。
このシンボルの絵を取り込み、分割コピーして 100 × 100 ピクセル× 16 個の BitmapData オブジェクトを作成するスクリプトは、大体、次のようになります。
このスクリプトはフレームに設定してください。

(↓各行頭に全角のスペースが入っています。コピーする際は、全て半角のスペースかタブに置き換えてください)



 import flash.display.BitmapData;
 import flash.geom.*;


 //分割したかけらの大きさを保持
 piece_w = 100;
 piece_h = 100;

 //コピー作業に使うRectangleとPointオブジェクトを作成
 rect = new Rectangle();
 copy_point = new Point( 0 , 0 );


 //ライブラリにあるビットマップシンボルの絵を取り込む
 org_bmp = BitmapData.loadBitmap( "PICTURE" );


 //画像を4×4個に16分割し、BitmapDataオブジェクトにコピーする
 //オブジェクト名には左上から順に0からの通し番号を付ける
 p_cnt = 0;
 for( column = 0 ; column < 4 ; column++ )
 {
  for( row = 0 ; row < 4 ; row++ , p_cnt++ )
  {
   //分割したデータを保持するBitmapDataオブジェクトを作成
   //指定のかけらの大きさで、透過なし
   this[ "piece" + p_cnt ] = new BitmapData( piece_w , piece_h , false );

   //コピー開始位置(BitmapData上の座標)とコピーする大きさの設定
   rect.x = row * piece_w;
   rect.y = column * piece_h;
   rect.width = piece_w;
   rect.height = piece_h;

   //指定の位置・大きさの部分を、確保したオブジェクトにコピー
   //コピーデータは左上を基点にして配置する
   this[ "piece" + p_cnt ].copyPixels( org_bmp , rect , copy_point );
  }
 }


 //コピー元のBitmapDataオブジェクトを破棄する
 org_bmp.dispose();



考えどころは、コピー元のコピー開始位置を決める部分だと思います。
このスクリプトでは、for ループを二重にし、内側のループカウンタをX方向、外側のループカウンタをY方向の位置の算出に利用しています。

コピーが済んだら、コピー元の BitmapData オブジェクト(上記のスクリプトでは org_bmp )は不要になります。
BitmapData オブジェクトは大量のメモリを占有するので、用が済んだものは dispose メソッドで破棄しておきましょう。

シンボルの絵を取り込んで分割コピーを作る作業は、普通は1回で充分だと思います。
初期化専用のフレームを作ってスクリプトを書き、2回目以降はこのフレームを再生しないタイムライン構成にすると、何回もビットマップデータを扱う処理をせずに済みます。

*****************************

上記のスクリプトでは、シンボルの絵を取り込んで作った BitmapData オブジェクト” org_bmp ”をコピー元として、16 個のかけらに分割した BitmapData オブジェクト piece0 ~ 15 が作成されます。

piece に続く番号と絵を切り取った位置の関係は

 0 1 2 3
 4 5 6 7
 8 9 10 11
 12 13 14 15

となっています。
例えば piece4 には、左端の列で上から2番目にあたる部分の絵のデータが入っています。


BitmapData オブジェクトはメモリの中に絵のデータがあるだけなので、このままでは何も表示されません。
表示する時は、ムービークリップを用意し、attachBitmap メソッドで表示したい絵のデータを持っている BitmapData オブジェクトを関連付けます。

表示用のムービークリップはスクリプトで空っぽのムービークリップを作ってもいいですし、ステージに配置しておいたムービークリップを使うこともできます。
ここでは、空っぽのムービークリップを作って表示するスクリプトをご紹介します。

先のスクリプトに、次のようなスクリプトを追加してみてください。
スクリプトをメインのタイムラインに書いた時は、ステージの( 100 , 100 )の位置を左上として、もとのシンボルと同じ絵が表示されます。
1枚の絵に見えますが、実際は 16 個のムービークリップでできています。
ですから、ドラッグの処理などを入れると1枚ずつバラバラに動かすことも可能です。


 //分割した絵を、それぞれムービークリップを作成して表示する
 p_cnt = 0;
 for( column = 0 ; column < 4 ; column++ )
 {
  for( row = 0 ; row < 4 ; row++ , p_cnt++ )
  {
   //空のムービークリップを作成する
   clip = this.createEmptyMovieClip( "clip" + p_cnt , p_cnt );

   //位置を決める
   //16枚並べた画像の左上が(100,100)の位置に来るように配置
   clip._x = row * piece_w + 100;
   clip._y = column * piece_h + 100;

   //分割したビットマップを関連付けて表示する
   clip.attachBitmap( this[ "piece" + p_cnt ] , 0 );
  }
 }



他のムービークリップに入れ子になっているムービークリップに表示する時は、BitmapData オブジェクトのターゲットパスにご注意ください。

-------------------------------------------------------------

piece0 ~ 15 は、破棄しなければフレームやシーンを移動してもメモリの中に残っていますから、使いたいフレームにムービークリップを用意し、attachBitmap で関連付けると何度でも再利用できます。


今回は loadBitmap メソッドで、ライブラリにあるシンボルの絵を取り込んでコピー元を作りましたが。
同じく BitmapData クラスの draw というメソッドを使うと、”ムービークリップインスタンス”の絵を BitmapData オブジェクトに取り込むことができます。
loadBitmap メソッドではグラフィックシンボルの絵は取り込めませんが、グラフィックシンボルをムービークリップの中に配置して draw メソッドでコピー元を作成すると、グラフィックシンボルの絵も同様に分割できます。
他にも、外部から読み込んだ JPEG や PNG などの画像を取り込んで分割する・・・という使い方もできそうですね。
機会がありましたら、研究してみてください。
    • good
    • 0
この回答へのお礼

質問をしておきながら全然レスつけずに申し訳ありません。

実務が忙しく試す時間もありませんが、なんとか時間を作ってやってみます。

教えて頂いた事はいずれ他の質問者にフィードバックしますので(汗


せっかく詳しく回答して頂いたのに本当に申し訳ないです。

お礼日時:2007/07/25 01:34

個人的に,おそらくぜんぜん違うものを作成しようとしていて,


ふと,
「たしか『ライブラリ中のグラフィックを、切り分けてMC化する』という質問があったなぁ。」
と思いだしました。
それで遅くなりましたが回答します。

 ライブラリ中にあるグラフィックを、切り分けてMC化する

ではなくて,

 ライブラリ中にあるグラフィックを,先にMC化して切りわける

ではだめでしょうか? 順番を逆にするのです。
BitmapDataクラスのスクリプトでライブラリのビットマップを表示させる以外の部分は全て古典的な手法だとは思いますが。


400×400px のビットマップ画像がライブラリに用意済であるものとし,
ライブラリのビットマップには 「pict」 という識別子を付けている状態で,
_root のフレーム1に "コピペするだけ" で使えるスクリプトです↓。

///////////////////////////////////////////////////////////////
// flash.display.BitmapDataクラスファイルの読み込み
import flash.display.BitmapData;

// bmd を作成し,ライブラリからビットマップpictを割り当てる
bmd = BitmapData.loadBitmap("pict");

for (i=0; i<=3; i++) {
for (j=0; j<=3; j++) {
// ムービークリップpiece00~ piece33を作成
pie = this.createEmptyMovieClip("piece"+i+j, getNextHighestDepth());
// piece00~ piece33内に画像表示用MC pic_mc を作成
pic = pie.createEmptyMovieClip("pic_mc", 0);
// pic_mc に bmd を割り当てる
pic.attachBitmap(bmd, 0);
// piece00~ piece33内にマスク用MC msk_mc を作成
msk = pie.createEmptyMovieClip("msk_mc", 1);
msk._x = i*100;
msk._y = j*100;
msk.beginFill(0x0000FF, 100);
msk.moveTo(0, 0);
msk.lineTo(100, 0);
msk.lineTo(100, 100);
msk.lineTo(0, 100);
msk.lineTo(0, 0);
msk.endFill();
// pic_mc に msk_mc のマスクをかける
pic.setMask(msk);
// piece00~ piece33 をドラッグ可能にする(検証)
pie.onPress = function() {
this.startDrag();
};
pie.onRelease = function() {
this.stopDrag();
};
pie.onReleaseOutside = pie.onRelease;
}
}
///////////////////////////////////////////////////////////////


ライブラリのビットマップをムービークリップの中に呼びだして,
そのムービークリップにマスクをかけただけです。

階層構造は次のようになっています(自動的にそうなるようにスクリプトを書いています)。

 _root
  ├ piece00
  │  ├ msk_mc(マスク)
  │  └ pic_mc(画像)
  ├ piece01
  │  ├ msk_mc(マスク)
  │  └ pic_mc(画像)
  ├ piece02
  │  ├ msk_mc(マスク)
  │  └ pic_mc(画像)
  … 略 …
  └ piece33
     ├ msk_mc(マスク)
     └ pic_mc(画像)

ステージを見た場合のインスタンス名は次のようになっています。

 piece00 piece10 piece20 piece30
 piece01 piece11 piece21 piece31
 piece02 piece12 piece22 piece32
 piece03 piece13 piece23 piece33

基準点はすべて _root の (0,0) です。

ちなみに,
ドラッグで各ピースが動かせますが,
「外部JPEGを動的に変えてジグソーパズルの柄をチェンジするにはどうしたら簡単だろうか?」
というような,個人的別件を考えている途中の回答なので,
検証のためドラッグ&ドロップができるようにしただけです。特に意味はありません。
    • good
    • 0
この回答へのお礼

遅くなりまして申し訳ありません。
DPEさんへのお礼と重複してしまいますが、、

教えて頂いた事はいずれ他の質問者にフィードバックします。


せっかく詳しく回答して頂いたのに本当に申し訳ないです。

お二方ともありがとうございました。

お礼日時:2007/07/25 01:36

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!