速習Webデザイン ActionScript3.0を読む その6

速習Webデザイン ActionScript 3.0

速習Webデザイン ActionScript 3.0

part6 表示オブジェクトのコントロール:応用

  • 01-01 埋め込みアセットクラス
    • ライブラリのデータは「埋め込みアセットクラス」として設定することでスクリプトから指定できるようになる。
    • リンケージプロパティで「ActionScriptに書き出し」にチェックを入れる。
  • 01-02
    • アセットクラス化したMCのインスタンスを表示させるには二つのプロセス。
    1. インスタンスを生成
    2. インスタンスを表示リストに追加
    • 書式は以下。
  • 生成

var 変数 :データ型 = new 埋め込みアセットクラス名() ;

  • 表示

表示オブジェクトコンテナ.addChild(インスタンス) ;

  • 削除

表示オブジェクトコンテナ.removeChild(インスタンス) ;

    • removeした後もメモリ上にインスタンスは残っているのでさらにaddChild()で表示できる。
    • メモリ上からも削除する場合は変数にnullを代入する。
    • クラス名を文字列で指定できると繰り返し処理が使えるので便利。
    • そのためのメソッドが「getDefinitionByName()」メソッド。
    • これ使う課題とかあるんじゃなかろか。
  • Let'TRY!!
    • ボタンクリックのたびにアセットクラスCharacterのインスタンスをステージに追加させる。インスタンスはランダムな位置にランダムなサイズで。インスタンスはランダムな移動をし、ステージ枠に当たったら跳ね返る。
    • なんか難しそう−。
    • とりあえず段階踏んで作ってみようとAddボタン押したらランダムな位置に表示させてみた。

var NewCharacter:MovieClip = new Character();

add_btn.addEventListener(MouseEvent.CLICK,xAddClick);

  function xAddClick(evt:MouseEvent):void{
    addChild(NewCharacter);
    NewCharacter.x = Math.floor(Math.random()*501)+50;
    NewCharacter.y = Math.floor(Math.random()*351)+50;
  }

try_06-01_00.fla

    • ちゃんと動いたけど、ボタンクリックの度に古いのが消えて新しいのが生成される。つまり「クリックのたびに」増えていかない。(15時30分)
    • 参考用の完成SWFファイルではクリックごとに増えていった。。。
    • もしかして個数用の変数を置いて、文字列でアセットクラスを指定しろっていうことなのかなー。
    • とか考えて試してみたけど、よく考えたらリンケージ貼ってるのはそもそも「character」一個だけだからその必要なし。
    • とりあえずいっぱい出すの難しいからランダム移動と跳ね返りを実装してみる。
    • まずはランダム移動。

var NewCharacter:MovieClip = new Character();

add_btn.addEventListener(MouseEvent.CLICK,xAddClick);

  function xAddClick(evt:MouseEvent):void{
    NewCharacter.x = Math.floor(Math.random()*501)+50;
    NewCharacter.y = Math.floor(Math.random()*351)+50;
    addChild(NewCharacter);
    NewCharacter.addEventListener(Event.ENTER_FRAME,xMove);
  }

  function xMove(evt):void{
    var xStep:int =Math.floor(Math.random()*10)-5;
    var yStep:int =Math.floor(Math.random()*10)-5;
    NewCharacter.x += xStep;
    NewCharacter.y += yStep;
  }

try_06-01_01.fla

    • これだと毎フレームで方向もステップも決めてることになるので、時々方向とステップを変えてそれ以外はそのままで進むようにしてみる。(16時13分)

var NewCharacter:MovieClip = new Character();
const Ini_STEP = 10;

add_btn.addEventListener(MouseEvent.CLICK,xAddClick);

  function xAddClick(evt:MouseEvent):void{
    NewCharacter.x = Math.floor(Math.random()*501)+50;
NewCharacter.y = Math.floor(Math.random()*351)+50;
addChild(NewCharacter);
xMove();
  }

  function xMove():void{
    var xStep:int =Math.floor(Math.random()*Ini_STEP)-Math.floor(Ini_STEP/2);
    var yStep:int =Math.floor(Math.random()*Ini_STEP)-Math.floor(Ini_STEP/2);
    trace(xStep, yStep);
      for(var i:uint=0;i<10000;i++){
        trace(i);
        NewCharacter.x += xStep;
        NewCharacter.y += yStep;
        if(NewCharacter.x <0 || NewCharacter.x >550){
          xStep *= -1;
        }
        if(NewCharacter.y <0 || NewCharacter.y >400){
          yStep *= -1;
        }
      }
}

try_06-01_02.fla

    • EnterFrame使わないとアニメーションにならず(´Д⊂
    • 難しいなー。。。。(16時46分)

NewCharacter.addEventListener(Event.ENTER_FRAME,xMove(xStep,yStep));
}

function xMove(xx:int,yy:int){
NewCharacter.x += xx;
NewCharacter.y += yy;
if(NewCharacter.x <0 || NewCharacter.x >550){
xx *= -1;
}
if(NewCharacter.y <0 || NewCharacter.y >400){
yy *= -1;
}
}

    • イベントハンドラに引数渡すことって出来ないのかな−。これだとエラーになる。。。(17時07分)
    • ちょっと考えてxStep、yStepをグローバル関数にすることで解決。

var NewCharacter:MovieClip = new Character();
const Ini_STEP = 10;
var xStep:int =0;
var yStep:int =0;

