Flashゲーム講座 & アクションスクリプトサンプル集



はじめに

 
 


 
「このサイトFlashゲーム講座やのに全然ゲームないやんー(# ゚Д゚)ノ」という事で、Flashゲーム講座らしい物を作ってみました。 初めてゲームを作るときに勉強用としてよく用いられているブロック崩しをこの講座で取り上げました。

このページではFlashの基本的な操作方法を理解している物として解説します。 また、初歩的なプロミング( 配列 や if文 や for文 など)も理解しているものとして話が進みますので、まったくプログラム知識がないという方は参考書などを買って軽く勉強する事をお勧めします。 わからないActionScriptがあったときはFlashのヘルプにあるActionScript 辞書 から調べるのもいいと思います。

このページを読んでいくと下になかなか進めずイライラしてくると思います。しかしここは落ち着いて1週間かけて理解するつもりでじっくりと読み進んでいただきたいと思います。
 
Flashファイルを用意しよう

新規作成でFlaファイルを作成します。
 
ムービープロパティからFlashの設定をします。
Flash5ならメニューから修正→ムービー
MX、MX2004ならプロパティから設定


 
  • ムービーのサイズを幅200 高さ 250 にします。
  • フレームレートを3060の値にします。
  • ムービーのサイズが大きすぎると描画が追いつかず、ゲームの動作が遅くなってしまがちになります。
    フレームレートが低すぎるとコマが飛び、ゲームとしての精度が落ちます。
    フレームレートが高すぎると1フレーム内で処理が仕切れずにゲームの動作が遅くなってしまいがちになります。

     




    バーを動かしてみよう

     

    サンプルをダウンロード
     


     
    バーを作ろう

    ペイントツールを使ってバーを描きます。

     
     
    バーを選択している状態で、情報パネルから幅を40 高さを10にします。

     
    バーを選択ている状態で、F8キーを押してバーをムービークリップにします。

    Flash5なら、メニューから→挿入→シンボルに変換
    MX、MX2004なら、メニューから→修正→シンボルに変換


     
    ムービークリップの中に入って、バーの中心をムービークリップの原点に来るように整列パネルで調整します。

     
    このムービークリップにアクションスクリプトを書いていきましょう。
    左のキーが押されたときに左に移動する、右のキーが押されたときに右に移動するプログラムを書きます。
     
    カーソルキーを押すと左右に移動
    
    onClipEvent (load) {
    
    	_x = 100;	// 初期x位置
    	_y = 230;	// 初期y位置
    	
    }
    onClipEvent (enterFrame) {
    
    	// 左キーを押したとき
    	if (Key.isDown(Key.LEFT)) {
    		_x = _x - 3;	// 左に移動
    	}
    	// 右キーを押したとき
    	if (Key.isDown(Key.RIGHT)) {
    		_x = _x + 3;	// 右に移動
    	}
    	
    }
    
    onClipEvent () {
    }
    ムービークリップにのみ書くことが出来るアクションスクリプトです。 ムービークリップにアクションスクリプトを書くときは、この中に書かないとエラーとなります。 引数に load を指定したときは、ムービークリップが画面に表示されたときに一度だけ実行されます。 引数に enterFrame を指定したときは、毎フレーム実行されます。
    
    Key.isDown()
    
    キーボードが押されているか調べます。押されているなら true が押されていないときは false が返ってきます。 引数にはどのキーかを示す、キーコードを指定します。 Key.LEFT は左カーソルキーのこ定数、 Key.RIGHT は右カーソルキーの定数を表しています。
     
    Flashでは、左上を原点として、右向きにx方向の正、下向きにy方向の正として扱われます。
     
    左カーソルを押すとバーの座標をx方向に -3 ずつ移動します。
     
    右カーソルを押すとバーの座標をx方向に +3 ずつ移動します。
     
    端の補正
     
    ここで移動しすぎるとバーが外に出てしまう事に気がつきます。そこで、横に行き過ぎたときにそれ以上横に移動しないように先ほどのプログラムに追加します。

     
    バーの移動に制限をつける
    
    
    onClipEvent (load) {
    
    	_x = 100;	// 初期x位置
    	_y = 230;	// 初期y位置
    	
    }
    onClipEvent (enterFrame) {
    
    	// 左キーを押したとき
    	if (Key.isDown(Key.LEFT)) {
    		_x = _x - 3;	// 左に移動
    	}
    	// 右キーを押したとき
    	if (Key.isDown(Key.RIGHT)) {
    		_x = _x + 3;	// 右に移動
    	}
    	
    	
    	// バーが右端に来たとき
    	if ( _x < 0 + 20) {
    		_x = 0 + 20;
    	}
    	// バーが左端に来たとき
    	if ( _x > 200 - 20) {
    		_x = 200 - 20;
    	}
    
    }
     
    バーのx座標 _x が20より小さいときに、左に行き過ぎたという事になります。そこでx座標 _x を20の位置に戻します。
     
    バーのx座標 _x が180より大きいときに、右に行き過ぎたという事になります。そこでx座標 _x を180の位置に戻します。
     
     




    玉を動かしてみよう

     

    サンプルをダウンロード
     


     
    玉を作ろう

    ペイントツールを使って玉を描きます。丸のほうが玉らしいですが、ここでは解説しやすくする為に、四角形の玉を作ります。

     
     
    玉を選択している状態にして、情報パネルから幅を10 高さを10にします。

     
    玉を選択ている状態にして、F8キーを押してバーをムービークリップにします。

    Flash5なら、メニューから→挿入→シンボルに変換
    MX、MX2004なら、メニューから→修正→シンボルに変換


     
    ムービークリップの中に入って、バーの中心をムービークリップの原点に来るように整列パネルで調整します。

     
    このムービークリップにアクションスクリプトを書いていきましょう。
    はじめに玉に移動量を与えておいて、その値分毎フレーム座標を移動し続けるプログラムを書きます。

    玉を移動させる
    
    onClipEvent (load) {
    	_x = 100.0;	// 初期位置x
    	_y = 220.0;	// 初期位置y
    
    	dx = 1;		// x移動量
    	dy = -3;		// y移動量
    	
    }
    onClipEvent (enterFrame) {
    
    	// 移動量加算
    	_x = _x + dx;
    	_y = _y + dy;
    	
    }
     
     
    変数 dx は、1フレームごとにx方向に移動する量を表しています。

     
    変数 dy は、1フレームごとにy方向に移動する量を表しています。

     
    端の反射
     
    次に玉が画面の端に来たときに玉が反射するようにアクションスクリプトを追加します。
     
    玉が壁に当たると反射させる
    
    
    onClipEvent (load) {
    	_x = 100.0;	// 初期位置x
    	_y = 220.0;	// 初期位置y
    
    	dx = 1;		// x移動量
    	dy = -3;		// y移動量
    	
    }
    onClipEvent (enterFrame) {
    
    	// 移動量加算
    	_x = _x + dx;
    	_y = _y + dy;
    	
    	// 左端に来たとき
    	if (_x < 0 + 5) {
    		_x = 0 + 5;
    		dx = dx * -1;
    	}
    	
    	// 右端に来たとき
    	if (_x > 200 - 5) {
    		_x = 200 - 5;
    		dx = dx * -1;
    	}
    	
    	// 上端に来たとき
    	if (_y < 0 + 5) {
    		_y = 0 + 5;
    		dy = dy * -1;
    	}
    	
    	// 下端に来たとき
    	if (_y > 250 + 5) {
    		_y = 250 + 5;
    		dy = dy * -1;
    	}
    					
    }
     
    玉のx座標 _x が 5 より小さいときに左端に当たってるということになります。そこでx座標 _x を 5 に戻してからx方向の移動量 dx に -1 を乗算して反転させます。

     
    玉のx座標 _x が 195 より大きいときに右端に当たってるということになります。そこでx座標 _x を 195 に戻してからx方向の移動量 dx に -1 を乗算して反転させます。
     
    玉のy座標 _y が 5 より小さいときに上端に当たってるということになります。そこでy座標 _y を 5 に戻してからy方向の移動量 dy に -1 を乗算して反転させます。

     
    玉のy座標 _y が 245 より大きいときに下端に当たってるということになります。そこでy座標 _y を 245 に戻してからy方向の移動量 dy に -1 を乗算して反転させます。
     
    一番下の当たり判定はゲームでは使用しませんが、見た目に反射を続けているのがわかる為、今だけ付けています。この部分は最後のほうでゲームオーバー判定として使用しますので覚えておいてください。
     
     
     
     
    当たり判定を取ったときに移動量を反転させただけでは、壁にめり込んでジグザグな動きをすることがあります。これは移動量を反転して1フレーム後にまだ壁にめり込んでいると再び壁との当たり判定があり、移動量だけが反転し続け永遠に壁から抜け出せないために起こります。

     
    このようにならないためにも当たり判定があったときは、当たり判定の無い位置まで退避させましょう。
    当たり判定があったとき 当たり判定の無い位置まで補正する
     
     




    バーと玉と当たり判定をつけてみよう

     

    サンプルをダウンロード
     


     
    玉とバーにインスタンス名をつる

    玉とバーにインスタンス名をつけます。

    Flashに配置した玉を選択した状態にしてFlash5ならインスタンスパネルから、MX、MX2004ならプロパティからball と名前をつけます。

    Flash5の場合、メニューから→ウインドウ→パネル→インスタンス
    MX、MX2004の場合、プロパティから設定


    Flash5の場合
     
    FlashMX2004の場合
     
    Flashに配置したバーを選択した状態にして、Flash5ならインスタンスパネルから、MX、MX2004ならプロパティからbar と名前をつけます。

    Flash5の場合
     
    FlashMX2004の場合
     
    当たり判定を取る

    当たり判定を取るアクションスクリプトを追加します。バーと玉のどちらに記述してもいいですが、ここでは玉のムービークリップに記述します。

     
    玉とバーとの当たり判定
    
    
    onClipEvent (load) {
    	_x = 100.0;	// 初期位置x
    	_y = 220.0;	// 初期位置y
    
    	dx = 1;		// x移動量
    	dy = -3;		// y移動量
    	
    }
    onClipEvent (enterFrame) {
    
    	// 移動量加算
    	_x = _x + dx;
    	_y = _y + dy;
    	
    	// 左端に来たとき
    	if (_x < 0 + 5) {
    		_x = 0 + 5;
    		dx = dx * -1;
    	}
    	
    	// 右端に来たとき
    	if (_x > 200 - 5) {
    		_x = 200 - 5;
    		dx = dx * -1;
    	}
    	
    	// 上端に来たとき
    	if (_y < 0 + 5) {
    		_y = 0 + 5;
    		dy = dy * -1;
    	}
    	
    	// 下端に来たとき
    	if (_y > 250 + 5) {
    		_y = 250 + 5;
    		dy = dy * -1;
    	}
    	
    
    	// ボールとバーが当たったとき
    	if (_root.ball.hitTest(_root.bar)) {
    		 _root.ball._y = _root.bar._y - 10;
    	}	
    
    }
    
    ムービークリップのターゲット.hitTest()
    ムービークリップとムービークリップの当たり判定を取ります。重なっているときは true 重なっていないときは false を返します。 先頭に1つ目のムービークリップインスタンスのパスを、引数に2つ目のムービークリップインスタンスのパスを指定します。
     
    hitTest()メソッドを使って当たり判定を取ります。当たり判定があった時に玉ががバーの上に来るように補正します。
     
     
     
    座標で4角形同士の当たり判定を取る方法

    おまけですが、hitTest ()メソッドを使用せずに玉とバーの座標の値だけで4角形同士の当たり判定を取る事ができます。Flash以外のプラットフォームを利用したゲーム開発では通常このようにして当たり判定を取っています。アクションスクリプトではこの部分がメソッドになっている為簡単に当たり判定が取れます。

    座標で当たり判定をとる場合、座標を比べる順番によって処理の効率が変わってきます。ブロック崩しの場合は、 玉は大抵バーのy座標より小さい所で動いている事が多いので下のような順番で判定を取れば、大抵の当たり判定処理を 1 回 if 文を通るだけで終わらせる事ができます。これは 1 回 if 文を通るだけで"確実に当たっていない"という事がわかる為です。
     
    座標を使った玉とバーとの当たり判定
    
    
    onClipEvent (load) {
    	/* 変更なし */
    }
    onClipEvent (enterFrame) {
    	/* 変更なし */
    
    	// ボールとバーが当たったとき
    	if(_root.ball._y + 5 < _root.bar._y - 5){
    	}else if(_root.ball._x + 5 < _root.bar._x - 20){
    	}else if(_root.bar._x + 20 < _root.ball._x - 5){
    	}else if(_root.bar._y + 5 < _root.ball._y - 5){
    	}else {
    		 _root.ball._y = _root.bar._y - 10;
    	}	
    
    }
     
    サンプルをダウンロード
     
     
    玉を反射させる

    玉とバーとの当たり判定を取った部分に以下のアクションスクリプトを追加します。

     
    玉の反射
    
    
    onClipEvent (load) {
    	_x = 100.0;	// 初期位置x
    	_y = 220.0;	// 初期位置y
    
    	dx = 1;		// x移動量
    	dy = -3;		// y移動量
    	
    }
    onClipEvent (enterFrame) {
    
    	// 移動量加算
    	_x = _x + dx;
    	_y = _y + dy;
    	
    	// 左端に来たとき
    	if (_x < 0 + 5) {
    		_x = 0 + 5;
    		dx = dx * -1;
    	}
    	
    	// 右端に来たとき
    	if (_x > 200 - 5) {
    		_x = 200 - 5;
    		dx = dx * -1;
    	}
    	
    	// 上端に来たとき
    	if (_y < 0 + 5) {
    		_y = 0 + 5;
    		dy = dy * -1;
    	}
    	
    	// 下端に来たとき
    	if (_y > 250 + 5) {
    		_y = 250 + 5;
    		dy = dy * -1;
    	}
    	
    
    	// ボールとバーが当たったとき
    	if (_root.ball.hitTest(_root.bar)) {
    		 _root.ball._y = _root.bar._y - 10;
    		 dy *= -1; 
    	}
    		
    }
     
    これで、玉が単純に反射して進みます。しかしこれでは面白くないので、右端に当たったときは右に、 左端に当たったときは左に移動するように改造してみましょう。
     
    サンプルをダウンロード
     
     
    何段階か決める方法

    if文で座標ごとに何段階か区切り、どの方向に移動するか決めます。

     
     
    玉の反射
    
    
    onClipEvent (load) {
    
    	/* 変更なし */
    		
    }
    onClipEvent (enterFrame) {
    
    	/* 変更なし */	
    	
    
    	// ボールとバーが当たったとき
    	if (_root.ball.hitTest(_root.bar)) {
    		_root.ball._y = _root.bar._y - 10;
    		// バーの左端に当たったとき
    		if(_root.bar._x + 20 < _root.ball._x ){
    			dx = 3;
    			dy *= -1;
    		// バーの右端に当たったとき
    		}else if(_root.ball._x + 20 < _root.bar._x){
    			dx = -3;
    			dy *= -1;
    		}else{
    			dy *= -1;
    		}
    	}
    		
    }
     
    サンプルをダウンロード
     
     
    計算で決める方法

    場所によって移動する方向を計算したときの場合です。

     
     
    玉の反射
    
    
    onClipEvent (load) {
    
        /* 変更なし */
    		
    }
    onClipEvent (enterFrame) {
    
        /* 変更なし */	
    	
    
        // ボールとバーが当たったとき
        if (_root.ball.hitTest(_root.bar)) {
            _root.ball._y = _root.bar._y - 10;
            dy *= -1;
            dx = ((_root.ball._x - _root.bar._x) / (20 + 5)) * 2;
        }
    		
    }
     
    サンプルをダウンロード
     
     
    三角関数を使った方法

    三角関数を使って、どの方向にも一定の速さで移動するようにした例です。

     
    玉の反射
    
    
    onClipEvent (load) {
    
        /* 変更なし */
    		
    }
    onClipEvent (enterFrame) {
    
        /* 変更なし */	
    	
    
        // ボールとバーが当たったとき
        if (_root.ball.hitTest(_root.bar)) {
            _root.ball._y = _root.bar._y - 10;
            rad = Math.atan2(_root.ball._y-_root.bar._y,
    _root.ball._x-_root.bar._x); dx = Math.cos(rad)*3; dy = Math.sin(rad)*3; }
    }
     
    サンプルをダウンロード
     
     
     




    ブロックを配置してみよう

     

    サンプルをダウンロード
     


     
    ブロックを作る

    いよいよブロックを作ります。

    ペイントツールを使ってブロックを描きます。

     
     
    ブロックを選択している状態にして、情報パネルから幅を40 高さを15にします。

     
    ブロックを選択ている状態にして、F8キーを押してブロックをムービークリップにします。

    Flash5なら、メニューから→挿入→シンボルに変換
    MX、MX2004なら、メニューから→修正→シンボルに変換


     
    ムービークリップの中に入って、ブロックの中心をムービークリップの原点に来るように整列パネルで調整します。

     
    ブロックを配置する

    ここでは、ブロックをFlash上にあらかじめ配置しておく静的に配置する方法と、ゲームが始まってからアクションスクリプトでブロックを配置する動的に配置する方法の2通りがあります。

    とりあえず難しいのは嫌だという方は先に解説する方法でブロックを配置してください。後に解説する方法は少し難しいですが、無駄が無いため慣れてくるとよく使うテクニックですので ぜひ挑戦してみましょう。
     
    ブロックをあらかじめ配置する

    ブロックをFlash上にあらかじめ配置しておきます。この方法は非常に手間がかかりますが簡単にできます。

    とりあえずブロックのムービークリップをライブラリから何度もドラッグしてきて下のように配置します。

     
    配置し終わったらこのムービークリップにインスタンス名を付けていきます。

    左上から右方向に、block0block1block2…という順番で brock"数値"という名前を付けていきます。

    Flash5の場合、メニューから→ウインドウ→パネル→インスタンス
     
    FlashMX、FlashMX2004の場合
     
    下の図のような順番で31番までインスタンス名を付けていきます。

    数値を付ける時に10より小さい数値を block00, block01, block02 … としないように注意してください。また数値は必ず 0 から 1 ずつ増やして順番に割り当ててください。
     
     
    サンプルをダウンロード
     
     
    ブロックを動的に配置する

    ActionScriptを使ってブロックを配置する方法です。まず、ライブラリにあるブロックのムービークリップにカーソルを合わせて右クリックで リンケージプロパティを選択します。
     
     
     
    ダイアログが開いたら、以下のように設定します。識別子に block と名前を付けます。
     
    Flash5の場合
     
    FlashMX、FlashMX2004の場合
     
    このフレームのタイムラインに以下のアクションスクリプトを記述します。(玉のムービークリップに記述した onClipEvent (load) {} の続きに書いてもかまいません)
     
    玉とバーとの当たり判定
    
    
    for(i=0;i<32;i++){
    	_root.attachMovie( "block", "block"+i, i );
    	eval("_root.block"+i)._x = i % 4 * 40 + 40;
    	eval("_root.block"+i)._y =Math.floor( i / 4 ) * 15 + 25;
    }	
    
    
    
    ムービークリップのターゲット.attachMovie()
    ライブラリにあるリンケージプロパティで名前を付けたムービークリップを flash にコピーします。 1番目の引数にリンケージプロパティで付けた識別子名を指定、 2 番目の引数にflashにコピーしてきたときのインスタンス名、3 番目の引数に 深度を指定します。同じ深度に2つのインスタンスを配置する事はできません。
    
    eval()
    引数内で作った文字で、変数や配列、ムービークリップ、関数などを指定する事ができます。ただしFlashMX以降では、 この関数を利用して変数を作成する事はできません。
    
    数値 % 数値
    割ったときに出るあまりを求めます。例えば 36 % 10 だと 6 が求まります。
    i % 4 の場合 i にランダムな整数値がくるなら、解は 0, 1, 2, 3のどれかになります。
    
    Math.floor()
    引数内の小数点を切り捨て、整数値を返します。
     
    これでムービーを書き出すとブロックが配置されることが確認できます。
     
    サンプルをダウンロード
     
     
     




    玉とブロックと当たり判定をつけてみよう

     

    サンプルをダウンロード
     


     
    ひとつのブロックと当たり判定を取ってみる

    ブロックひとつと玉との当たり判定を取って重なっていれば、そのブロックを消してみます。
    下の図のように先ほど配置したブロックの block0 とインスタンス名をつけたブロックと 玉と当たり判定を取ってみます。
     
     
     
    フラグを作ってブロックの状態管理をする

    変数を作ります。変数の中にはあらかじめ 0 を入れておきます。 ブロックが消えたときに変数を 1 にします。 変数が 1 のときは、ブロックが消えていることがわかるので、当たり判定後の処理を弾きます。
     
     
    玉のムービークリップインスタンスに以下のアクションスクリプトを追加します。
     
    玉とブロック block0 との当たり判定
    
    
    onClipEvent (load) {
    
        /* 変更なし */
    	
        flg = 0;
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    	
        // ボールとバーが当たったとき
    
        /* 変更なし */
    
        // ボールとブロックが当たったとき
        if (_root.ball.hitTest(_root.block0) {
            if(flg == 0){
                // ブロックを非表示に
                _root.block0._visible = false;
                flg = 1;
            }
        }			
    }
    
    
    
    ムービークリップのターゲット._visible
    ムービークリップの可視属性です。trueで表示、falseで非表示になります。
     
     
    これで玉と 0 番目のブロックのが重なったときに 0 番目のブロックが消えます。
     
     
    すべてのブロックと当たり判定を取ってみる

    0 番目のブロックが消せたという事は上で追加した部分を残り 31 回 繰り返せばすべてのブロックと当たり判定が取れるという事になります。
    そこで、下のように数値を変えて記述していくと実現できるわけですが …
     
    玉とすべてのブロックとの当たり判定
    
    
    onClipEvent (load) {
    
        /* 変更なし */
    	
        flg0 = 0;
        flg1 = 0;
        flg2 = 0;
        flg3 = 0;
        flg4 = 0;
        flg5 = 0;
        ・
        ・
        ・
        ・
        ・
        flg30 = 0;
        flg31 = 0;
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    	
        // ボールとバーが当たったとき
    
        /* 変更なし */
    
        // ボールとブロック block0 が当たったとき
        if (_root.ball.hitTest(_root.block0) {
            if(flg0 == 0){
                // ブロックを非表示に
                _root.block0._visible = false;
                flg0 = 1;
            }
    
        }
    				
        // ボールとブロック block1 が当たったとき
        if (_root.ball.hitTest(_root.block1) {
            if(flg1 == 0){
                // ブロックを非表示に
                _root.block1._visible = false;
                flg1 = 1;
            }
    
        }
    				
        // ボールとブロック block2 が当たったとき
        if (_root.ball.hitTest(_root.block2) {
            if(flg2 == 0){
                // ブロックを非表示に
                _root.block2._visible = false;
                flg2 = 1;
            }
    
        }
    				
        // ボールとブロック block3 が当たったとき
        if (_root.ball.hitTest(_root.block3) {
            if(flg3 == 0){
                // ブロックを非表示に
                _root.block3._visible = false;
                flg3 = 1;
            }
    
        }
    
        // ボールとブロック block4 が当たったとき
        if (_root.ball.hitTest(_root.block4) {
            if(flg4 == 0){
                // ブロックを非表示に
                _root.block4._visible = false;
                flg4 = 1;
            }
    
        }
    
    	
            ・
            ・
            ・
            ・
            ・
    
    
        // ボールとブロック block30 が当たったとき
        if (_root.ball.hitTest(_root.block30) {
            if(flg30 == 0){
                // ブロックを非表示に
                _root.block30._visible = false;
                flg30 = 1;
            }
    
        }
    	
        // ボールとブロック block31 が当たったとき
        if (_root.ball.hitTest(_root.block31) {
            if(flg0 == 31){
                // ブロックを非表示に
                _root.block31._visible = false;
                flg31 = 1;
            }
    
        }
    		
    }
    
    
     
    … とこの様に長々と書いていくのはしんどいですね。そこで for 文を使って繰り返し処理ができるようにします。 eval()関数を使って、block0 から 31 まで連続したムービークリップを指定します。
     
    玉とすべてのブロックとの当たり判定
    
    
    onClipEvent (load) {
    
        /* 変更なし */
        
        // ブロックの状態
        flg = new Array();
        for(i=0;i<32;i++){
            flg[i] = 0;
        }
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
            }
        }
    }
    
    
    
    eval()
    引数内で作った文字で、変数や配列、ムービークリップ、関数などを指定する事ができます。ただしFlashMX以降では、 この関数を利用して変数を作成する事はできません。
     
    これなら、ソースもぐっと短くなりますし、ブロックの数を 100 個に増やしたとしても繰り返す回数を変更するだけでいくらでも対応できます。
     
     
    ブロックを当たった時に玉を反射する

    ブロックに当たった時に玉が反射するようにします。 ブロックと玉が角に近い位置に当たったときは、角の向いている方向、それ以外に当たったときは面に対して反射するようにしたいと思います。
     
     
     
    ブロックの左上の角に当たったときの判定

    下のようにブロックの左上近くに当たった時に玉を左上に移動するように玉の移動量を変更します。
     
     
    左上付近に当たったかは、下の2つの条件を満たしたときにわかります。どれだけめり込むかは自分の好みで設定してください。
     
    2つのMCが重なっているときに、

    この条件と

    この条件が2つ同時に満たされているとき
     
    ブロックの左上付近に当たったら玉を左上に移動する
    
    
    onClipEvent (load) {
    
        /* 変更なし */	
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
    
                // ブロックの左上付近に当たったとき
                if (
    _root.ball._x+5 < eval("_root.block"+i)._x-20+4 &&
    _root.ball._y+5 < eval("_root.block"+i)._y-7.5+4
    ) { dx = -3; dy = -3; }
    } } }
     
     
    ブロックの右上の角に当たったときの判定

    下のようにブロックの右上近くに当たった時に玉を右上に移動するように玉の移動量を変更します。
     
     
    右上付近に当たったかは、下の2つの条件を満たしたときにわかります。どれだけめり込むかは自分の好みで設定してください。
     
    2つのMCが重なっているときに、

    この条件と

    この条件が2つ同時に満たされているとき
     
    ブロックの左上付近に当たったら玉を右上に移動する
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */	
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
    
                // ブロックの左上付近に当たったとき
                if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = -3;
    
                // ブロックの右上付近に当たったとき
                } else if (
    eval("_root.block"+i)._x+20-4 < _root.ball._x-5 &&
    _root.ball._y+5 < eval("_root.block"+i)._y-7.5+4
    ) { dx = 3; dy = -3; }
    } } }
     
     
    ブロックの左下の角に当たったときの判定

    下のようにブロックの左下近くに当たった時に玉を左下に移動するように玉の移動量を変更します。
     
     
    左下付近に当たったかは、下の2つの条件を満たしたときにわかります。どれだけめり込むかは自分の好みで設定してください。
     
    2つのMCが重なっているときに、

    この条件と

    この条件が2つ同時に満たされているとき
     
    ブロックの左上付近に当たったら玉を左下に移動する
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */	
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
    
                // ブロックの左上付近に当たったとき
                if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = -3;
    
                // ブロックの右上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = -3;
    
                // ブロックの左下付近に当たったとき
                } else if (
    _root.ball._x+5 < eval("_root.block"+i)._x-20+4 &&
    eval("_root.block"+i)._y+7.5-4 < _root.ball._y-5
    ) { dx = -3; dy = 3; }
    } } }
     
     
    ブロックの右下の角に当たったときの判定

    下のようにブロックの右下近くに当たった時に玉を右下に移動するように玉の移動量を変更します。
     
     
    右下付近に当たったかは、下の2つの条件を満たしたときにわかります。どれだけめり込むかは自分の好みで設定してください。
     
    2つのMCが重なっているときに、

    この条件と

    この条件が2つ同時に満たされているとき
     
    ブロックの右下付近に当たったら玉を右下に移動する
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */	
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
    
                // ブロックの左上付近に当たったとき
                if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = -3;
    
                // ブロックの右上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = -3;
    
                // ブロックの左下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = 3;
    
                // ブロックの右下付近に当たったとき
                } else if (
    eval("_root.block"+i)._x+20-4 < _root.ball._x-5 &&
    eval("_root.block"+i)._y+7.5-4 < _root.ball._y-5
    ) { dx = 3; dy = 3; }
    } } }
     
     
    ブロックの上側に当たったときの判定

    下のようにブロックの上側に当たった時に玉をy方向に反射するようにします。
     
     
    右下付近に当たったかは、下の条件を満たしたときにわかります。どれだけめり込むかは自分の好みで設定してください。
     
    2つのMCが重なっているときに、

    この条件が満たされているとき
     
    ブロックの上側付近に当たったら玉を上に反射する
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */	
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
    
                // ブロックの左上付近に当たったとき
                if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = -3;
    
                // ブロックの右上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = -3;
    
                // ブロックの左下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = 3;
    
                // ブロックの右下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = 3;
    
    
                // ブロックの上付近に当たったとき
                } else if (_root.ball._y+5 < 
    eval("_root.block"+i)._y-7.5+4) { dy = -3; }
    } } }
     
     
    ブロックの下側に当たったときの判定

    下のようにブロックの下側に当たった時に玉をy方向に反射するようにします。
     
     
    下側付近に当たったかは、下の条件を満たしたときにわかります。どれだけめり込むかは自分の好みで設定してください。
     
    2つのMCが重なっているときに、

    この条件が満たされているとき
     
    ブロックの下側付近に当たったら玉を下に反射する
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */	
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
    
                // ブロックの左上付近に当たったとき
                if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = -3;
    
                // ブロックの右上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = -3;
    
                // ブロックの左下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = 3;
    
                // ブロックの右下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = 3;
    
                // ブロックの上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dy = -3;
    
    
                // ブロックの下付近に当たったとき
                } else if (eval("_root.block"+i)._y+7.5-4 < 
    _root.ball._y-5) { dy = 3; }
    } } }
     
     
    ブロックの左側に当たったときの判定

    下のようにブロックの左側に当たった時に玉をx方向に反射するようにします。
     
     
    左側付近に当たったかは、下の条件を満たしたときにわかります。どれだけめり込むかは自分の好みで設定してください。
     
    2つのMCが重なっているときに、

    この条件が満たされているとき
     
    ブロックの左側付近に当たったら玉を左に反射する
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */	
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
    
                // ブロックの左上付近に当たったとき
                if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = -3;
    
                // ブロックの右上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = -3;
    
                // ブロックの左下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = 3;
    
                // ブロックの右下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = 3;
    
                // ブロックの上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dy = -3;
    
                // ブロックの下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dy = 3;
    		
    
                // ブロックの左付近に当たったとき
                } else if (_root.ball._x+5 < 
    eval("_root.block"+i)._x-7.5+4) { dx = -3; }
    } } }
     
     
    ブロックの右側に当たったときの判定

    下のようにブロックの右側に当たった時に玉をx方向に反射するようにします。
     
     
    右下付近に当たったかは、下の条件を満たしたときにわかります。どれだけめり込むかは自分の好みで設定してください。
     
    2つのMCが重なっているときに、

    この条件が満たされているとき
     
    ブロックの右側付近に当たったら玉を右に反射する
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */	
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    
        // 32個のブロックをfor文で処理する
        for (i=0; i<32; i++) {
            if(flg[i] == 1)	continue;		// 次のループへ
    
            // ボールとブロック block i 番目 が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i))) {
    
                flg[i] = 1;	// 消えた事をあらわすフラグ
    
                // ブロックを非表示に
                eval("_root.block"+i)._visible = false;
    
                // ブロックの左上付近に当たったとき
                if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = -3;
    
                // ブロックの右上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = -3;
    
                // ブロックの左下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = -3;
                    dy = 3;
    
                // ブロックの右下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = 3;
                    dy = 3;
    
                // ブロックの上付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dy = -3;
    
                // ブロックの下付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dy = 3;
    
                // ブロックの左付近に当たったとき
                } else if ( /*   変更なし   */ ) {
                    dx = -3;
    
                // ブロックの右付近に当たったとき
                } else if (eval("_root.block"+i)._y+7.5-4 < 
    _root.ball._x-5) { dx = 3; }
    } } }
     
     
     




    ゲームオーバーを付けてみよう

     

    サンプルをダウンロード
     


     
     
    ゲームオーバーを判定する

    さて、玉が反射するようになりブロック崩しのメイン部分は出来ました。後はゲームクリアとゲームオーバーを付けるだけです。
    ブロック崩しでゲームオーバーになるには玉が一番下まできたときです。ですから、玉が一番下の座標にきたかをチェックしましょう。
     
    座標でチェックする

    このFlashの画面は幅200*高さ250ですから、玉がy座標の240より大きい値になったときに玉が底についたと言えます。
     
     
     
    玉 が一番下に付いたかチェック
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */
    
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    	
        // ボールとバーが当たったとき
    
        /* 変更なし */
    
        // 移動量加算
        _x = _x + dx;
        _y = _y + dy;
    	
        // 左端に来たとき
        if (_x < 0 + 5) {
            _x = 0 + 5;
            dx = dx * -1;
        }
    	
        // 右端に来たとき
        if (_x > 200 - 5) {
            _x = 200 - 5;
            dx = dx * -1;
        }
    
        // 上端に来たとき
        if (_y < 0 + 5) {
            _y = 0 + 5;
            dy = dy * -1;
        }
    
        // 下端に来たとき(ゲームオーバー)
        if (_y > 250 + 5) {
            _root.gotoAndStop("2");
        }
        
        
        for(i=0;i<32;i++){
            // ボールとブロック が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i)) {
    
                // ブロックを非表示に
    
                /* 変更なし */
    
                // 玉を反射する
    
                /* 変更なし */
    
           }
        }
    
    }
    
    
     
    ゲームオーバー画面を別のタイムラインに作ってそこへ、gotoAndPlay()を使って移動するとゲームオーバー画面に移動できます。

     
    ブロックを動的に配置した場合は、タイムラインが移動してもムービークリップが画面に残ったままになるのでゲームオーバー画面に移動する前にブロックを削除する必要があります。
     
    玉 が一番下に付いたかチェック
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */
    
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    	
        // ボールとバーが当たったとき
    
        /* 変更なし */
    
        // 移動量加算
        _x = _x + dx;
        _y = _y + dy;
    	
        // 左端に来たとき
        if (_x < 0 + 5) {
            _x = 0 + 5;
            dx = dx * -1;
        }
    	
        // 右端に来たとき
        if (_x > 200 - 5) {
            _x = 200 - 5;
            dx = dx * -1;
        }
    
        // 上端に来たとき
        if (_y < 0 + 5) {
            _y = 0 + 5;
            dy = dy * -1;
        }
    
        // 下端に来たとき(ゲームオーバー)
        if (_y > 250 + 5) {
    
            // ブロックを破棄
            for(i=0;i<32;i++){
                eval("_root.block"+i).removeMovieClip ( );
            }
            _root.gotoAndStop("2");
        }
        
        
        for(i=0;i<32;i++){
            // ボールとブロック が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i)) {
    
                // ブロックを非表示に
    
                /* 変更なし */
    
                // 玉を反射する
    
                /* 変更なし */
    
           }
        }
    
    }
    
     
    
    ムービークリップのパス.removeMovieClip ();
    
    Flash画面上にあるムービークリップを削除できます。ただし、深度が 0 より小さい ムービークリップ は削除することができません。
     
     
    次にゲームをクリアしているかを調べます。
     
     




    ブロックが全部消えたかチェックしよう

     

    サンプルをダウンロード
     


     
    ブロックが全部消えたか調べる

    次はゲームクリアの部分を作ります。
    ブロック崩しでゲームクリアになるにはすべてのブロックを消すことが出来たときです。それではどのようにして、ブロックが消えたと判定するのでしょうか?
     
    一番下のループで配列の中身を順番に見ていきます。配列の中に1つでも 1 があったときは、break が呼ばれ、for文がその場で中断されますすべての配列の中に 1 が無かったときは、for文 をすべて回るので変数 i には 32 が入っています。 i に 32 が入っているとブロックがすべて消えたことがわかります。

    別のタイムラインにゲームクリア画面を作っておいてgotoAndPlay()で移動するとゲームクリアとなります。
     
    ブロック がすべて消えたかチェック
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */
    	
        // 32個の配列を作り 0 を入れておく
        flg = new Array();
        for(i=0 ; i<32 ; i++){
    	
            flg[i] = 0;
    	
        }
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    	
        // ボールとバーが当たったとき
    
        /* 変更なし */
    
        for(i=0;i<32;i++){
            // ボールとブロック が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i)) {
    
                // ブロックを非表示に
    
                /* 変更なし */
    
                // 玉を反射する
    
                /* 変更なし */
    
                // 当たり判定のあった番号と同じ配列の番号を0にする
                flg[i] = 1;
            }
        }
    
        // 配列をチェック
        for(i=0 ; i<32 ; i++){
            // 0 があればループ終了
            if(flg[i] == 0){
                break;	// forループ終了	
            }	
        }
    	
        // 最後までループが回った時(0が無かった)
        if(i == 32){
            /* ゲームクリア画面へ移動 */
        }			
    }
    
     
     




    スコアをつけてみよう

     

    サンプルをダウンロード
     


     
    スコアをつける

    スコアを作ります。
    変数 score を作ってはじめに 0 を入れておきます。ブロックと玉が当たったときに score に好きな値を加算していくとスコアをためていくことができます。
     
     
    スコアをつける
    
    
    // ブロック配置
    onClipEvent (load) {
    
        /* 変更なし */
    	
        // 32個の配列を作り 0 を入れておく
     
        /* 変更なし */
    
        // スコアを 0 にする
        _root.score = 0;
    }
    
    
    onClipEvent (enterFrame) {
    
        /* 変更なし */
    	
        // ボールとバーが当たったとき
    
        /* 変更なし */
    
        for(i=0;i<32;i++){
            // ボールとブロック が当たったとき
            if (_root.ball.hitTest(eval("_root.block"+i)) {
    
                // ブロックを非表示に
    
                /* 変更なし */
    
                // 玉を反射する
    
                /* 変更なし */
    
                // 当たり判定のあった番号と同じ配列の番号を 1 にする
    
                /* 変更なし */
    	    
    	    // スコアを加算する
    	    _root.soore = _root.score + 100;
    	    
           }
        }
    	
        // 配列をチェック
    
        /* 変更なし */
    	
        // 最後までループが回った時
     
        /* 変更なし */
    			
    }