add_btn.addEventListener(MouseEvent.CLICK,xAddClick);

  function xAddClick(evt:MouseEvent):void{
    NewCharacter.x = Math.floor(Math.random()*501)+50;
    NewCharacter.y = Math.floor(Math.random()*351)+50;
    addChild(NewCharacter);
    xStep = Math.floor(Math.random()*Ini_STEP)-Math.floor(Ini_STEP/2);
    yStep = Math.floor(Math.random()*Ini_STEP)-Math.floor(Ini_STEP/2);
    NewCharacter.addEventListener(Event.ENTER_FRAME,xMove);
  }

  function xMove(evt:Event){
    NewCharacter.x += xStep;
    NewCharacter.y += yStep;
    
    
    if(NewCharacter.x <0 || NewCharacter.x >550){
      xStep *= -1;
    }
    if(NewCharacter.y <0 || NewCharacter.y >400){
      yStep *= -1;
    }
  }

try_06-01_03.fla

    • ランダム移動と跳ね返りが実装できた。(17時23分)
    • あとはクリックの度に増やしていく方法。うーん。
    • とりあえず18時まで考えて分からなかったらお手本参照してみよう。

var NewCharacter:Array = new Array();
var i :uint=0;
const Ini_STEP = 10;
var xStep:Array = new Array();
var yStep:Array = new Array();

add_btn.addEventListener(MouseEvent.CLICK,xAddClick);

  function xAddClick(evt:MouseEvent):void{
    NewCharacter[i] = new Character();
    NewCharacter[i].x = Math.floor(Math.random()*501)+50;
    NewCharacter[i].y = Math.floor(Math.random()*351)+50;
    addChild(NewCharacter[i]);
    xStep[i] = Math.floor(Math.random()*Ini_STEP)-Math.floor(Ini_STEP/2);
    yStep[i] = Math.floor(Math.random()*Ini_STEP)-Math.floor(Ini_STEP/2);
    NewCharacter[i].addEventListener(Event.ENTER_FRAME,xMove);
    i++;
}

    • 配列を使ってインスタンスを増やすことに成功。(17時52分)
    • でもxMoveをどうすればいいか分からず。複数のインスタンスを別々にどう動かすか。
    • うーん、なんとなく見えてる気がするんだけど。最後に増やすって遠回りしたのかなー。
    • そして目標時間ちょいオーバーだけど何とか出来た!!!!
    • xStepの代入式勘違いしてて書き直す。最後が「(Ini_STEP/2)」ではなく「(Ini_STEP*2)」。それにともない初期値のIni_STEPも10から5にした。

var NewCharacter:Array = new Array();
var i :uint=0;
const Ini_STEP = 5;
var xStep:Array = new Array();
var yStep:Array = new Array();

add_btn.addEventListener(MouseEvent.CLICK,xAddClick);

  function xAddClick(evt:MouseEvent):void{
    NewCharacter[i] = new Character();
    NewCharacter[i].x = Math.floor(Math.random()*501)+50;
    NewCharacter[i].y = Math.floor(Math.random()*351)+50;
    addChild(NewCharacter[i]);
    xStep[i] = Math.floor(Math.random()*Ini_STEP)-Math.floor(Ini_STEP*2);
    yStep[i] = Math.floor(Math.random()*Ini_STEP)-Math.floor(Ini_STEP*2);
    NewCharacter[i].addEventListener(Event.ENTER_FRAME,xMove);
    i++;
  }

  function xMove(evt:Event){
    for(var j:uint=0; j< NewCharacter.length ; j++){
      NewCharacter[j].x += xStep[j];
      NewCharacter[j].y += yStep[j];
        if(NewCharacter[j].x <0 || NewCharacter[j].x >550){
          xStep[j] *= -1;
        }
        if(NewCharacter[j].y <0 || NewCharacter[j].y >400){
          yStep[j] *= -1;
        }
    }
}

try_06-01_04.fla

    • 実はイマイチ納得できてなくて無理矢理動いてる気がする。EnterFrameの処理がもっと上手なやり方がありそう。
    • そしてサイズがランダムになってないことに気づいた。今から実装。
    • 以下を付け足す。(18時30分)

NewCharacter[i].scaleX = NewCharacter[i].scaleY = Math.random()*2+0.5;

    • 無事動く。
    • ただお手本は壁に当たらずとも途中で早さや向きが変わっていた気がする。
    • あと、壁に当たったかの判定はそれ用の関数にすべきかも。
    • rotationプロパティを使って壁に当たる度に角度が変わるようにするのもありかも。
  • お手本見たらたら全然違うぞー!!!
    • まず配列なんか使ってないし。。。どーゆーことやぁぁぁぁぁ!!!
    • お手本のキモはここですね。

function charaEnterFrame(evt:Event):void {
  var chara:MovieClip = evt.target as MovieClip;

    • イベントリスナー変数「evt」に「.target」とasによる型変換で「chara」に代入ね。なるー。
    • つーか一番ビックリしたのがコレ↓

var newChara:MovieClip = new Character();
  newChara.speedX = xGetSpeed();

    • これって勝手に「speedX」っていうプロパティ作ってませんか?こんなことできるんだっけ?
    • もとのアセットクラスにカスタムプロパティってことかな?
    • それからそもそも、複数のインスタンスが生成できなかったのはリスナー関数の中で生成しなかったからかな。
    • お手本ではクリック用イベントハンドラの中で生成してる。
    • そんなわけで「try_06-01_00.fla」を書き換えてみる。

add_btn.addEventListener(MouseEvent.CLICK,xAddClick);

  function xAddClick(evt:MouseEvent):void{
    var NewCharacter:MovieClip = new Character();
    addChild(NewCharacter);
    NewCharacter.x = Math.floor(Math.random()*501)+50;
    NewCharacter.y = Math.floor(Math.random()*351)+50;
}

try_06-01_00re00.fla

    • うわー、ばっちりうまくいったー。。。。
    • 生成する場所変えるだけ、一行場所変えるだけだったのか−。。。。。
    • 勉強になりましたっっっっっっっっ(ロ_ロ)ゞ