静岡理工科大学 菅沼ホーム ActionScript目次 索引

アニメーションとゲーム

      1. アニメーション
        1. 円の描画
        2. ランニング(外部複数画像の利用)
        3. ボールの運動(描画とイベント処理)
        4. ボールの運動(外部単一画像の利用とイベント処理)
        5. 花火
        6. Web ページ
      2. ゲーム
        1. シューティングゲーム
        2. ぷよぷよ(テトリス)

  1. アニメーション

      ここでは,「 Java で作成したアニメーション」とほぼ同じものを ActionScript で作成し,その違いを見てみたいと思います.

    1. 円の描画

        「 Java の場合」と同様に,半径の異なる円を描くことによってアニメーションを作成してみます.ボタンをクリックしたときのイベント処理に対して,リスナーとイベントハンドラーを使用する点は,形式は異なりますが,Java と非常に似ています.

        ただし,円や直線を描くグラフィックスの部分で大きく異なります.Java においては,先に示した例のように,定期的に,表示する半径が異なるすべての円を描き直しています.しかし,ActionScript では,ある特定の半径の円を描くだけです.つまり,ActionScript においては,グラフィックスは Sprite オブジェクトや Shape オブジェクトに描いた模様のようなものであり,意図的に消さない限り( clear() メソッド),一度描いたものが消えることはありません.このため,グラフィックス自身が一つの表示オブジェクトのように取り扱われます.

      Circle.as

      01	package {
      02		import flash.display.Sprite;
      03		import flash.display.Shape;
      04		import flash.events.Event;
      05		import flash.events.MouseEvent;
      06	
      07		[SWF(backgroundColor="0xe1ffe1", width="400", height="250", frameRate="10")]
      08	
      09		public class Circle extends Sprite {
      10			private var start : sButton;
      11			private var stop : sButton;
      12			private var rec : Sprite;
      13			private var line : Shape;
      14			private var count : int = 0;
      15			private var sw : Boolean = false;
      16			private var r : Number = 10;
      17	
      18			public function Circle() {
      19				init()
      20			}
      21	
      22			private function init():void {
      23				start = new sButton("開始", 20);
      24				start.x = 110;
      25				start.y = 10;
      26				start.name = "start";
      27				addChild(start);
      28				stop = new sButton("停止", 20);
      29				stop.x = 210;
      30				stop.y = 10;
      31				stop.name = "stop";
      32				addChild(stop);
      33	
      34				rec = new Sprite();
      35				rec.graphics.beginFill(0x00ffffff);
      36				rec.graphics.drawRect(10, 55, 380, 180);
      37				rec.graphics.endFill();
      38				addChild(rec);
      39	
      40				line = new Shape();
      41				rec.addChild(line);
      42				addEventListener(Event.ENTER_FRAME, onEnterFrame);
      43				start.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      44				stop.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      45			}
      46	
      47			private function onEnterFrame(event:Event):void {
      48				if (sw) {
      49					count++;
      50					line.graphics.lineStyle(1);
      51					line.graphics.drawCircle(10+r, 55+r, r);
      52					r = 1.5 * r;
      53					if (count > 10) {
      54						line.graphics.clear();
      55						count = 0;
      56						r     = 10;
      57					}
      58				}
      59			}
      60	
      61			private function onMouseDown(event:MouseEvent):void {
      62				if (sw) {
      63					if (event.target.name == "stop")
      64						sw = false;
      65				}
      66				else {
      67					if (event.target.name == "start")
      68						sw = true;
      69				}
      70			}
      71		}
      72	}
      				
      23 行目~ 32 行目

        「開始」及び「停止」ボタンを追加している.

      34 行目~ 38 行目

        描画領域として,白い矩形を描いた Sprite クラスのオブジェクト rec を追加している.

      40 行目~ 41 行目

        実際に円を描く Shape クラスのオブジェクト line を,rec に追加している.

      42 行目

        Event クラスの ENTER_FRAME に対応するため,イベントリスナを追加している.この結果,07 行目に指定された通り,100 ms 毎に onEnterFrame メソッドが実行される.

      43 行目~ 44 行目

        「開始」及び「停止」ボタンが押されたときに発生するイベントに対応するため,イベントリスナを追加している.この結果,これらのボタンが押されると,onMouseDown メソッドが実行される.

      47 行目~ 59 行目

        ENTER_FRAME イベントに対応する処理である.変数 sw が true の場合,Shape クラスのオブジェクト line 上に,指定された半径の円を描いている.ただし,count の値が 10 より大きくなった場合は,描いた図形をクリアし,変数 count や r の値を初期状態に戻している.

      61 行目~ 70 行目

        ボタンが押されたときの処理である.押されたボタンにより,変数 sw の値を true または false に設定している.

    2. ランニング(外部複数画像の利用)

        ランニングでは,「 Java の場合」と同様,複数の画像を異なる位置に表示することによってアニメーションを作成しています.

      Run.as

      001	package {
      002		import flash.display.Sprite;
      003		import flash.display.Loader;
      004		import flash.net.URLRequest;
      005		import flash.events.Event;
      006	
      007		[SWF(backgroundColor="0xffffff", width="600", height="400", frameRate="10")]
      008	
      009		public class Run extends Sprite {
      010			private var a : Array = new Array();
      011			private var now_id : int = 0;
      012			private var ko : int = -1;
      013	
      014			public function Run() {
      015				a[0] = new Loader();
      016				a[0].load(new URLRequest("fig0.gif"));
      017				a[1] = new Loader();
      018				a[1].load(new URLRequest("fig1.gif"));
      019				a[2] = new Loader();
      020				a[2].load(new URLRequest("fig2.gif"));
      021				a[3] = new Loader();
      022				a[3].load(new URLRequest("fig3.gif"));
      023				a[4] = new Loader();
      024				a[4].load(new URLRequest("fig4.gif"));
      025				a[5] = new Loader();
      026				a[5].load(new URLRequest("fig5.gif"));
      027				addEventListener(Event.ENTER_FRAME, onEnterFrame);
      028			}
      029	
      030			private function onEnterFrame(event:Event):void {
      031				var x : int;
      032				var y : int;
      033				var k : int = now_id % 6;
      034				if (now_id == 0) {
      035					x = -20;
      036					y = 200 - 238 / 2;
      037				}
      038				else if (now_id == 1) {
      039					x = 5;
      040					y = 200 - 249 / 2;
      041				}
      042				else if (now_id == 2) {
      043					x = 70;
      044					y = 200 - 258 / 2;
      045				}
      046				else if (now_id == 3) {
      047					x = 140;
      048					y = 200 - 258 / 2;
      049				}
      050				else if (now_id == 4) {
      051					x = 150;
      052					y = 200 - 258 / 2;
      053				}
      054				else if (now_id == 5) {
      055					x = 160;
      056					y = 200 - 247 / 2;
      057				}
      058				else if (now_id == 6) {
      059					x = 200;
      060					y = 200 - 238 / 2;
      061				}
      062				else if (now_id == 7) {
      063					x = 225;
      064					y = 200 - 249 / 2;
      065				}
      066				else if (now_id == 8) {
      067					x = 290;
      068					y = 200 - 258 / 2;
      069				}
      070				else if (now_id == 9) {
      071					x = 360;
      072					y = 200 - 258 / 2;
      073				}
      074				else if (now_id == 10) {
      075					x = 370;
      076					y = 200 - 258 / 2;
      077				}
      078				else if (now_id == 11) {
      079					x = 380;
      080					y = 200 - 247 / 2;
      081				}
      082				else if (now_id == 12) {
      083					x = 420;
      084					y = 200 - 238 / 2;
      085				}
      086				else if (now_id == 13) {
      087					x = 445;
      088					y = 200 - 249 / 2;
      089				}
      090				else if (now_id == 14) {
      091					x = 510;
      092					y = 200 - 258 / 2;
      093				}
      094				else if (now_id == 15) {
      095					x = 580;
      096					y = 200 - 258 / 2;
      097				}
      098				else if (now_id == 16) {
      099					x = 590;
      100					y = 200 - 258 / 2;
      101				}
      102				else {
      103					x = 600;
      104					y = 200 - 247 / 2;
      105				}
      106				a[k].x = x;
      107				a[k].y = y;
      108				if (ko >= 0)
      109					removeChild(a[ko]);
      110				addChild(a[k]);
      111				ko = k;
      112				now_id++;
      113				if (now_id > 17)
      114					now_id = 0;
      115			}
      116		}
      117	}
      				
      015 行目~ 026 行目

        Loader クラス,及び,URLRequest クラスを利用して,配列 a に,6 つの画像を読み込んでいる.配列 a は,10 行目において,Array クラスを使用して定義している.

      031 行目~ 107 行目

        今描画すべき画像( a[k] )の描画位置を設定している.6 つの画像を 3 回繰り返し,左端から右端までの移動を実現させている.

      108 行目~ 109 行目

        一つ前に描画した画像を削除している.

      112 行目~ 114 行目

        6 つの画像を 3 回繰り返した場合(右端に到達),最初の画像に戻し左端から移動を開始するように設定している.

    3. ボールの運動(描画とイベント処理)

        ボールの落下は,「 Java の場合」と同様,ボールを描き,それを一定時間毎に異なる位置に表示することによってアニメーションを作成しています.ボールをクッリクすると停止し,もう一度クリックすると再び動き出します.

      Ball.as

      01	package {
      02		import flash.display.Sprite;
      03		import flash.events.Event;
      04		import flash.events.MouseEvent;
      05	
      06		[SWF(backgroundColor="0xeeffee", width="600", height="400", frameRate="30")]
      07	
      08		public class Ball extends Sprite {
      09			private var ball : Sprite;
      10			private var g : Number = 9.8;   // y 軸方向の加速度
      11			private var v0 : Number = 0;   // y 軸方向の初期速度
      12			private var v : Number = 0;   // y 軸方向の現在速度
      13			private var t : Number = 0;   // 時間の初期値
      14			private var h0 : Number = stage.stageHeight;   // ボールの初期位置の y 座標(上が正,初期高さ)
      15			private var sw : Number = 1;   // ボールの状態( 0:停止している,1:動いている)
      16	
      17			public function Ball() {
      18				init();
      19			}
      20	
      21			private function init():void {
      22				ball = new Sprite();
      23				addChild(ball);
      24				ball.graphics.beginFill(0x00ff00);
      25				ball.graphics.drawCircle(0, 0, 40);
      26				ball.graphics.endFill();
      27				ball.x = 0;
      28				ball.y = 0;
      29				addEventListener(Event.ENTER_FRAME, onEnterFrame);
      30				ball.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      31			}
      32	
      33			private function onEnterFrame(event:Event):void {
      34				if (ball.x < stage.stageWidth + 40 && sw > 0) {
      35					ball.x += 1.5;
      36					t      += 0.1;
      37					v       = -g * t + v0;
      38					ball.y  = stage.stageHeight - (-0.5 * g * t * t + v0 * t + h0);
      39					if (ball.y >= stage.stageHeight - 40 && v < 0) {
      40						ball.y = stage.stageHeight - 40;
      41						v0     = -0.8 * v;
      42						h0     = 40;
      43						t      = 0;
      44					}
      45					trace("position", ball.x, ball.y);
      46				}
      47			}
      48	
      49			private function onMouseDown(event:MouseEvent):void {
      50				if (sw == 0)
      51					sw = 1;
      52				else
      53					sw = 0;
      54			}
      55		}
      56	}
      				
      22 行目~ 28 行目

        緑の円を描いた Sprite クラスのオブジェクト ball を追加している.

      34 行目~ 40 行目

        ボールが動いており( sw > 0 ),かつ,画面内に存在したときの処理である.
      • 35 行目: ボールの x 座標の変更( 1.5 ピクセル / 33 ms )
      • 36 行目: 時間の変更( 0.1 秒 / 33 ms )
      • 37 行目: ボールの速度の変更
      • 38 行目: ボールの y 座標の変更.画面座標に合うように座標変換も行っている.
      • 39 行目~ 44 行目: ボールが地面に落ちたときの跳ね返り処理を行っている.その際,速度が 0.8 倍される.
      • 45 行目: ボールの位置を trace メソッドで出力している(何も表示されない).

      49 行目~ 54 行目

        ボールの上でマウスボタンを押すと実行されるメソッドである.ボールが動いている場合は停止,停止している場合は再び動かす.

    4. ボールの運動(外部単一画像の利用とイベント処理)

        ボールの落下は,「 Java の場合」と同様,ボールの画像( ball.gif )を読み込み,その画像を一定時間毎に異なる位置に表示することによってアニメーションを作成しています.

      Ball.as

      package {
      	import flash.display.Sprite;
      	import flash.display.Loader;
      	import flash.net.URLRequest;
      	import flash.events.Event;
      	import flash.events.MouseEvent;
      
      	[SWF(backgroundColor="0xeeffee", width="600", height="400", frameRate="30")]
      
      	public class Ball extends Sprite {
      		private var ball : Loader;
      		private var g : Number = 9.8;   // y 軸方向の加速度
      		private var v0 : Number = 0;   // y 軸方向の初期速度
      		private var v : Number = 0;   // y 軸方向の現在速度
      		private var t : Number = 0;   // 時間の初期値
      		private var h0 : Number = stage.stageHeight;   // ボールの初期位置の y 座標(上が正,初期高さ)
      		private var sw : Number = 1;   // ボールの状態( 0:停止している,1:動いている)
      
      		public function Ball() {
      			init();
      		}
      
      		private function init():void {
      			ball = new Loader();
      			ball.load(new URLRequest("ball.gif"));
      			ball.x = -40;
      			ball.y = -40;
      			addChild(ball);
      			addEventListener(Event.ENTER_FRAME, onEnterFrame);
      			ball.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      		}
      
      		private function onEnterFrame(event:Event):void {
      			if (ball.x < stage.stageWidth + 40 && sw > 0) {
      				ball.x += 1.5;
      				t      += 0.1;
      				v       = -g * t + v0;
      				ball.y  = stage.stageHeight - (-0.5 * g * t * t + v0 * t + h0) - 40;
      				if (ball.y >= stage.stageHeight - 80 && v < 0) {
      					ball.y = stage.stageHeight - 80;
      					v0     = -0.8 * v;
      					h0     = 40;
      					t      = 0;
      				}
      				trace("position", ball.x, ball.y);
      			}
      		}
      
      		private function onMouseDown(event:MouseEvent):void {
      			if (sw == 0)
      				sw = 1;
      			else
      				sw = 0;
      		}
      	}
      }
      				

    5. ピクセル値の操作(花火)

        「 Java の場合」と同様,アニメーションを作成する方法としては,今まで述べた図形を描画する方法や外部から読み込んだ図形を順に表示する方法の他に,イメージのピクセル値を直接編集する方法が考えられます(もちろん,これらの方法を同時に使用する方法も考えられます).最初の例は,ピクセル値を直接操作して描いた矩形を左から右に移動させているだけのものです.

      Pixel.as

      01	package
      02	{
      03		import flash.display.Sprite;
      04		import flash.display.Bitmap;
      05		import flash.display.BitmapData;
      06		import flash.events.Event;
      07	
      08		[SWF(backgroundColor="0xeeffee", width="600", height="400", frameRate="10")]
      09	
      10		public class Pixel extends Sprite
      11		{
      12			private var w : int = 40;   // 図形の幅
      13			private var h : int = 40;   // 図形の高さ
      14			private var bmd : BitmapData;   // BitmapData オブジェクト
      15			private var bm : Bitmap;   // Bitmap オブジェクト
      16			
      17			public function Pixel()
      18			{
      19				var i1 : int;
      20				var i2 : int;
      21	
      22				bmd = new BitmapData(w, h, true, 0x00000000);
      23				for(i1 = 0; i1 < h; i1++) {
      24					for(i2 = 0; i2 < w; i2++) {
      25						if (i1 < h/2)
      26							bmd.setPixel32(i2, i1, 0xffff0000);
      27						else
      28							bmd.setPixel32(i2, i1, 0xff00ff00);
      29					}
      30				}
      31				bm = new Bitmap(bmd);
      32				bm.x = 0;
      33				bm.y = stage.stageHeight / 2 - h / 2;
      34				addChild(bm);
      35	
      36				addEventListener(Event.ENTER_FRAME, onEnterFrame);
      37			}
      38	
      39			private function onEnterFrame(event:Event):void
      40			{
      41				bm.x += 20;
      42				if (bm.x >= stage.stageWidth - w)
      43					bm.x = 0;
      44			}
      45		}
      46	}
      				
      22 行目

        BitmapData クラスによって,すべてのピクセル値が黒である正方形の領域を生成している.

      23 行目~ 30 行目

        矩形の上半分を赤に,また,下半分を青に設定している.各ピクセルの透明度,赤,緑,青に対する情報が,4 バイト 1 組になり,bmd の 1 次元配列に設定される.

      31 行目

        表示できるようにするため,生成された BitmapData オブジェクトから Bitmap クラスのオブジェクトを生成している.

      32 行目~ 34 行目

        矩形の初期位置を設定し,ステージに追加している.

        次の例は,もう少し複雑な例です.花火と同じような情景を描いています.

      Fire.as

      001	package
      002	{
      003		import flash.display.Sprite;
      004		import flash.display.Bitmap;
      005		import flash.display.BitmapData;
      006		import flash.events.Event;
      007	
      008		[SWF(backgroundColor="0x000000", width="600", height="400", frameRate="5")]
      009	
      010		public class Fire extends Sprite
      011		{
      012			private var max : int = 20;   // 花火の数
      013			private var m_pr : int = 7;   // 打ち上げ間隔の最大値
      014			private var m_cl : int = 10;   // 花火の色の最大値
      015			private var f_l : int = 300;   // 花火の直径
      016			private var count : int = 0;   // カウンタ
      017			private var next : int = 0;   // 次の打ち上げ時期
      018			private var k : Array = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
      019									 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];   // 花火の状態(-1:打ち上げ前,0:打ち上げ当初,>0:描いた輪の数)
      020			private var cl : Array = new Array();   // 花火の色
      021			private var bmd : Array = new Array();
      022			private var bm : Array = new Array();
      023			private var color : Array = [0xffff0000, 0xff00ff00, 0xff0000ff, 0xffffff00, 0xffff00ff,
      024									     0xff00ffff, 0xffeeffee, 0xffffaaaa, 0xffaaffaa, 0xffaaaaff];   // 花火の基本色
      025			
      026			public function Fire()
      027			{
      028				init();
      029			}
      030			
      031			private function init():void
      032			{
      033				var i1 : int;
      034	
      035				for (i1 = 0; i1 < max; i1++) {
      036					bmd[i1] = new BitmapData(f_l, f_l, true, 0x00000000);
      037					bm[i1] = new Bitmap(bmd[i1]);
      038					addChild(bm[i1]);
      039				}
      040				addEventListener(Event.ENTER_FRAME, onEnterFrame);
      041			}
      042	
      043			private function onEnterFrame(event:Event):void
      044			{
      045				var ang:Number, s:Number;
      046				var i0:int, i1:int, i2:int, i3:int, kx:int, ky:int, kx1:int, ky1:int, sw:int;
      047	
      048				for (i0 = 0; i0 < max; i0++) {
      049					if (k[i0] < 0) {
      050							// 新しい花火
      051						if (count >= next && sw == 0) {
      052							sw     = 1;
      053							count  = 0;
      054							cl[i0] = int(m_cl * Math.random());
      055							if (cl[i0] >= m_cl)
      056								cl[i0] = m_cl - 1;
      057							bm[i0].x = stage.stageWidth * Math.random() - f_l / 2;
      058							bm[i0].y = stage.stageHeight * Math.random() - f_l / 2;
      059							k[i0] = 0;
      060							next  = int(m_pr * Math.random());
      061							if (next <= 0)
      062								next = 1;
      063						}
      064					}
      065					else {
      066						k[i0]++;
      067							// 花火の消去
      068						if (k[i0] > m_pr) {
      069							k[i0] = -1;
      070							for(i1 = 0; i1 < f_l; i1++) {
      071								for(i2 = 0; i2 < f_l; i2++)
      072									bmd[i0].setPixel32(i1, i2, 0x00000000);
      073							}
      074						}
      075							// 花火の描画
      076						else {
      077							s   = Math.PI / 6;
      078							ang = 0;
      079							for (i1 = 0; i1 < 12; i1++) {
      080								kx = f_l / 2 + 20 * k[i0] * Math.cos(ang);
      081								ky = f_l / 2 + 20 * k[i0] * Math.sin(ang);
      082								for (i2 = kx-5; i2 < kx+5; i2++) {
      083									for (i3 = ky-5; i3 < ky+5; i3++)
      084										bmd[i0].setPixel32(i2, i3, color[cl[i0]]);
      085								}
      086								bmd[i0].setPixel32(kx-1, ky-6, color[cl[i0]]);
      087								bmd[i0].setPixel32(kx, ky-6, color[cl[i0]]);
      088								bmd[i0].setPixel32(kx+1, ky-6, color[cl[i0]]);
      089								bmd[i0].setPixel32(kx-1, ky+5, color[cl[i0]]);
      090								bmd[i0].setPixel32(kx, ky+5, color[cl[i0]]);
      091								bmd[i0].setPixel32(kx+1, ky+5, color[cl[i0]]);
      092								bmd[i0].setPixel32(kx-6, ky-1, color[cl[i0]]);
      093								bmd[i0].setPixel32(kx-6, ky, color[cl[i0]]);
      094								bmd[i0].setPixel32(kx-6, ky+1, color[cl[i0]]);
      095								bmd[i0].setPixel32(kx+5, ky-1, color[cl[i0]]);
      096								bmd[i0].setPixel32(kx+5, ky, color[cl[i0]]);
      097								bmd[i0].setPixel32(kx+5, ky+1, color[cl[i0]]);
      098								ang += s;
      099							}
      100						}
      101					}
      102				}
      103	
      104				count++;
      105			}
      106		}
      107	}
      				
      035 行目~ 039 行目

        ビットマップイメージを処理するための BitmapData クラスによって,花火の大きさを 1 辺とするすべてのピクセル値が黒である正方形の領域を生成した後,そのオブジェクトを表示できるようにするため,生成された BitmapData オブジェクトから Bitmap クラスのオブジェクトを生成している.

      049 行目~ 064 行目

        花火が打ち上げ前の状態( k[i0] < 0 )であるときの処理である.カウンタ count の値が 次の打ち上げ時刻 next 以降であり,かつ,次の花火の打ち上げ時刻が設定されていない場合( sw == 0 )は,新しい花火を打ち上げるために,以下の処理が行われる.
      • 052 行目: 次の花火の打ち上げ時刻設定済み
      • 053 行目: カウンタの初期設定
      • 054 行目~ 056 行目: 花火の色を基本色からランダムに選択
      • 057 行目~ 058 行目: 花火の位置をランダムに選択
      • 059 行目: 花火を打ち上げた状態に設定
      • 060 行目~ 062 行目: 次の打ち上げ時刻をランダムに選択

      068 行目~ 074 行目

        花火を打ち上げた後の処理であり,066 行目において描画する輪の数を増加させ,その数が指定の数( m_pr )より大きくなった場合は,花火を消去する(すべてのピクセル値を黒にする).

      077 行目~ 099 行目

        現在の半径位置( k[i0] )で,かつ,円周を 12 等分した位置に 幅 9 ピクセル,高さ 9 ピクセルの矩形を描いている.なお,086 行目~ 097 行目は,上で描いた矩形に多少丸みを付けるための処理であり,必ずしも必要ない.

      104 行目

        カウンタ(時間)の増加処理

    6. Web ページ

        ここでは,ActionScript によって,「 Java の場合」と同じようなホームページのトップページを作成した例を示します.最初に表示された状態では,すべての図形が停止していますが,徐々に各図形が動き出します.まず,上部にある文字の部分をクリックすると,

      加速: 動きが少しずつ速くなります
      加速: 動きが少しずつ遅くなります
      情報学部: 情報学部への入り口に移動します

      といった動作を行います.

        図形部分をクリックすると,動きが止まり,対応する説明が表示されます.この際,Java の場合は,新しい Window を生成しましたが,ActionScript では不可能ですので,説明用の Sprite オブジェクトを生成しています.このオブジェクトは,ドラッグ&ドロップが可能なように設定してあり,また,ダブルクッリクすると削除できます.ただし,サイズの変更はできないようになっています.

        説明を削除する(ダブルクリック)と再び動き出し,説明を削除せずに文字や図形以外の部分をクリックすると説明に対応する図形が削除された後,他の図形は再び動き出します.また,文字や図形以外の部分をクリックすると,動きが停止します.停止した状態で,文字や図形以外の部分をクリックすると,再び動き出します.最初に設定されている速度では,各図形をクリックすることは難しいかと思いますので,減速又は停止した後にクリックしてみてください.

      Space.as

      package
      {
      	import flash.display.Sprite;
      	import flash.display.Loader;
      	import flash.events.Event;
      	import flash.net.URLRequest;
      	import flash.events.MouseEvent;
      	import flash.text.TextField;
      	import flash.text.TextFieldType;
      	import flash.text.TextFormat;
      	import flash.text.TextFormatAlign;
      	import flash.net.navigateToURL;
      	import flash.net.URLRequest;
      
      	[SWF(backgroundColor="0xffffff", width="1024", height="768", frameRate="10")]
      
      	public class Space extends Sprite
      	{
      		private var space : Loader;
      		private var bun : Array = new Array();
      		private var bun_t : Array = new Array();
      		private var bun_tg : Array = new Array();
      		private var i_w:Array, i_wt:Array, i_h:Array, i_ht:Array;   // 画像の幅と高さ
      		private var p:Array, a:Array, b:Array;   // 周期,楕円の長径と短径
      		private var gx:Array, gy:Array, gz:Array;   // 画像の位置
      		private var now:Array, s:Array, c:Array;   // 画像の現在位置など
      
      		private var dsp : Array;   // 画像の表示の有無
      		private var state : int = 1;
      		private var h:Number, w:Number;
      		private var dsp_t : Array = [-1, -1, -1, -1, -1, -1, -1, -1, -1];
      		private var gaku:TextField, slow:TextField, hurry:TextField;
      /*
      		コンストラクタ
      */
      		public function Space()
      		{
      			i_load();
      		}
      /*
      		画像の読み込み
      */
      		private function i_load():void
      		{
      			var i1 : int;
      					// 背景画像
      			space = new Loader();
      			space.load(new URLRequest("space.jpg"));
      					// 領域の図
      			bun[0] = new Loader();
      			bun[0].load(new URLRequest("computer.gif"));
      			bun[1] = new Loader();
      			bun[1].load(new URLRequest("architecture.gif"));
      			bun[2] = new Loader();
      			bun[2].load(new URLRequest("AI.gif"));
      			bun[3] = new Loader();
      			bun[3].load(new URLRequest("life.gif"));
      			bun[4] = new Loader();
      			bun[4].load(new URLRequest("education.gif"));
      			bun[5] = new Loader();
      			bun[5].load(new URLRequest("media.gif"));
      			bun[6] = new Loader();
      			bun[6].load(new URLRequest("social.gif"));
      			bun[7] = new Loader();
      			bun[7].load(new URLRequest("business.gif"));
      			bun[8] = new Loader();
      			bun[8].load(new URLRequest("communication.gif"));
      					// 領域の説明
      			bun_tg[0] = new Loader();
      			bun_tg[0].load(new URLRequest("computer_txt.gif"));
      			bun_tg[1] = new Loader();
      			bun_tg[1].load(new URLRequest("architecture_txt.gif"));
      			bun_tg[2] = new Loader();
      			bun_tg[2].load(new URLRequest("AI_txt.gif"));
      			bun_tg[3] = new Loader();
      			bun_tg[3].load(new URLRequest("life_txt.gif"));
      			bun_tg[4] = new Loader();
      			bun_tg[4].load(new URLRequest("education_txt.gif"));
      			bun_tg[5] = new Loader();
      			bun_tg[5].load(new URLRequest("media_txt.gif"));
      			bun_tg[6] = new Loader();
      			bun_tg[6].load(new URLRequest("social_txt.gif"));
      			bun_tg[7] = new Loader();
      			bun_tg[7].load(new URLRequest("business_txt.gif"));
      			bun_tg[8] = new Loader();
      			bun_tg[8].load(new URLRequest("communication_txt.gif"));
      			bun_tg[8].contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
      		}
      /*
      		初期設定
      */
      		private function init():void
      		{
      			var i1 : int;
      					// テキストフィールド
      			var gaku : TextField = new TextField();
      			gaku.text = "情報学部";
      			gaku.width = 160;
      			gaku.height = 30;
      			gaku.name = "gaku";
      			gaku.x = width / 2 - gaku.width / 2;
      			gaku.y = 10;
      			gaku.type = TextFieldType.DYNAMIC;
      			var tf_gaku : TextFormat = new TextFormat();
      			tf_gaku.size = 25;
      			tf_gaku.color = 0xff00ffff;
      			tf_gaku.align = TextFormatAlign.CENTER;
      			gaku.setTextFormat(tf_gaku);
      			gaku.addEventListener(MouseEvent.CLICK, onClick);
      			addChild(gaku);
      
      			var slow : TextField = new TextField();
      			slow.text = "<< 減速";
      			slow.width = 70;
      			slow.height = 25;
      			slow.name = "slow";
      			slow.x = width / 2 - gaku.width / 2 - slow.width - 20;
      			slow.y = 13;
      			slow.type = TextFieldType.DYNAMIC;
      			var tf_slow : TextFormat = new TextFormat();
      			tf_slow.size = 20;
      			tf_slow.color = 0xffffff00;
      			tf_slow.align = TextFormatAlign.CENTER;
      			slow.setTextFormat(tf_slow);
      			slow.addEventListener(MouseEvent.CLICK, onClick);
      			addChild(slow);
      
      			var hurry : TextField = new TextField();
      			hurry.text = "加速 >>";
      			hurry.width = 70;
      			hurry.height = 25;
      			hurry.name = "hurry";
      			hurry.x = width / 2 + gaku.width / 2 + 20;
      			hurry.y = 13;
      			hurry.type = TextFieldType.DYNAMIC;
      			var tf_hurry : TextFormat = new TextFormat();
      			tf_hurry.size = 20;
      			tf_hurry.color = 0xffffff00;
      			tf_hurry.align = TextFormatAlign.CENTER;
      			hurry.setTextFormat(tf_hurry);
      			hurry.addEventListener(MouseEvent.CLICK, onClick);
      			addChild(hurry);
      					// 周期,楕円の長径と短径
      			p  = new Array();
      			a  = new Array();
      			b  = new Array();
      			gx = new Array();
      			gy = new Array();
      			gz = new Array();
      			for (i1 = 0; i1 < 9; i1++) {
      				p[i1] = int(10 + 70 * Math.random());
      				if (i1 == 3 || i1 == 4)
      					a[i1] = 3 * height / 8 + (width / 8 + 50) * Math.random();
      				else
      					a[i1] = 3 * width / 8 + (width / 8 + 50) * Math.random();
      				b[i1] = 3 * height / 8 + (height / 8 + 50) * Math.random();
      			}
      					// 現在位置など
      			now = new Array();
      			s   = new Array();
      			c   = new Array();
      			for (i1 = 0; i1 < 9; i1++)
      				now[i1] = 0;
      			for (i1 = 0; i1 < 9; i1++)
      				c[i1] = int(100 * Math.random());
      			for (i1 = 0; i1 < 9; i1++)
      				addChild(bun[i1]);
      			w     = width;
      			h     = height;
      			gx[0] = w / 2;
      			gy[0] = h / 2;
      			gz[0] = 0;
      
      			addEventListener(Event.ENTER_FRAME, onEnterFrame);
      		}
      /*
      		一定時間ごとの処理
      */
      		private function onEnterFrame(event:Event):void
      		{
      			var i1:int, i2:int, m:int = 0;
      			var r:Number, x1:Number, x2:Number, y1:Number, y2:Number, z1:Number, z2:Number, sw:Number, sh:Number;
      			var a45 : Number = Math.PI / 4.0;
      			var w1:Number, h1:Number;
      
      			if (state == 1) {
      						// アーキテクチャ
      				if (dsp[1]) {
      					x1    = a[1] * Math.cos(2 * Math.PI / p[1] * now[1]);
      					gy[1] = h / 2;
      					z1    = b[1] * Math.sin(2 * Math.PI / p[1] * now[1]);
      					gx[1] = w / 2 + (int)(Math.cos(a45) * x1 - Math.sin(a45) * z1);
      					gz[1] = (int)(Math.sin(a45) * x1 + Math.cos(a45) * z1);
      				}
      						// 人工知能
      				if (dsp[2]) {
      					x1    = a[2] * Math.cos(-Math.PI + 2 * Math.PI / p[2] * now[2]);
      					gy[2] = h / 2;
      					z1    = b[2] * Math.sin(-Math.PI + 2 * Math.PI / p[2] * now[2]);
      					gx[2] = w / 2 + (int)(Math.cos(-a45) * x1 - Math.sin(-a45) * z1);
      					gz[2] = (int)(Math.sin(-a45) * x1 + Math.cos(-a45) * z1);
      				}
      						// 生命
      				if (dsp[3]) {
      					gx[3] = w / 2;
      					y1    = a[3] * Math.cos(2 * Math.PI / p[3] * now[3]);
      					z1    = b[3] * Math.sin(2 * Math.PI / p[3] * now[3]);
      					gy[3] = h / 2 + (int)(Math.cos(a45) * y1 - Math.sin(a45) * z1);
      					gz[3] = (int)(Math.sin(a45) * y1 + Math.cos(a45) * z1);
      				}
      						// 教育
      				if (dsp[4]) {
      					gx[4] = w / 2;
      					y1    = a[4] * Math.cos(-Math.PI + 2 * Math.PI / p[4] * now[4]);
      					z1    = b[4] * Math.sin(-Math.PI + 2 * Math.PI / p[4] * now[4]);
      					gy[4] = h / 2 + (int)(Math.cos(-a45) * y1 - Math.sin(-a45) * z1);
      					gz[4] = (int)(Math.sin(-a45) * y1 + Math.cos(-a45) * z1);
      				}
      						// メディア
      				if (dsp[5]) {
      					x1    = a[5] * Math.cos(2 * Math.PI / p[5] * now[5]);
      					y1    = 0;
      					z1    = b[5] * Math.sin(2 * Math.PI / p[5] * now[5]);
      					x2    = (int)(Math.cos(a45) * x1 - Math.sin(a45) * z1);
      					gz[5] = (int)(Math.sin(a45) * x1 + Math.cos(a45) * z1);
      					gx[5] = w / 2 + (int)(Math.cos(a45) * x2 - Math.sin(a45) * y1);
      					gy[5] = h / 2 + (int)(Math.sin(a45) * x2 + Math.cos(a45) * y1);
      				}
      						// 社会
      				if (dsp[6]) {
      					x1    = a[6] * Math.cos(2 * Math.PI / p[6] * now[6]);
      					y1    = 0;
      					z1    = b[6] * Math.sin(2 * Math.PI / p[6] * now[6]);
      					x2    = (int)(Math.cos(a45) * x1 - Math.sin(a45) * z1);
      					gz[6] = (int)(Math.sin(a45) * x1 + Math.cos(a45) * z1);
      					gx[6] = w / 2 + (int)(Math.cos(-a45) * x2 - Math.sin(-a45) * y1);
      					gy[6] = h / 2 + (int)(Math.sin(-a45) * x2 + Math.cos(-a45) * y1);
      				}
      						// ビジネス
      				if (dsp[7]) {
      					x1    = a[7] * Math.cos(Math.PI + 2 * Math.PI / p[7] * now[7]);
      					y1    = 0;
      					z1    = b[7] * Math.sin(Math.PI + 2 * Math.PI / p[7] * now[7]);
      					x2    = (int)(Math.cos(-a45) * x1 - Math.sin(-a45) * z1);
      					gz[7] = (int)(Math.sin(-a45) * x1 + Math.cos(-a45) * z1);
      					gx[7] = w / 2 + (int)(Math.cos(a45) * x2 - Math.sin(a45) * y1);
      					gy[7] = h / 2 + (int)(Math.sin(a45) * x2 + Math.cos(a45) * y1);
      				}
      						// コミュニケーション
      				if (dsp[8]) {
      					x1    = a[8] * Math.cos(Math.PI + 2 * Math.PI / p[8] * now[8]);
      					y1    = 0;
      					z1    = b[8] * Math.sin(Math.PI + 2 * Math.PI / p[8] * now[8]);
      					x2    = (int)(Math.cos(-a45) * x1 - Math.sin(-a45) * z1);
      					gz[8] = (int)(Math.sin(-a45) * x1 + Math.cos(-a45) * z1);
      					gx[8] = w / 2 + (int)(Math.cos(-a45) * x2 - Math.sin(-a45) * y1);
      					gy[8] = h / 2 + (int)(Math.sin(-a45) * x2 + Math.cos(-a45) * y1);
      				}
      						// 表示
      				for (i1 = 0; i1 < 9; i1++)
      					s[i1] = 0;
      				for (i1 = 0; i1 < 9; i1++) {
      					m = -1;
      					for (i2 = 0; i2 < 9; i2++) {
      						if (s[i2] == 0 && (m < 0 || gz[m] > gz[i2]))
      							m = i2;
      					}
      					s[m] = 1;
      					if (dsp[m]) {
      						if (m == 0) {
      							bun[0].x = gx[0] - i_w[0] / 2;
      							bun[0].y = gy[0] - i_h[0] / 2;
      						}
      						else {
      							r  = (w / 2.0 + gz[m]) / w;
      							sw = r * i_w[m];
      							sh = r * i_h[m];
      							bun[m].width  = sw;
      							bun[m].height = sh;
      							bun[m].x = gx[m] - sw / 2;
      							bun[m].y = gy[m] - sh / 2;
      							if (c[m] > 0)
      								c[m]--;
      							else {
      								now[m]++;
      								if (now[m] >= p[m])
      									now[m] = 0;
      							}
      						}
      					}
      				}
      			}
      
      			else {
      				for (i1 = 0; i1 < 9; i1++) {
      					if (dsp_t[i1] > 0) {
      						dsp_t[i1]++;
      						w1 = 1.5 * dsp_t[i1] * i_wt[i1] / 10;
      						h1 = 1.5 * dsp_t[i1] * i_ht[i1] / 10;
      						x1 = gx[i1] - 0.075 * i_wt[i1] + dsp_t[i1] * ((w / 2 - 0.75 * i_wt[i1]) - (gx[i1] - 0.075 * i_wt[i1])) / 10;
      						y1 = gy[i1] - 0.075 * i_ht[i1] + dsp_t[i1] * ((h / 2 - 0.75 * i_ht[i1]) - (gy[i1] - 0.075 * i_ht[i1])) / 10;
      						bun_t[i1].width  = w1;
      						bun_t[i1].height = h1;
      						bun_t[i1].x = x1;
      						bun_t[i1].y = y1;
      						if (dsp_t[i1] == 10)
      							dsp_t[i1] = 0;
      					}
      				}
      			}
      		}
      /*
      		マウスのクリック
      */
      		private function onClick(event:MouseEvent):void
      		{
      			var w1:Number, h1:Number;
      			var k : int = -1;
      
      			if (event.target.name == "gaku")
      				navigateToURL(new URLRequest("http://ex-cs.sist.ac.jp/~suganuma/dep/index.html"));
      			else if (event.target.name == "slow") {
      				stage.frameRate--;
      				if (stage.frameRate < 1)
      					stage.frameRate = 1;
      			}
      			else if (event.target.name == "hurry")
      				stage.frameRate++;
      			else {
      				if (event.target.name == "computer")
      					k = 0;
      				else if (event.target.name == "architecture")
      					k = 1;
      				else if (event.target.name == "AI")
      					k = 2;
      				else if (event.target.name == "life")
      					k = 3;
      				else if (event.target.name == "education")
      					k = 4;
      				else if (event.target.name == "media")
      					k = 5;
      				else if (event.target.name == "social")
      					k = 6;
      				else if (event.target.name == "business")
      					k = 7;
      				else if (event.target.name == "communication")
      					k = 8;
      				if (k >= 0) {
      					if (dsp_t[k] <= 0) {
      						state = 2;
      						dsp_t[k] = 1;
      						w1 = 0.15 * i_wt[k];
      						h1 = 0.15 * i_ht[k];
      						bun_t[k].width = w1;
      						bun_t[k].height = h1;
      						bun_t[k].x = gx[k] - w1 / 2;
      						bun_t[k].y = gy[k] - h1 / 2;
      						bun_tg[k].doubleClickEnabled = true;
      						bun_tg[k].addEventListener(MouseEvent.DOUBLE_CLICK, onDoubleClick);
      						bun_tg[k].addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      						bun[k].visible = false;
      						addChild(bun_t[k]);
      					}
      				}
      				else {
      					if (state == 1)
      						state = 2;
      					else
      						state = 1;
      				}
      			}
      		}
      /*
      		マウスのダブルクリック
      */
      		private function onDoubleClick(event:MouseEvent):void
      		{
      			var k : int = -1;
      
      			if (event.target.name == "computer_t")
      				k = 0;
      			else if (event.target.name == "architecture_t")
      				k = 1;
      			else if (event.target.name == "AI_t")
      				k = 2;
      			else if (event.target.name == "life_t")
      				k = 3;
      			else if (event.target.name == "education_t")
      				k = 4;
      			else if (event.target.name == "media_t")
      				k = 5;
      			else if (event.target.name == "social_t")
      				k = 6;
      			else if (event.target.name == "business_t")
      				k = 7;
      			else
      				k = 8;
      			bun_t[k].removeEventListener(MouseEvent.DOUBLE_CLICK, onDoubleClick);
      			removeChild(bun_t[k]);
      			bun[k].visible = true;
      			state = 1;
      		}
      /*
      		マウスのダウン
      */
      		private function onMouseDown(event:MouseEvent):void
      		{
      			var k : int = -1;
      
      			if (event.target.name == "computer_t")
      				k = 0;
      			else if (event.target.name == "architecture_t")
      				k = 1;
      			else if (event.target.name == "AI_t")
      				k = 2;
      			else if (event.target.name == "life_t")
      				k = 3;
      			else if (event.target.name == "education_t")
      				k = 4;
      			else if (event.target.name == "media_t")
      				k = 5;
      			else if (event.target.name == "social_t")
      				k = 6;
      			else if (event.target.name == "business_t")
      				k = 7;
      			else
      				k = 8;
      			bun_t[k].startDrag();
      			bun_t[k].addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
      			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      		}
      /*
      		マウスの移動
      */
      		private function onMouseMove(event:MouseEvent):void
      		{
      			event.updateAfterEvent();
      		}
      /*
      		マウスのアップ
      */
      		private function onMouseUp(event:MouseEvent):void
      		{
      			var k : int = -1;
      
      			if (event.target.name == "computer_t")
      				k = 0;
      			else if (event.target.name == "architecture_t")
      				k = 1;
      			else if (event.target.name == "AI_t")
      				k = 2;
      			else if (event.target.name == "life_t")
      				k = 3;
      			else if (event.target.name == "education_t")
      				k = 4;
      			else if (event.target.name == "media_t")
      				k = 5;
      			else if (event.target.name == "social_t")
      				k = 6;
      			else if (event.target.name == "business_t")
      				k = 7;
      			else
      				k = 8;
      			bun_t[k].stopDrag();
      			bun_t[k].removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
      			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      		}
      /*
      		画像読み込み後の処理
      */
      		private function onComplete(event:Event):void
      		{
      			var i1 : int;
      
      			space.x = 0;
      			space.y = 0;
      			addChild(space);
      					// 名前の設定
      			bun[0].name = "computer";
      			bun[1].name = "architecture";
      			bun[2].name = "AI";
      			bun[3].name = "life";
      			bun[4].name = "education";
      			bun[5].name = "media";
      			bun[6].name = "social";
      			bun[7].name = "business";
      			bun[8].name = "communication";
      			bun_t[0] = new Sprite();
      			bun_t[0].addChild(bun_tg[0]);
      			bun_t[1] = new Sprite();
      			bun_t[1].addChild(bun_tg[1]);
      			bun_t[2] = new Sprite();
      			bun_t[2].addChild(bun_tg[2]);
      			bun_t[3] = new Sprite();
      			bun_t[3].addChild(bun_tg[3]);
      			bun_t[4] = new Sprite();
      			bun_t[4].addChild(bun_tg[4]);
      			bun_t[5] = new Sprite();
      			bun_t[5].addChild(bun_tg[5]);
      			bun_t[6] = new Sprite();
      			bun_t[6].addChild(bun_tg[6]);
      			bun_t[7] = new Sprite();
      			bun_t[7].addChild(bun_tg[7]);
      			bun_t[8] = new Sprite();
      			bun_t[8].addChild(bun_tg[8]);
      			bun_tg[0].name = "computer_t";
      			bun_tg[1].name = "architecture_t";
      			bun_tg[2].name = "AI_t";
      			bun_tg[3].name = "life_t";
      			bun_tg[4].name = "education_t";
      			bun_tg[5].name = "media_t";
      			bun_tg[6].name = "social_t";
      			bun_tg[7].name = "business_t";
      			bun_tg[8].name = "communication_t";
      
      			i_w  = new Array();
      			i_h  = new Array();
      			i_wt = new Array();
      			i_ht = new Array();
      			dsp  = new Array();
      			for (i1 = 0; i1 < 9; i1++) {
      				i_w[i1]  = bun[i1].width;
      				i_h[i1]  = bun[i1].height;
      				i_wt[i1] = bun_t[i1].width;
      				i_ht[i1] = bun_t[i1].height;
      				dsp[i1]  = true;
      				bun[i1].addEventListener(MouseEvent.CLICK, onClick);
      			}
      			addEventListener(MouseEvent.CLICK, onClick);
      
      			init();
      		}
      	}
      }
      				

  2. ゲーム

      ゲームに関しては,「 ActionScript によるゲームプログラミング」も参考にして下さい.より多くのゲームに対し,より詳細な説明をしています.なお,ここでも,「 Java の場合」と同じゲームを扱っています.

    1. シューティングゲーム

        このプログラムは,キーイベントを使用した簡単なシューティング風ゲームです.左右の矢印キーによって下中央に描かれた黒い矩形(砲台)を左右に動かすことができます.Shift キーをクリックするとレーザ砲が発射され,ターゲット(緑の円)に命中すると,ターゲットの色が一時的にピンクに変化し消滅します.また,ターゲットが,黒い矩形に当たるとゲームオーバーになります.

        ここでは,複数人で作成する大きなプログラムではなく,一人で比較的小さなプログラムを作成する場合について,その作成手順について考えてみます.少なくとも,すべてのプログラムを作成してからコンパイルし,実行してみるといった方法はあまり良い方法ではありません.作成するプログラムにもよりますが,私は,部分的な機能を実現するプログラムを作成し,その機能を確認した後,新しい機能を追加していくといった方法をよく利用します.たとえば,この例の場合は,以下のような手順になります.

      1. ターゲットと砲台の表示:  単に,ターゲットと砲台を表示しているだけです.

        Game1.as

        01	package {
        02		import flash.display.Sprite;
        03		import flash.display.Shape;
        04	
        05		[SWF(backgroundColor="0xeeffee", width="500", height="300", frameRate="30")]
        06	
        07		public class Game1 extends Sprite {
        08			private var target : Shape;
        09			private var gun : Shape;
        10			private var r : int = 25;   // ターゲットの半径
        11			private var game : Boolean = true;   // ゲーム実行中か否か
        12	
        13			public function Game1() {
        14						// 砲台の表示
        15				gun   = new Shape();
        16				gun.x = stage.stageWidth / 2 - 10;
        17				gun.y = stage.stageHeight - 20;
        18				gun.graphics.beginFill(0x000000);
        19				gun.graphics.drawRect(0, 0, 20, 20);
        20				gun.graphics.endFill();
        21				addChild(gun);
        22						// ターゲットの表示
        23				target = new Shape();
        24				target.graphics.beginFill(0x00ff00);
        25				target.graphics.drawCircle(0, 0, r);
        26				target.graphics.endFill();
        27				target.x = 20;
        28				target.y = 50;
        29				addChild(target);
        30			}
        31		}
        32	}
        					
        15 行目~ 21 行目

          砲台として,一辺の長さが 20 ピクセルの塗りつぶした黒の正方形を追加している

        23 行目~ 29 行目

          ターゲットとして,半径 25 ピクセルの塗りつぶした緑の円を追加している.

      2. ターゲットの移動:  ENTER_FRAME イベントを利用して,30 コマ/秒の速さで,ターゲットを下方向へ移動してみます.前のステップで作成したプログラムを少し変更するだけですが,アニーションの機能を確認することができます.また,このプログラムでは,変数 game を false に設定することによって,ゲームオーバー画面も確認することができます.

        Game1.as

        01	package {
        02		import flash.display.Sprite;
        03		import flash.display.Shape;
        04		import flash.text.TextField;
        05		import flash.text.TextFieldType;
        06		import flash.text.TextFormat;
        07		import flash.text.TextLineMetrics;
        08		import flash.events.Event;
        09	
        10		[SWF(backgroundColor="0xeeffee", width="500", height="300", frameRate="30")]
        11	
        12		public class Game1 extends Sprite {
        13			private var target : Shape;
        14			private var gun : Shape;
        15			private var r : int = 25;   // ターゲットの半径
        16			private var sp : int = 5;   // ターゲットの速度
        17			private var game : Boolean = true;   // ゲーム実行中か否か
        18	
        19			public function Game1() {
        20						// 砲台の表示
        21				gun   = new Shape();
        22				gun.x = stage.stageWidth / 2 - 10;
        23				gun.y = stage.stageHeight - 20;
        24				gun.graphics.beginFill(0x000000);
        25				gun.graphics.drawRect(0, 0, 20, 20);
        26				gun.graphics.endFill();
        27				addChild(gun);
        28						// ターゲットの表示
        29				target = new Shape();
        30				target.graphics.beginFill(0x00ff00);
        31				target.graphics.drawCircle(0, 0, r);
        32				target.graphics.endFill();
        33				target.x = 20;
        34				target.y = 50;
        35				addChild(target);
        36	
        37				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        38			}
        39	
        40			private function onEnterFrame(event:Event):void {
        41						// ゲーム中
        42				if (game) {
        43					target.y += sp;
        44				}
        45						// ゲームオーバ
        46				else {
        47					var tf : TextFormat = new TextFormat();
        48					tf.size = 50;
        49					tf.bold = true;
        50					var tx : TextField  = new TextField();
        51					tx.text = "Game Over";
        52					tx.setTextFormat(tf);
        53					var mt : TextLineMetrics = tx.getLineMetrics(0);
        54					tx.width  = mt.width + 5;
        55					tx.height = mt.height + 5;
        56					tx.x      = stage.stageWidth / 2 - tx.width / 2;
        57					tx.y      = stage.stageHeight / 2 - tx.height / 2;
        58					addChild(tx);
        59				}
        60			}
        61		}
        62	}
        					
        37 行目

          ENTER_FRAME イベントに対応するため,イベントリスナを追加している.この結果,イベントが発生すると,onEnterFrame メソッド( 40 行目~ 60 行目)が実行される.

        42 行目~ 44 行目

          ゲーム実行中の処理であり,ターゲットの y 座標を sp ピクセルずつ増加させている.

        46 行目~ 59 行目

          ゲームオーバーになった場合に対する処理であり,画面中央に,「 Game Over 」を表示している.この画面は,変数 game を false に変更することによって表示可能である.なお,TextLineMetrics クラスは,テキストの位置および行のプロパティに関する情報を保持するクラスである.

      3. ターゲットの生成・移動・消滅:  ターゲットは,

        • 画面上に存在し,移動している状態( t_exist = 1 )
        • 画面上に存在しない状態( t_exist = 0 )
        • 命中し色が変わった状態( t_exist = 2 )

        という 3 つの状態のいずれかになります.その状態を記憶しているのが変数 t_exist です.ここでは,ターゲットを画面上部の任意の場所に生成し,画面の外に出たら消滅するように変更します.消滅すると,再び,新しいターゲットが生成されます.また,移動方向は,π/4 ~ 3π/4 の間の値からランダムに選択します.なお,位置や方向をランダムにするために,Math クラスの random メソッドを使用しています.

        Game1.as

        01	package {
        02		import flash.display.Sprite;
        03		import flash.display.Shape;
        04		import flash.text.TextField;
        05		import flash.text.TextFieldType;
        06		import flash.text.TextFormat;
        07		import flash.text.TextLineMetrics;
        08		import flash.events.Event;
        09	
        10		[SWF(backgroundColor="0xeeffee", width="500", height="300", frameRate="30")]
        11	
        12		public class Game1 extends Sprite {
        13			private var target : Shape;
        14			private var gun : Shape;
        15			private var t_exist : int = 0;   // ターゲットの状態(0:未存在,1:移動中,2:命中)
        16			private var vx : int;   // ターゲットのx方向の速度
        17			private var vy : int;   // ターゲットのy方向の速度
        18			private var r : int = 25;   // ターゲットの半径
        19			private var sp : int = 5;   // ターゲットの速度
        20			private var game : Boolean = true;   // ゲーム実行中か否か
        21	
        22			public function Game1() {
        23						// 砲台の表示
        24				gun   = new Shape();
        25				gun.x = stage.stageWidth / 2 - 10;
        26				gun.y = stage.stageHeight - 20;
        27				gun.graphics.beginFill(0x000000);
        28				gun.graphics.drawRect(0, 0, 20, 20);
        29				gun.graphics.endFill();
        30				addChild(gun);
        31						// ターゲットの表示
        32				target   = new Shape();
        33				target.x = -r;
        34				target.y = -r;
        35				target.graphics.beginFill(0x00ff00);
        36				target.graphics.drawCircle(0, 0, r);
        37				target.graphics.endFill();
        38				addChild(target);
        39	
        40				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        41			}
        42	
        43			private function onEnterFrame(event:Event):void {
        44						// ゲーム中
        45				if (game) {
        46								// ターゲットの移動と消滅
        47					if (t_exist == 1) {
        48						target.x += vx;
        49						target.y += vy;
        50						if (target.x < -2*r || target.x > stage.stageWidth+r || target.y > stage.stageHeight+r)
        51							t_exist = 0;
        52					}
        53								// ターゲットの生成
        54					else {
        55						target.x = 2 * r + (int)((stage.stageWidth - 4 * r) * Math.random());
        56						target.y = 0;
        57						var ang : Number = 0.5 * Math.PI * Math.random() + 0.25 * Math.PI;
        58						vx      = (int)(sp * Math.cos(ang));
        59						vy      = (int)(sp * Math.sin(ang));
        60						t_exist = 1;
        61					}
        62				}
        63						// ゲームオーバ
        64				else {
        65					var tf : TextFormat = new TextFormat();
        66					tf.size = 50;
        67					tf.bold = true;
        68					var tx : TextField  = new TextField();
        69					tx.text = "Game Over";
        70					tx.setTextFormat(tf);
        71					var mt : TextLineMetrics = tx.getLineMetrics(0);
        72					tx.width  = mt.width + 5;
        73					tx.height = mt.height + 5;
        74					tx.x      = stage.stageWidth / 2 - tx.width / 2;
        75					tx.y      = stage.stageHeight / 2 - tx.height / 2;
        76					addChild(tx);
        77				}
        78			}
        79		}
        80	}
        					
        47 行目~ 52 行目

          ターゲットの x 座標,及び,y 座標を変化させ,画面の外に出た場合はターゲットを消滅させている.ただし,実際には,変数 t_exist に 0 を設定し,ターゲットは存在しないという指標を設定しただけであり,target オブジェクト自身が消滅したわけではない.

        54 行目~ 61 行目

          ターゲットの位置を初期状態( x 座標の値はランダムに選択)に戻すと共に,ターゲットの進行方向をランダムに選択し,その値から,ターゲットの x 軸方向,及び,y 軸方向の速度を計算している.

      4. ゲームオーバー:  このゲームでは,ターゲットと砲台が衝突するとゲームオーバーとなります.ここでは,その判定を追加します.まだ,砲台を移動できませんので,砲台に衝突するようなターゲットが現れるまでしばらく待ち,機能を確認します.

        Game1.as

        01	package {
        02		import flash.display.Sprite;
        03		import flash.display.Shape;
        04		import flash.text.TextField;
        05		import flash.text.TextFieldType;
        06		import flash.text.TextFormat;
        07		import flash.text.TextLineMetrics;
        08		import flash.events.Event;
        09	
        10		[SWF(backgroundColor="0xeeffee", width="500", height="300", frameRate="30")]
        11	
        12		public class Game1 extends Sprite {
        13			private var target : Shape;
        14			private var gun : Shape;
        15			private var t_exist : int = 0;   // ターゲットの状態(0:未存在,1:移動中,2:命中)
        16			private var vx : int;   // ターゲットのx方向の速度
        17			private var vy : int;   // ターゲットのy方向の速度
        18			private var r : int = 25;   // ターゲットの半径
        19			private var sp : int = 5;   // ターゲットの速度
        20			private var game : Boolean = true;   // ゲーム実行中か否か
        21	
        22			public function Game1() {
        23						// 砲台の表示
        24				gun   = new Shape();
        25				gun.x = stage.stageWidth / 2 - 10;
        26				gun.y = stage.stageHeight - 20;
        27				gun.graphics.beginFill(0x000000);
        28				gun.graphics.drawRect(0, 0, 20, 20);
        29				gun.graphics.endFill();
        30				addChild(gun);
        31						// ターゲットの表示
        32				target   = new Shape();
        33				target.x = -r;
        34				target.y = -r;
        35				target.graphics.beginFill(0x00ff00);
        36				target.graphics.drawCircle(0, 0, r);
        37				target.graphics.endFill();
        38				addChild(target);
        39	
        40				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        41			}
        42	
        43			private function onEnterFrame(event:Event):void {
        44						// ゲーム中
        45				if (game) {
        46								// ターゲットの移動と消滅
        47					if (t_exist == 1) {
        48										// ゲームオーバ
        49						var x1 : Number = target.x - (gun.x + 10);
        50						var y1 : Number = target.y - (gun.y + 10);
        51						if (Math.sqrt(x1*x1+y1*y1) < r+10) {
        52							game = false;
        53							graphics.clear();
        54							removeChild(gun);
        55							removeChild(target);
        56						}
        57										// ゲームオーバでない
        58						else {
        59							target.x += vx;
        60							target.y += vy;
        61							if (target.x < -2*r || target.x > stage.stageWidth+r || target.y > stage.stageHeight+r)
        62								t_exist = 0;
        63						}
        64					}
        65								// ターゲットの生成
        66					else {
        67						target.x = 2 * r + (int)((stage.stageWidth - 4 * r) * Math.random());
        68						target.y = 0;
        69						var ang : Number = 0.5 * Math.PI * Math.random() + 0.25 * Math.PI;
        70						vx      = (int)(sp * Math.cos(ang));
        71						vy      = (int)(sp * Math.sin(ang));
        72						t_exist = 1;
        73					}
        74				}
        75						// ゲームオーバ
        76				else {
        77					var tf : TextFormat = new TextFormat();
        78					tf.size = 50;
        79					tf.bold = true;
        80					var tx : TextField  = new TextField();
        81					tx.text = "Game Over";
        82					tx.setTextFormat(tf);
        83					var mt : TextLineMetrics = tx.getLineMetrics(0);
        84					tx.width  = mt.width + 5;
        85					tx.height = mt.height + 5;
        86					tx.x      = stage.stageWidth / 2 - tx.width / 2;
        87					tx.y      = stage.stageHeight / 2 - tx.height / 2;
        88					addChild(tx);
        89				}
        90			}
        91		}
        92	}
        					
        49 行目~ 56 行目

          ターゲットが移動中の場合に対して,ターゲットと砲台間の距離を計算し,それらが衝突している場合は,変数 game を false に設定し,グラフィックスをクリアし,かつ,砲台及びターゲットを削除している.

      5. キーイベント:  最後に,キーイベントに対する処理を追加します.左矢印または右矢印キーを押すと,砲台が左または右に 20 ピクセルだけ移動します.また,Shift キーを押すと,レーザ光が発射されます(変数 fire を 1 にする).

        Game1.as

        001	package {
        002		import flash.display.Sprite;
        003		import flash.display.Shape;
        004		import flash.text.TextField;
        005		import flash.text.TextFieldType;
        006		import flash.text.TextFormat;
        007		import flash.text.TextLineMetrics;
        008		import flash.events.Event;
        009		import flash.events.KeyboardEvent;
        010	
        011		[SWF(backgroundColor="0xeeffee", width="500", height="300", frameRate="30")]
        012	
        013		public class Game1 extends Sprite {
        014			private var target : Shape;
        015			private var gun : Shape;
        016			private var t_exist : int = 0;   // ターゲットの状態(0:未存在,1:移動中,2:命中)
        017			private var vx : int;   // ターゲットのx方向の速度
        018			private var vy : int;   // ターゲットのy方向の速度
        019			private var r : int = 25;   // ターゲットの半径
        020			private var sp : int = 5;   // ターゲットの速度
        021			private var fire : int = 0;   // レーザ砲の発射
        022			private var game : Boolean = true;   // ゲーム実行中か否か
        023	
        024			public function Game1() {
        025						// 砲台の表示
        026				gun   = new Shape();
        027				gun.x = stage.stageWidth / 2 - 10;
        028				gun.y = stage.stageHeight - 20;
        029				gun.graphics.beginFill(0x000000);
        030				gun.graphics.drawRect(0, 0, 20, 20);
        031				gun.graphics.endFill();
        032				addChild(gun);
        033						// ターゲットの表示
        034				target   = new Shape();
        035				target.x = -r;
        036				target.y = -r;
        037				target.graphics.beginFill(0x00ff00);
        038				target.graphics.drawCircle(0, 0, r);
        039				target.graphics.endFill();
        040				addChild(target);
        041	
        042				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        043				stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        044			}
        045	
        046			private function onEnterFrame(event:Event):void {
        047						// ゲーム中
        048				if (game) {
        049								// ターゲットの移動と消滅
        050					if (t_exist == 1) {
        051										// ゲームオーバ
        052						var x1 : Number = target.x - (gun.x + 10);
        053						var y1 : Number = target.y - (gun.y + 10);
        054						if (Math.sqrt(x1*x1+y1*y1) < r+10) {
        055							game = false;
        056							graphics.clear();
        057							removeChild(gun);
        058							removeChild(target);
        059						}
        060										// ゲームオーバでない
        061						else {
        062												// レーザ砲の発射
        063														// 命中
        064							if (fire > 0) {
        065								fire++;
        066								if (fire > 2) {
        067									fire = 0;
        068									graphics.clear();
        069									if (Math.abs(target.x-gun.x-10) < r) {
        070										t_exist = 2;
        071										target.graphics.clear();
        072										target.graphics.beginFill(0xffc0cb);
        073										target.graphics.drawCircle(0, 0, r);
        074										target.graphics.endFill();
        075									}
        076								}
        077							}
        078														// 命中でない
        079							else if (t_exist < 2) {
        080								target.x += vx;
        081								target.y += vy;
        082								if (target.x < -2*r || target.x > stage.stageWidth+r || target.y > stage.stageHeight+r)
        083									t_exist = 0;   // 画面外へ出た
        084							}
        085						}
        086					}
        087								// ターゲットの生成
        088					else if (fire == 0){
        089						if (t_exist == 2) {
        090							target.graphics.clear();
        091							target.graphics.beginFill(0x00ff00);
        092							target.graphics.drawCircle(0, 0, r);
        093							target.graphics.endFill();
        094						}
        095						target.x = 2 * r + (int)((stage.stageWidth - 4 * r) * Math.random());
        096						target.y = 0;
        097						var ang : Number = 0.5 * Math.PI * Math.random() + 0.25 * Math.PI;
        098						vx      = (int)(sp * Math.cos(ang));
        099						vy      = (int)(sp * Math.sin(ang));
        100						t_exist = 1;
        101					}
        102				}
        103						// ゲームオーバ
        104				else {
        105					var tf : TextFormat = new TextFormat();
        106					tf.size = 50;
        107					tf.bold = true;
        108					var tx : TextField  = new TextField();
        109					tx.text = "Game Over";
        110					tx.setTextFormat(tf);
        111					var mt : TextLineMetrics = tx.getLineMetrics(0);
        112					tx.width  = mt.width + 5;
        113					tx.height = mt.height + 5;
        114					tx.x      = stage.stageWidth / 2 - tx.width / 2;
        115					tx.y      = stage.stageHeight / 2 - tx.height / 2;
        116					addChild(tx);
        117				}
        118			}
        119	
        120			private function onKeyDown(e:KeyboardEvent):void {
        121				if (e.keyCode == 37)  // 左矢印
        122					gun.x -= 20;
        123				else if (e.keyCode == 39)   // 右矢印
        124					gun.x += 20;
        125				if (e.shiftKey) {   // Shift キー
        126					graphics.lineStyle(3, 0xff0000);  
        127					graphics.moveTo(gun.x+9, gun.y);
        128					graphics.lineTo(gun.x+9, 0);
        129					fire = 1;
        130				}
        131			}
        132		}
        133	}
        					
        043 行目

          KEY_DOWN イベント(キーが押された場合)に対応するため,ステージにイベントリスナを追加している.この結果,イベントが発生すると,onKeyDown メソッド( 120 行目~ 131 行目)が実行される.

        064 行目~ 077 行目

          レーザ砲が発射されている場合の処理である.変数 fire の値を増加させ,その値が 2 より大きい場合は,レーザ砲の発射痕跡を消し,命中判定を行っている.ターゲットに命中した場合は,ターゲットの状態を変更( t_exist = 2 )すると共に,ターゲットの色を 0xffc0cb に設定している.

        089 行目~ 094 行目

          ターゲットが画面の外に出て消滅したのではなく,レーザ砲に命中して消滅した場合に対する処理であり,ターゲットの色を元の緑に戻している.

        120 行目~ 131 行目

          キーが押された場合に対する処理である.左矢印キーの場合は,砲台を左に 20 ピクセル,また,右矢印キーの場合は,砲台を右に 20 ピクセル移動している.さらに,シフトキーの場合は,レーザ砲の痕跡を描き,レーザ砲が発射された状態に設定している( fire = 1 ).

    2. ぷよぷよ(テトリス)

        このプログラムは,キーイベントを使用した簡単なぷよぷよ風ゲームです.左右の矢印キーによって落下してくるピースを左右に動かすことができます.また,下矢印キーで90度,または,-90度の回転,上矢印キーで左右,または,上下の色を交換できます.

        ここでは,複数人で作成する大きなプログラムではなく,一人で比較的小さなプログラムを作成する場合について,その作成手順について考えてみます.少なくとも,すべてのプログラムを作成してからコンパイルし,実行してみるといった方法はあまり良い方法ではありません.作成するプログラムにもよりますが,私は,部分的な機能を実現するプログラムを作成し,その機能を確認した後,新しい機能を追加していくといった方法をよく利用します.たとえば,この例の場合は,以下のような手順になります.

      1. ピースの表示:  このプログラムでは,画面を格子状に区切り,この格子を配列に対応させ,各要素の値によってピースの色を制御しています( 0 の場合は,ピースが存在しない).どのような位置に,どのような色で表示しても構いませんが,後からのことを考えると,位置や色に対する一般的な処理を行っておいた方がよいと思います.なお,変数 p_x 及び p_y はピースの位置を表すための変数です.

        Game2.as

        01	package {
        02		import flash.display.Sprite;
        03		import flash.display.Shape;
        04	
        05		[SWF(backgroundColor="0xeeffee", width="270", height="380", frameRate="2")]
        06	
        07		public class Game2 extends Sprite {
        08			private var draw : Sprite;   // ゲーム領域
        09			private var ps : Array;   // ピースの配置
        10			private var p : Array;   // ピースの色(0の時は存在しない)
        11			private var row : int = 12;   // 行の数
        12			private var col : int = 5;   // 列の数
        13			private var p_x : int;   // 動いているピースの位置(列)
        14			private var p_y : int;   // 動いているピースの位置(行)
        15			private var p_wh : int = 30;   // ピースの幅と高さ
        16			private var game : Boolean = true;   // ゲーム中か否か
        17						//
        18						// コンストラクタ
        19						//
        20			public function Game2() {
        21				var i1 : int;
        22				var i2 : int;
        23								// ゲーム領域
        24				draw   = new Sprite();
        25				draw.x = 10;
        26				draw.y = 10;
        27				draw.graphics.beginFill(0xffffff);
        28				draw.graphics.drawRect(0, 0, p_wh*col, p_wh*row);
        29				draw.graphics.endFill();
        30				addChild(draw);
        31								// ピースの配置
        32				p  = new Array(row);
        33				ps = new Array(row);
        34				for (i1 = 0; i1 < row; i1++) {
        35					p[i1]  = new Array(col);
        36					ps[i1] = new Array(col);
        37					for (i2 = 0; i2 < col; i2++) {
        38						p[i1][i2]  = 0;
        39						ps[i1][i2] = new Shape();
        40						ps[i1][i2].graphics.beginFill(0xffffff);
        41						ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        42						ps[i1][i2].graphics.endFill();
        43						ps[i1][i2].x = p_wh * i2;
        44						ps[i1][i2].y = p_wh * i1;
        45						draw.addChild(ps[i1][i2]);
        46					}
        47				}
        48								// ピースの選択
        49				p_y           = 3;
        50				p_x           = 1;
        51				p[p_y][p_x]   = 2;
        52				p[p_y][p_x+1] = 3;
        53				piece();
        54			}
        55						//
        56						// ピースの描画
        57						//
        58			private function piece() : void
        59			{
        60				var i1 : int;
        61				var i2 : int;
        62	
        63				for (i1 = 0; i1 < row; i1++) {
        64					for (i2 = 0; i2 < col; i2++) {
        65						if (p[i1][i2] > 0) {
        66							switch (p[i1][i2]) {
        67								case 1:
        68									ps[i1][i2].graphics.beginFill(0xff0000);
        69									break;
        70								case 2:
        71									ps[i1][i2].graphics.beginFill(0xffd700);
        72									break;
        73								case 3:
        74									ps[i1][i2].graphics.beginFill(0x00ffff);
        75									break;
        76								case 4:
        77									ps[i1][i2].graphics.beginFill(0xadff2f);
        78									break;
        79							}
        80							ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        81							ps[i1][i2].graphics.endFill();
        82						}
        83					}
        84				}
        85			}
        86		}
        87	}
        					
        24 行目~ 30 行目

          実際のゲーム画面である白い矩形領域を追加している.

        32 行目~ 47 行目

          上の領域を 12 行 5 列の領域(ブロック)に分割し,各ブロックには,ピースに対応する Shape クラスのオブジェクト ps[i][j]( i = 0~11,j = 0~4 )を追加し,そこに 30 × 30 ピクセルの白い矩形を描いている(ピースが存在しない状態).なお,変数 p は,各ブロックに描く矩形の色を表し,0 はピースが存在しないことを意味している.

        49 行目~ 52 行目

          4 行 2 列,及び,4 行 3 列のピースの色を,各々,2( 0xffd700 ),及び,3( 0x00ffff )に設定し,描画するためのメソッド piece( 58 行目~ 85 行目)を呼んでいる.

        58 行目~ 85 行目

          描画するためのメソッドであり,変数 p に指定された色によって,各ブロックに矩形を描いている.

      2. ピースの落下:  先ほど表示したピースを,一定時間毎( この例では,500 ms )に落下させてみます.ENTER_FRAME イベント処理を利用して,ピースの位置を配列の 1 要素分だけ下に移動させています.前のステップで作成したプログラムを少し変更するだけですが,ENTER_FRAME イベントを利用したアニーションの機能を確認することができます.また,このプログラムでは,変数 game を false に設定することによって,ゲームオーバー画面も確認することができます.

        Game2.as

        001	package {
        002		import flash.display.Sprite;
        003		import flash.display.Shape;
        004		import flash.text.TextField;
        005		import flash.text.TextFieldType;
        006		import flash.text.TextFormat;
        007		import flash.text.TextLineMetrics;
        008		import flash.events.Event;
        009	
        010		[SWF(backgroundColor="0xeeffee", width="270", height="380", frameRate="2")]
        011	
        012		public class Game2 extends Sprite {
        013			private var draw : Sprite;   // ゲーム領域
        014			private var ps : Array;   // ピースの配置
        015			private var p : Array;   // ピースの色(0の時は存在しない)
        016			private var row : int = 12;   // 行の数
        017			private var col : int = 5;   // 列の数
        018			private var p_x : int;   // 動いているピースの位置(列)
        019			private var p_y : int;   // 動いているピースの位置(行)
        020			private var p_wh : int = 30;   // ピースの幅と高さ
        021			private var game : Boolean = true;   // ゲーム中か否か
        022						//
        023						// コンストラクタ
        024						//
        025			public function Game2() {
        026				var i1 : int;
        027				var i2 : int;
        028								// ゲーム領域
        029				draw   = new Sprite();
        030				draw.x = 10;
        031				draw.y = 10;
        032				draw.graphics.beginFill(0xffffff);
        033				draw.graphics.drawRect(0, 0, p_wh*col, p_wh*row);
        034				draw.graphics.endFill();
        035				addChild(draw);
        036								// ピースの配置
        037				p  = new Array(row);
        038				ps = new Array(row);
        039				for (i1 = 0; i1 < row; i1++) {
        040					p[i1]  = new Array(col);
        041					ps[i1] = new Array(col);
        042					for (i2 = 0; i2 < col; i2++) {
        043						p[i1][i2]  = 0;
        044						ps[i1][i2] = new Shape();
        045						ps[i1][i2].graphics.beginFill(0xffffff);
        046						ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        047						ps[i1][i2].graphics.endFill();
        048						ps[i1][i2].x = p_wh * i2;
        049						ps[i1][i2].y = p_wh * i1;
        050						draw.addChild(ps[i1][i2]);
        051					}
        052				}
        053								// ピースの選択
        054				p_y           = 3;
        055				p_x           = 1;
        056				p[p_y][p_x]   = 2;
        057				p[p_y][p_x+1] = 3;
        058				piece();
        059	
        060				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        061			}
        062						//
        063						// 一定時間毎の処理
        064						//
        065			private function onEnterFrame(event:Event):void
        066			{
        067				var i1 : int;
        068				var i2 : int;
        069								// ゲーム中
        070				if (game) {
        071										// ピースの落下
        072					if (p_y < row-1) {
        073						p[p_y+1][p_x]   = p[p_y][p_x];
        074						p[p_y+1][p_x+1] = p[p_y][p_x+1];
        075						p[p_y][p_x]     = 0;
        076						p[p_y][p_x+1]   = 0;
        077						ps[p_y][p_x].graphics.clear();
        078						ps[p_y][p_x+1].graphics.clear();
        079						p_y++;
        080						piece();
        081					}
        082				}
        083								// ゲームオーバー
        084				else {
        085					for (i1 = 0; i1 < row; i1++) {
        086						for (i2 = 0; i2 < col; i2++)
        087							ps[i1][i2].graphics.clear();
        088					}
        089					var tf : TextFormat = new TextFormat();
        090					tf.size = 50;
        091					tf.bold = true;
        092					var tx1 : TextField  = new TextField();
        093					tx1.text = "Game";
        094					tx1.setTextFormat(tf);
        095					var mt : TextLineMetrics = tx1.getLineMetrics(0);
        096					tx1.width  = mt.width + 5;
        097					tx1.height = mt.height + 5;
        098					tx1.x      = p_wh * 5 / 2 - tx1.width / 2;
        099					tx1.y      = p_wh * 6 - tx1.height;
        100					draw.addChild(tx1);
        101					var tx2 : TextField  = new TextField();
        102					tx2.text = "Over!";
        103					tx2.setTextFormat(tf);
        104					mt = tx2.getLineMetrics(0);
        105					tx2.width  = mt.width + 5;
        106					tx2.height = mt.height + 5;
        107					tx2.x      = p_wh * 5 / 2 - tx2.width / 2;
        108					tx2.y      = p_wh * 6;
        109					draw.addChild(tx2);
        110				}
        111			}
        112						//
        113						// ピースの描画
        114						//
        115			private function piece() : void
        116			{
        117				var i1 : int;
        118				var i2 : int;
        119	
        120				for (i1 = 0; i1 < row; i1++) {
        121					for (i2 = 0; i2 < col; i2++) {
        122						if (p[i1][i2] > 0) {
        123							switch (p[i1][i2]) {
        124								case 1:
        125									ps[i1][i2].graphics.beginFill(0xff0000);
        126									break;
        127								case 2:
        128									ps[i1][i2].graphics.beginFill(0xffd700);
        129									break;
        130								case 3:
        131									ps[i1][i2].graphics.beginFill(0x00ffff);
        132									break;
        133								case 4:
        134									ps[i1][i2].graphics.beginFill(0xadff2f);
        135									break;
        136							}
        137							ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        138							ps[i1][i2].graphics.endFill();
        139						}
        140					}
        141				}
        142			}
        143		}
        144	}
        					
        060 行目

          ENTER_FRAME イベントに対応するため,イベントリスナを追加している.この結果,イベントが発生すると,onEnterFrame メソッド( 065 行目~ 111 行目)が実行される.

        072 行目~ 081 行目

          ピースが落下中の処理であり,ピースが床に到達していない場合に実行される.
        • 073 行目~ 074 行目: 一つ下のピースの色を,現在位置のピース色に変更
        • 075 行目~ 076 行目: 現在位置のピース色を 0 に設定
        • 077 行目~ 078 行目: 現在ピースが存在するブロックのグラフィックスをクリア
        • 079 行目: 現在位置を変更
        • 080 行目: 再描画

        084 行目~ 110 行目

          ゲームオーバーになった場合に対する処理であり,すべてのブロックのグラフィックスをクリアし,画面中央に,「 Game Over! 」を表示している.この画面は,変数 game を false に変更することによって表示可能である.なお,TextLineMetrics クラスは,テキストの位置および行のプロパティに関する情報を保持するクラスである.

      3. ピースの生成と落下:  ピースを画面上部(水平位置はランダム)に発生させ,落下させます.ランダムな値を設定するために,Math クラスの random メソッドを使用しています.

        Game2.as

        001	package {
        002		import flash.display.Sprite;
        003		import flash.display.Shape;
        004		import flash.text.TextField;
        005		import flash.text.TextFieldType;
        006		import flash.text.TextFormat;
        007		import flash.text.TextLineMetrics;
        008		import flash.events.Event;
        009	
        010		[SWF(backgroundColor="0xeeffee", width="270", height="380", frameRate="2")]
        011	
        012		public class Game2 extends Sprite {
        013			private var draw : Sprite;   // ゲーム領域
        014			private var ps : Array;   // ピースの配置
        015			private var p : Array;   // ピースの色(0の時は存在しない)
        016			private var row : int = 12;   // 行の数
        017			private var col : int = 5;   // 列の数
        018			private var p_x : int;   // 動いているピースの位置(列)
        019			private var p_y : int;   // 動いているピースの位置(行)
        020			private var p_wh : int = 30;   // ピースの幅と高さ
        021			private var game : Boolean = true;   // ゲーム中か否か
        022						//
        023						// コンストラクタ
        024						//
        025			public function Game2() {
        026				var i1 : int;
        027				var i2 : int;
        028								// ゲーム領域
        029				draw   = new Sprite();
        030				draw.x = 10;
        031				draw.y = 10;
        032				draw.graphics.beginFill(0xffffff);
        033				draw.graphics.drawRect(0, 0, p_wh*col, p_wh*row);
        034				draw.graphics.endFill();
        035				addChild(draw);
        036								// ピースの配置
        037				p  = new Array(row);
        038				ps = new Array(row);
        039				for (i1 = 0; i1 < row; i1++) {
        040					p[i1]  = new Array(col);
        041					ps[i1] = new Array(col);
        042					for (i2 = 0; i2 < col; i2++) {
        043						p[i1][i2]  = 0;
        044						ps[i1][i2] = new Shape();
        045						ps[i1][i2].graphics.beginFill(0xffffff);
        046						ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        047						ps[i1][i2].graphics.endFill();
        048						ps[i1][i2].x = p_wh * i2;
        049						ps[i1][i2].y = p_wh * i1;
        050						draw.addChild(ps[i1][i2]);
        051					}
        052				}
        053								// ピースの選択
        054				select();
        055	
        056				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        057			}
        058						//
        059						// 一定時間毎の処理
        060						//
        061			private function onEnterFrame(event:Event):void
        062			{
        063				var i1 : int;
        064				var i2 : int;
        065								// ゲーム中
        066				if (game) {
        067										// ピースの落下
        068					if (p_y < row-1) {
        069						p[p_y+1][p_x]   = p[p_y][p_x];
        070						p[p_y+1][p_x+1] = p[p_y][p_x+1];
        071						p[p_y][p_x]     = 0;
        072						p[p_y][p_x+1]   = 0;
        073						ps[p_y][p_x].graphics.clear();
        074						ps[p_y][p_x+1].graphics.clear();
        075						p_y++;
        076						piece();
        077					}
        078					else
        079						select();
        080				}
        081								// ゲームオーバー
        082				else {
        083					for (i1 = 0; i1 < row; i1++) {
        084						for (i2 = 0; i2 < col; i2++)
        085							ps[i1][i2].graphics.clear();
        086					}
        087					var tf : TextFormat = new TextFormat();
        088					tf.size = 50;
        089					tf.bold = true;
        090					var tx1 : TextField  = new TextField();
        091					tx1.text = "Game";
        092					tx1.setTextFormat(tf);
        093					var mt : TextLineMetrics = tx1.getLineMetrics(0);
        094					tx1.width  = mt.width + 5;
        095					tx1.height = mt.height + 5;
        096					tx1.x      = p_wh * 5 / 2 - tx1.width / 2;
        097					tx1.y      = p_wh * 6 - tx1.height;
        098					draw.addChild(tx1);
        099					var tx2 : TextField  = new TextField();
        100					tx2.text = "Over!";
        101					tx2.setTextFormat(tf);
        102					mt = tx2.getLineMetrics(0);
        103					tx2.width  = mt.width + 5;
        104					tx2.height = mt.height + 5;
        105					tx2.x      = p_wh * 5 / 2 - tx2.width / 2;
        106					tx2.y      = p_wh * 6;
        107					draw.addChild(tx2);
        108				}
        109			}
        110						//
        111						// ピースの描画
        112						//
        113			private function piece() : void
        114			{
        115				var i1 : int;
        116				var i2 : int;
        117	
        118				for (i1 = 0; i1 < row; i1++) {
        119					for (i2 = 0; i2 < col; i2++) {
        120						if (p[i1][i2] > 0) {
        121							switch (p[i1][i2]) {
        122								case 1:
        123									ps[i1][i2].graphics.beginFill(0xff0000);
        124									break;
        125								case 2:
        126									ps[i1][i2].graphics.beginFill(0xffd700);
        127									break;
        128								case 3:
        129									ps[i1][i2].graphics.beginFill(0x00ffff);
        130									break;
        131								case 4:
        132									ps[i1][i2].graphics.beginFill(0xadff2f);
        133									break;
        134							}
        135							ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        136							ps[i1][i2].graphics.endFill();
        137						}
        138					}
        139				}
        140			}
        141						//
        142						// ピースの選択
        143						//
        144			private function select() : void
        145			{
        146				var color : int;
        147	
        148				p_y = 0;
        149				p_x = (int)(Math.random() * (col - 1));
        150				if (p_x > col-2)
        151					p_x = col - 2;
        152	
        153				color = (int)(Math.random() * 4) + 1;
        154				if (color > 4)
        155					color = 4;
        156				p[0][p_x] = color;
        157				color = (int)(Math.random() * 4) + 1;
        158				if (color > 4)
        159					color = 4;
        160				p[0][p_x+1] = color;
        161	
        162				piece();
        163			}
        164		}
        165	}
        					
        054 行目

          ピースの初期位置や色をランダムに選択するメソッド select( 144 行目~ 163 行目)を呼んでいる.

        068 行目~ 077 行目

          ピースが落下中の処理であり,ピースが床に到達していない場合に実行される.

        078 行目~ 079 行目

          ピースが床に到達した場合は,次のピースを選択するために,メソッド select( 144 行目~ 163 行目)を呼んでいる.

        149 行目~ 151 行目

          ピースの初期位置(水平方向)をランダムに選択

        153 行目~ 160 行目

          2 つのピースの色をランダムに選択

      4. キーイベント:  キーイベントに対する処理を追加します.移動や回転を行う場合は,移動や回転が可能か否かのチェックが必要となります.変数 rot の値が 0 の時は横並び,1 の時は縦並びであることを意味します.当然,rot の値によって,一番下に到着したか否かのチェック方法も異なってきますので,ピースの落下を制御する部分も変更する必要があります.また,一番下に到着すると,変数 ok を false に設定し,キーイベントを受け付けないようにしています.

        Game2.as

        001	package {
        002		import flash.display.Sprite;
        003		import flash.display.Shape;
        004		import flash.text.TextField;
        005		import flash.text.TextFieldType;
        006		import flash.text.TextFormat;
        007		import flash.text.TextLineMetrics;
        008		import flash.events.Event;
        009		import flash.events.KeyboardEvent;
        010	
        011		[SWF(backgroundColor="0xeeffee", width="270", height="380", frameRate="2")]
        012	
        013		public class Game2 extends Sprite {
        014			private var draw : Sprite;   // ゲーム領域
        015			private var ps : Array;   // ピースの配置
        016			private var p : Array;   // ピースの色(0の時は存在しない)
        017			private var row : int = 12;   // 行の数
        018			private var col : int = 5;   // 列の数
        019			private var p_x : int;   // 動いているピースの位置(列)
        020			private var p_y : int;   // 動いているピースの位置(行)
        021			private var p_wh : int = 30;   // ピースの幅と高さ
        022			private var rot : int = 0;   // 横か縦か(0:横,1:縦)
        023			private var game : Boolean = true;   // ゲーム中か否か
        024			private var ok : Boolean = true;   // キーイベントを受け付けるか否か
        025						//
        026						// コンストラクタ
        027						//
        028			public function Game2() {
        029				var i1 : int;
        030				var i2 : int;
        031								// ゲーム領域
        032				draw   = new Sprite();
        033				draw.x = 10;
        034				draw.y = 10;
        035				draw.graphics.beginFill(0xffffff);
        036				draw.graphics.drawRect(0, 0, p_wh*col, p_wh*row);
        037				draw.graphics.endFill();
        038				addChild(draw);
        039								// ピースの配置
        040				p  = new Array(row);
        041				ps = new Array(row);
        042				for (i1 = 0; i1 < row; i1++) {
        043					p[i1]  = new Array(col);
        044					ps[i1] = new Array(col);
        045					for (i2 = 0; i2 < col; i2++) {
        046						p[i1][i2]  = 0;
        047						ps[i1][i2] = new Shape();
        048						ps[i1][i2].graphics.beginFill(0xffffff);
        049						ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        050						ps[i1][i2].graphics.endFill();
        051						ps[i1][i2].x = p_wh * i2;
        052						ps[i1][i2].y = p_wh * i1;
        053						draw.addChild(ps[i1][i2]);
        054					}
        055				}
        056								// ピースの選択
        057				select();
        058	
        059				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        060				stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        061			}
        062						//
        063						// 一定時間毎の処理
        064						//
        065			private function onEnterFrame(event:Event):void
        066			{
        067				var i1 : int;
        068				var i2 : int;
        069				var ct : int;
        070								// ゲーム中
        071				if (game) {
        072										// ピースの落下
        073					ct = 0;
        074												// 横並び
        075					if (rot == 0) {
        076						if (p_y < row-1) {
        077							ct              = 1;
        078							p[p_y+1][p_x]   = p[p_y][p_x];
        079							p[p_y+1][p_x+1] = p[p_y][p_x+1];
        080							p[p_y][p_x]     = 0;
        081							p[p_y][p_x+1]   = 0;
        082							ps[p_y][p_x].graphics.clear();
        083							ps[p_y][p_x+1].graphics.clear();
        084							p_y++;
        085							piece();
        086						}
        087						else
        088							ok = false;
        089					}
        090												// 縦並び
        091					else {
        092						if (p_y < row-2) {
        093							ct            = 1;
        094							p[p_y+2][p_x] = p[p_y+1][p_x];
        095							p[p_y+1][p_x] = p[p_y][p_x];
        096							p[p_y][p_x]   = 0;
        097							ps[p_y][p_x].graphics.clear();
        098							p_y++;
        099							piece();
        100						}
        101						else
        102							ok = false;
        103					}
        104										// 消去と次のピース
        105					if (ct == 0)
        106						select();
        107				}
        108								// ゲームオーバー
        109				else {
        110					for (i1 = 0; i1 < row; i1++) {
        111						for (i2 = 0; i2 < col; i2++)
        112							ps[i1][i2].graphics.clear();
        113					}
        114					var tf : TextFormat = new TextFormat();
        115					tf.size = 50;
        116					tf.bold = true;
        117					var tx1 : TextField  = new TextField();
        118					tx1.text = "Game";
        119					tx1.setTextFormat(tf);
        120					var mt : TextLineMetrics = tx1.getLineMetrics(0);
        121					tx1.width  = mt.width + 5;
        122					tx1.height = mt.height + 5;
        123					tx1.x      = p_wh * 5 / 2 - tx1.width / 2;
        124					tx1.y      = p_wh * 6 - tx1.height;
        125					draw.addChild(tx1);
        126					var tx2 : TextField  = new TextField();
        127					tx2.text = "Over!";
        128					tx2.setTextFormat(tf);
        129					mt = tx2.getLineMetrics(0);
        130					tx2.width  = mt.width + 5;
        131					tx2.height = mt.height + 5;
        132					tx2.x      = p_wh * 5 / 2 - tx2.width / 2;
        133					tx2.y      = p_wh * 6;
        134					draw.addChild(tx2);
        135				}
        136			}
        137						//
        138						// キーが押されたときの処理
        139						//
        140			private function onKeyDown(e:KeyboardEvent):void {
        141				var k : int;
        142				if (ok) {
        143					if (e.keyCode == 37) {   // 左矢印(左移動)
        144						if (p_x > 0) {
        145							if (rot == 0 && p[p_y][p_x-1] == 0) {
        146								p[p_y][p_x-1] = p[p_y][p_x];
        147								p[p_y][p_x]   = p[p_y][p_x+1];
        148								p[p_y][p_x+1] = 0;
        149								ps[p_y][p_x+1].graphics.clear();
        150								p_x--;
        151								piece();
        152							}
        153							else if (p[p_y][p_x-1] == 0 && p[p_y+1][p_x-1] == 0) {
        154								p[p_y][p_x-1]   = p[p_y][p_x];
        155								p[p_y+1][p_x-1] = p[p_y+1][p_x];
        156								p[p_y][p_x]     = 0;
        157								p[p_y+1][p_x]   = 0;
        158								ps[p_y][p_x].graphics.clear();
        159								ps[p_y+1][p_x].graphics.clear();
        160								p_x--;
        161								piece();
        162							}
        163						}
        164					}
        165					else if (e.keyCode == 39) {   // 右矢印(右移動)
        166						if (rot == 0) {
        167							if (p_x < col-2 && p[p_y][p_x+2] == 0) {
        168								p[p_y][p_x+2] = p[p_y][p_x+1];
        169								p[p_y][p_x+1] = p[p_y][p_x];
        170								p[p_y][p_x]   = 0;
        171								ps[p_y][p_x].graphics.clear();
        172								p_x++;
        173								piece();
        174							}
        175						}
        176						else {
        177							if (p_x < col-1 && p[p_y][p_x+1] == 0 && p[p_y+1][p_x+1] == 0) {
        178								p[p_y][p_x+1]   = p[p_y][p_x];
        179								p[p_y+1][p_x+1] = p[p_y+1][p_x];
        180								p[p_y][p_x]     = 0;
        181								p[p_y+1][p_x]   = 0;
        182								ps[p_y][p_x].graphics.clear();
        183								ps[p_y+1][p_x].graphics.clear();
        184								p_x++;
        185								piece();
        186							}
        187						}
        188					}
        189					else if (e.keyCode == 38) {   // 上矢印(上下または左右入れ替え)
        190						if (rot == 0) {
        191							k             = p[p_y][p_x];
        192							p[p_y][p_x]   = p[p_y][p_x+1];
        193							p[p_y][p_x+1] = k;
        194						}
        195						else {
        196							k             = p[p_y][p_x];
        197							p[p_y][p_x]   = p[p_y+1][p_x];
        198							p[p_y+1][p_x] = k;
        199						}
        200						piece();
        201					}
        202					else if (e.keyCode == 40) {   // 下矢印(90度または-90度回転)
        203						if (rot == 0 && p[p_y+1][p_x] == 0) {
        204							if (p_y < row-1) {
        205								p[p_y+1][p_x] = p[p_y][p_x+1];
        206								p[p_y][p_x+1] = 0;
        207								ps[p_y][p_x+1].graphics.clear();
        208								rot = 1;
        209								piece();
        210							}
        211						}
        212						else {
        213							if (p_x < col-1 && p[p_y][p_x+1] == 0) {
        214								p[p_y][p_x+1] = p[p_y+1][p_x];
        215								p[p_y+1][p_x] = 0;
        216								ps[p_y+1][p_x].graphics.clear();
        217								rot = 0;
        218								piece();
        219							}
        220						}
        221					}
        222				}
        223			}
        224						//
        225						// ピースの描画
        226						//
        227			private function piece() : void
        228			{
        229				var i1 : int;
        230				var i2 : int;
        231	
        232				for (i1 = 0; i1 < row; i1++) {
        233					for (i2 = 0; i2 < col; i2++) {
        234						if (p[i1][i2] > 0) {
        235							switch (p[i1][i2]) {
        236								case 1:
        237									ps[i1][i2].graphics.beginFill(0xff0000);
        238									break;
        239								case 2:
        240									ps[i1][i2].graphics.beginFill(0xffd700);
        241									break;
        242								case 3:
        243									ps[i1][i2].graphics.beginFill(0x00ffff);
        244									break;
        245								case 4:
        246									ps[i1][i2].graphics.beginFill(0xadff2f);
        247									break;
        248							}
        249							ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        250							ps[i1][i2].graphics.endFill();
        251						}
        252					}
        253				}
        254			}
        255						//
        256						// ピースの選択
        257						//
        258			private function select() : void
        259			{
        260				var color : int;
        261	
        262				ok  = true;
        263				rot = 0;
        264				p_y = 0;
        265				p_x = (int)(Math.random() * (col - 1));
        266				if (p_x > col-2)
        267					p_x = col - 2;
        268	
        269				color = (int)(Math.random() * 4) + 1;
        270				if (color > 4)
        271					color = 4;
        272				p[0][p_x] = color;
        273				color = (int)(Math.random() * 4) + 1;
        274				if (color > 4)
        275					color = 4;
        276				p[0][p_x+1] = color;
        277	
        278				piece();
        279			}
        280		}
        281	}
        					
        060 行目

          KEY_DOWN イベント(キーが押された場合)に対応するため,ステージにイベントリスナを追加している.この結果,イベントが発生すると,onKeyDown メソッド( 140 行目~ 223 行目)が実行される.

        091 行目~ 103 行目

          ピースが縦並びの場合の落下処理.横並びの場合も同様であるが,最下段に到達したときは,キーイベントを受け付けないようにしている( 102 行目)

        145 行目~ 152 行目

          左矢印キーが押され,ピースが横並びであった場合の処理である.左側に他のピースが存在しない場合は,左側に移動する.

        153 行目~ 162 行目

          左矢印キーが押され,ピースが縦並びであった場合の処理である.左側に他のピースが存在しない場合は,左側に移動する.

        165 行目~ 188 行目

          右矢印キーによって右移動するための処理である.左矢印キーが押された場合と同様の処理を行っている.

        189 行目~ 201 行目

          上矢印キーが押された場合の処理であり,上下,または,左右の色を入れ替えている.

        202 行目~ 221 行目

          下矢印キーが押された場合の処理であり,回転可能な場合は,回転させる処理を行っている.

      5. ピースの積み上げ:  このままでは,ピースが積み上がっていきません.落下しているピースが,他のピースの上に乗ったらそこで止めるための処理が必要になります.特に,横並びの場合,一つのピースだけが他のピースの上に乗った場合,キーイベントの処理を受け付けないようにした後(変数 ok を false ),乗っていないピースだけを落下させる処理が必要になる点に注意して下さい.また,上まで積み上がるとゲームオーバーになる処理も追加しています.

        Game2.as

        001	package {
        002		import flash.display.Sprite;
        003		import flash.display.Shape;
        004		import flash.text.TextField;
        005		import flash.text.TextFieldType;
        006		import flash.text.TextFormat;
        007		import flash.text.TextLineMetrics;
        008		import flash.events.Event;
        009		import flash.events.KeyboardEvent;
        010	
        011		[SWF(backgroundColor="0xeeffee", width="270", height="380", frameRate="2")]
        012	
        013		public class Game2 extends Sprite {
        014			private var draw : Sprite;   // ゲーム領域
        015			private var ps : Array;   // ピースの配置
        016			private var p : Array;   // ピースの色(0の時は存在しない)
        017			private var row : int = 12;   // 行の数
        018			private var col : int = 5;   // 列の数
        019			private var p_x : int;   // 動いているピースの位置(列)
        020			private var p_y : int;   // 動いているピースの位置(行)
        021			private var p_wh : int = 30;   // ピースの幅と高さ
        022			private var rot : int = 0;   // 横か縦か(0:横,1:縦)
        023			private var game : Boolean = true;   // ゲーム中か否か
        024			private var ok : Boolean = true;   // キーイベントを受け付けるか否か
        025						//
        026						// コンストラクタ
        027						//
        028			public function Game2() {
        029				var i1 : int;
        030				var i2 : int;
        031								// ゲーム領域
        032				draw   = new Sprite();
        033				draw.x = 10;
        034				draw.y = 10;
        035				draw.graphics.beginFill(0xffffff);
        036				draw.graphics.drawRect(0, 0, p_wh*col, p_wh*row);
        037				draw.graphics.endFill();
        038				addChild(draw);
        039								// ピースの配置
        040				p  = new Array(row);
        041				ps = new Array(row);
        042				for (i1 = 0; i1 < row; i1++) {
        043					p[i1]  = new Array(col);
        044					ps[i1] = new Array(col);
        045					for (i2 = 0; i2 < col; i2++) {
        046						p[i1][i2]  = 0;
        047						ps[i1][i2] = new Shape();
        048						ps[i1][i2].graphics.beginFill(0xffffff);
        049						ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        050						ps[i1][i2].graphics.endFill();
        051						ps[i1][i2].x = p_wh * i2;
        052						ps[i1][i2].y = p_wh * i1;
        053						draw.addChild(ps[i1][i2]);
        054					}
        055				}
        056								// ピースの選択
        057				select();
        058	
        059				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        060				stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        061			}
        062						//
        063						// 一定時間毎の処理
        064						//
        065			private function onEnterFrame(event:Event):void
        066			{
        067				var i1 : int;
        068				var i2 : int;
        069				var ct : int;
        070								// ゲーム中
        071				if (game) {
        072										// ピースの落下
        073					ct = 0;
        074												// 横並び
        075					if (rot == 0) {
        076						if (p_y < row-1) {
        077							if (ok) {
        078														// 分離しない
        079								if (p[p_y+1][p_x] == 0 && p[p_y+1][p_x+1] == 0) {
        080									ct              = 1;
        081									p[p_y+1][p_x]   = p[p_y][p_x];
        082									p[p_y+1][p_x+1] = p[p_y][p_x+1];
        083									p[p_y][p_x]     = 0;
        084									p[p_y][p_x+1]   = 0;
        085									ps[p_y][p_x].graphics.clear();
        086									ps[p_y][p_x+1].graphics.clear();
        087									p_y++;
        088									piece();
        089								}
        090														// 分離
        091								else {
        092									ok = false;
        093									if (p[p_y+1][p_x] == 0) {
        094										ct            = 1;
        095										p[p_y+1][p_x] = p[p_y][p_x];
        096										p[p_y][p_x]   = 0;
        097										ps[p_y][p_x].graphics.clear();
        098										p_y++;
        099										piece();
        100									}
        101									else if (p[p_y+1][p_x+1] == 0) {
        102										ct              = 1;
        103										p[p_y+1][p_x+1] = p[p_y][p_x+1];
        104										p[p_y][p_x+1]   = 0;
        105										ps[p_y][p_x+1].graphics.clear();
        106										p_x++;
        107										p_y++;
        108										piece();
        109									}
        110								}
        111							}
        112							else {
        113								if (p[p_y+1][p_x] == 0) {
        114									ct            = 1;
        115									p[p_y+1][p_x] = p[p_y][p_x];
        116									p[p_y][p_x]   = 0;
        117									ps[p_y][p_x].graphics.clear();
        118									p_y++;
        119									piece();
        120								}
        121							}
        122						}
        123						else
        124							ok = false;
        125					}
        126												// 縦並び
        127					else {
        128						if (p_y < row-2 && p[p_y+2][p_x] == 0) {
        129							ct            = 1;
        130							p[p_y+2][p_x] = p[p_y+1][p_x];
        131							p[p_y+1][p_x] = p[p_y][p_x];
        132							p[p_y][p_x]   = 0;
        133							ps[p_y][p_x].graphics.clear();
        134							p_y++;
        135							piece();
        136						}
        137						else
        138							ok = false;
        139					}
        140										// 消去と次のピース
        141					if (ct == 0)
        142						select();
        143				}
        144								// ゲームオーバー
        145				else {
        146					for (i1 = 0; i1 < row; i1++) {
        147						for (i2 = 0; i2 < col; i2++)
        148							ps[i1][i2].graphics.clear();
        149					}
        150					var tf : TextFormat = new TextFormat();
        151					tf.size = 50;
        152					tf.bold = true;
        153					var tx1 : TextField  = new TextField();
        154					tx1.text = "Game";
        155					tx1.setTextFormat(tf);
        156					var mt : TextLineMetrics = tx1.getLineMetrics(0);
        157					tx1.width  = mt.width + 5;
        158					tx1.height = mt.height + 5;
        159					tx1.x      = p_wh * 5 / 2 - tx1.width / 2;
        160					tx1.y      = p_wh * 6 - tx1.height;
        161					draw.addChild(tx1);
        162					var tx2 : TextField  = new TextField();
        163					tx2.text = "Over!";
        164					tx2.setTextFormat(tf);
        165					mt = tx2.getLineMetrics(0);
        166					tx2.width  = mt.width + 5;
        167					tx2.height = mt.height + 5;
        168					tx2.x      = p_wh * 5 / 2 - tx2.width / 2;
        169					tx2.y      = p_wh * 6;
        170					draw.addChild(tx2);
        171				}
        172			}
        173						//
        174						// キーが押されたときの処理
        175						//
        176			private function onKeyDown(e:KeyboardEvent):void {
        177				var k : int;
        178				if (ok) {
        179					if (e.keyCode == 37) {   // 左矢印(左移動)
        180						if (p_x > 0) {
        181							if (rot == 0 && p[p_y][p_x-1] == 0) {
        182								p[p_y][p_x-1] = p[p_y][p_x];
        183								p[p_y][p_x]   = p[p_y][p_x+1];
        184								p[p_y][p_x+1] = 0;
        185								ps[p_y][p_x+1].graphics.clear();
        186								p_x--;
        187								piece();
        188							}
        189							else if (p[p_y][p_x-1] == 0 && p[p_y+1][p_x-1] == 0) {
        190								p[p_y][p_x-1]   = p[p_y][p_x];
        191								p[p_y+1][p_x-1] = p[p_y+1][p_x];
        192								p[p_y][p_x]     = 0;
        193								p[p_y+1][p_x]   = 0;
        194								ps[p_y][p_x].graphics.clear();
        195								ps[p_y+1][p_x].graphics.clear();
        196								p_x--;
        197								piece();
        198							}
        199						}
        200					}
        201					else if (e.keyCode == 39) {   // 右矢印(右移動)
        202						if (rot == 0) {
        203							if (p_x < col-2 && p[p_y][p_x+2] == 0) {
        204								p[p_y][p_x+2] = p[p_y][p_x+1];
        205								p[p_y][p_x+1] = p[p_y][p_x];
        206								p[p_y][p_x]   = 0;
        207								ps[p_y][p_x].graphics.clear();
        208								p_x++;
        209								piece();
        210							}
        211						}
        212						else {
        213							if (p_x < col-1 && p[p_y][p_x+1] == 0 && p[p_y+1][p_x+1] == 0) {
        214								p[p_y][p_x+1]   = p[p_y][p_x];
        215								p[p_y+1][p_x+1] = p[p_y+1][p_x];
        216								p[p_y][p_x]     = 0;
        217								p[p_y+1][p_x]   = 0;
        218								ps[p_y][p_x].graphics.clear();
        219								ps[p_y+1][p_x].graphics.clear();
        220								p_x++;
        221								piece();
        222							}
        223						}
        224					}
        225					else if (e.keyCode == 38) {   // 上矢印(上下または左右入れ替え)
        226						if (rot == 0) {
        227							k             = p[p_y][p_x];
        228							p[p_y][p_x]   = p[p_y][p_x+1];
        229							p[p_y][p_x+1] = k;
        230						}
        231						else {
        232							k             = p[p_y][p_x];
        233							p[p_y][p_x]   = p[p_y+1][p_x];
        234							p[p_y+1][p_x] = k;
        235						}
        236						piece();
        237					}
        238					else if (e.keyCode == 40) {   // 下矢印(90度または-90度回転)
        239						if (rot == 0 && p[p_y+1][p_x] == 0) {
        240							if (p_y < row-1) {
        241								p[p_y+1][p_x] = p[p_y][p_x+1];
        242								p[p_y][p_x+1] = 0;
        243								ps[p_y][p_x+1].graphics.clear();
        244								rot = 1;
        245								piece();
        246							}
        247						}
        248						else {
        249							if (p_x < col-1 && p[p_y][p_x+1] == 0) {
        250								p[p_y][p_x+1] = p[p_y+1][p_x];
        251								p[p_y+1][p_x] = 0;
        252								ps[p_y+1][p_x].graphics.clear();
        253								rot = 0;
        254								piece();
        255							}
        256						}
        257					}
        258				}
        259			}
        260						//
        261						// ピースの描画
        262						//
        263			private function piece() : void
        264			{
        265				var i1 : int;
        266				var i2 : int;
        267	
        268				for (i1 = 0; i1 < row; i1++) {
        269					for (i2 = 0; i2 < col; i2++) {
        270						if (p[i1][i2] > 0) {
        271							switch (p[i1][i2]) {
        272								case 1:
        273									ps[i1][i2].graphics.beginFill(0xff0000);
        274									break;
        275								case 2:
        276									ps[i1][i2].graphics.beginFill(0xffd700);
        277									break;
        278								case 3:
        279									ps[i1][i2].graphics.beginFill(0x00ffff);
        280									break;
        281								case 4:
        282									ps[i1][i2].graphics.beginFill(0xadff2f);
        283									break;
        284							}
        285							ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        286							ps[i1][i2].graphics.endFill();
        287						}
        288					}
        289				}
        290			}
        291						//
        292						// ピースの選択
        293						//
        294			private function select() : void
        295			{
        296				var color : int;
        297	
        298				ok  = true;
        299				rot = 0;
        300				p_y = 0;
        301				p_x = (int)(Math.random() * (col - 1));
        302				if (p_x > col-2)
        303					p_x = col - 2;
        304	
        305				if (p[0][p_x] == 0 && p[0][p_x+1] ==0 ) {
        306					color = (int)(Math.random() * 4) + 1;
        307					if (color > 4)
        308						color = 4;
        309					p[0][p_x] = color;
        310					color = (int)(Math.random() * 4) + 1;
        311					if (color > 4)
        312						color = 4;
        313					p[0][p_x+1] = color;
        314				}
        315				else
        316					game = false;
        317	
        318				piece();
        319			}
        320		}
        321	}
        					
        079 行目~ 089 行目

          ピースが横並びで,かつ,2 つのピースが同時に落下する場合の処理である.

        092 行目

          093 行目~ 109 行目は,左右いずれかのピースが他のピースの上に乗った場合の処理である.ここでは,変数 ok を false に設定し,イベントを受け付けないようにしている.従って,ok が false であることは,ピースが最下段に到達するか,または,横並びの 2 つのピースが分離し,1 つのピースだけが落下している状態であることを意味する.

        093 行目~ 100 行目

          右側のピースが他のピースの上に乗り,左側のピースだけが落下する状態を開始する処理である.

        101 行目~ 109 行目

          上と同様,左側のピースが他のピースの上に乗り,右側のピースだけが落下する状態を開始する処理である.

        113 行目~ 120 行目

          1 つのピースだけが落下している場合に対する処理である.

        127 行目~ 139 行目

          ピースが縦に並んでいる場合に対する落下処理である.

        305 行目,315 行目~ 316 行目

          ピースを生成した位置に,他のピースが存在した場合は,ゲームオーバーにしている..

      6. ピースの削除:  最後に行わなければならないのがピースの削除です.同じ色のピースが縦横 4 個以上並んだ場合,それらを削除し,それらの上に乗っていたピースを可能なところまで落下させます.メソッド search で同じ色のピースを数え,メソッド delete で削除しています.

        Game2.as

        001	package {
        002		import flash.display.Sprite;
        003		import flash.display.Shape;
        004		import flash.text.TextField;
        005		import flash.text.TextFieldType;
        006		import flash.text.TextFormat;
        007		import flash.text.TextLineMetrics;
        008		import flash.events.Event;
        009		import flash.events.KeyboardEvent;
        010	
        011		[SWF(backgroundColor="0xeeffee", width="270", height="380", frameRate="2")]
        012	
        013		public class Game2 extends Sprite {
        014			private var draw : Sprite;   // ゲーム領域
        015			private var ps : Array;   // ピースの配置
        016			private var p : Array;   // ピースの色(0の時は存在しない)
        017			private var pp : Array;   // ピースの色(作業域)
        018			private var row : int = 12;   // 行の数
        019			private var col : int = 5;   // 列の数
        020			private var p_x : int;   // 動いているピースの位置(列)
        021			private var p_y : int;   // 動いているピースの位置(行)
        022			private var p_wh : int = 30;   // ピースの幅と高さ
        023			private var rot : int = 0;   // 横か縦か(0:横,1:縦)
        024			private var game : Boolean = true;   // ゲーム中か否か
        025			private var ok : Boolean = true;   // キーイベントを受け付けるか否か
        026						//
        027						// コンストラクタ
        028						//
        029			public function Game2() {
        030				var i1 : int;
        031				var i2 : int;
        032								// ゲーム領域
        033				draw   = new Sprite();
        034				draw.x = 10;
        035				draw.y = 10;
        036				draw.graphics.beginFill(0xffffff);
        037				draw.graphics.drawRect(0, 0, p_wh*col, p_wh*row);
        038				draw.graphics.endFill();
        039				addChild(draw);
        040								// ピースの配置
        041				p  = new Array(row);
        042				pp = new Array(row);
        043				ps = new Array(row);
        044				for (i1 = 0; i1 < row; i1++) {
        045					p[i1]  = new Array(col);
        046					pp[i1] = new Array(col);
        047					ps[i1] = new Array(col);
        048					for (i2 = 0; i2 < col; i2++) {
        049						p[i1][i2]  = 0;
        050						pp[i1][i2] = 0;
        051						ps[i1][i2] = new Shape();
        052						ps[i1][i2].graphics.beginFill(0xffffff);
        053						ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        054						ps[i1][i2].graphics.endFill();
        055						ps[i1][i2].x = p_wh * i2;
        056						ps[i1][i2].y = p_wh * i1;
        057						draw.addChild(ps[i1][i2]);
        058					}
        059				}
        060								// ピースの選択
        061				select();
        062	
        063				addEventListener(Event.ENTER_FRAME, onEnterFrame);
        064				stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        065			}
        066						//
        067						// 一定時間毎の処理
        068						//
        069			private function onEnterFrame(event:Event):void
        070			{
        071				var i1 : int;
        072				var i2 : int;
        073				var i3 : int;
        074				var i4 : int;
        075				var ct : int;
        076								// ゲーム中
        077				if (game) {
        078										// ピースの落下
        079					ct = 0;
        080												// 横並び
        081					if (rot == 0) {
        082						if (p_y < row-1) {
        083							if (ok) {
        084														// 分離しない
        085								if (p[p_y+1][p_x] == 0 && p[p_y+1][p_x+1] == 0) {
        086									ct              = 1;
        087									p[p_y+1][p_x]   = p[p_y][p_x];
        088									p[p_y+1][p_x+1] = p[p_y][p_x+1];
        089									p[p_y][p_x]     = 0;
        090									p[p_y][p_x+1]   = 0;
        091									ps[p_y][p_x].graphics.clear();
        092									ps[p_y][p_x+1].graphics.clear();
        093									p_y++;
        094									piece();
        095								}
        096														// 分離
        097								else {
        098									ok = false;
        099									if (p[p_y+1][p_x] == 0) {
        100										ct            = 1;
        101										p[p_y+1][p_x] = p[p_y][p_x];
        102										p[p_y][p_x]   = 0;
        103										ps[p_y][p_x].graphics.clear();
        104										p_y++;
        105										piece();
        106									}
        107									else if (p[p_y+1][p_x+1] == 0) {
        108										ct              = 1;
        109										p[p_y+1][p_x+1] = p[p_y][p_x+1];
        110										p[p_y][p_x+1]   = 0;
        111										ps[p_y][p_x+1].graphics.clear();
        112										p_x++;
        113										p_y++;
        114										piece();
        115									}
        116								}
        117							}
        118							else {
        119								if (p[p_y+1][p_x] == 0) {
        120									ct            = 1;
        121									p[p_y+1][p_x] = p[p_y][p_x];
        122									p[p_y][p_x]   = 0;
        123									ps[p_y][p_x].graphics.clear();
        124									p_y++;
        125									piece();
        126								}
        127							}
        128						}
        129						else
        130							ok = false;
        131					}
        132												// 縦並び
        133					else {
        134						if (p_y < row-2 && p[p_y+2][p_x] == 0) {
        135							ct            = 1;
        136							p[p_y+2][p_x] = p[p_y+1][p_x];
        137							p[p_y+1][p_x] = p[p_y][p_x];
        138							p[p_y][p_x]   = 0;
        139							ps[p_y][p_x].graphics.clear();
        140							p_y++;
        141							piece();
        142						}
        143						else
        144							ok = false;
        145					}
        146										// 消去と次のピース
        147					if (ct == 0) {
        148						ct = 4;
        149						while (ct >= 4) {
        150							ct = 0;
        151							for (i1 = row-1; i1 >= 0 && ct < 4; i1--) {
        152								for (i2 = 0; i2 < col && ct < 4; i2++) {
        153									for (i3 = 0; i3 < row; i3++) {
        154										for (i4 = 0; i4 < col; i4++)
        155											pp[i3][i4] = 0;
        156									}
        157									if (p[i1][i2] > 0) {
        158										pp[i1][i2] = 1;
        159										ct         = search(i1, i2, 1);
        160									}
        161								}
        162							}
        163							if (ct >= 4)
        164								p_delete();
        165						}
        166						piece();
        167						select();
        168					}
        169				}
        170								// ゲームオーバー
        171				else {
        172					for (i1 = 0; i1 < row; i1++) {
        173						for (i2 = 0; i2 < col; i2++)
        174							ps[i1][i2].graphics.clear();
        175					}
        176					var tf : TextFormat = new TextFormat();
        177					tf.size = 50;
        178					tf.bold = true;
        179					var tx1 : TextField  = new TextField();
        180					tx1.text = "Game";
        181					tx1.setTextFormat(tf);
        182					var mt : TextLineMetrics = tx1.getLineMetrics(0);
        183					tx1.width  = mt.width + 5;
        184					tx1.height = mt.height + 5;
        185					tx1.x      = p_wh * 5 / 2 - tx1.width / 2;
        186					tx1.y      = p_wh * 6 - tx1.height;
        187					draw.addChild(tx1);
        188					var tx2 : TextField  = new TextField();
        189					tx2.text = "Over!";
        190					tx2.setTextFormat(tf);
        191					mt = tx2.getLineMetrics(0);
        192					tx2.width  = mt.width + 5;
        193					tx2.height = mt.height + 5;
        194					tx2.x      = p_wh * 5 / 2 - tx2.width / 2;
        195					tx2.y      = p_wh * 6;
        196					draw.addChild(tx2);
        197				}
        198			}
        199						//
        200						// キーが押されたときの処理
        201						//
        202			private function onKeyDown(e:KeyboardEvent):void {
        203				var k : int;
        204				if (ok) {
        205					if (e.keyCode == 37) {   // 左矢印(左移動)
        206						if (p_x > 0) {
        207							if (rot == 0 && p[p_y][p_x-1] == 0) {
        208								p[p_y][p_x-1] = p[p_y][p_x];
        209								p[p_y][p_x]   = p[p_y][p_x+1];
        210								p[p_y][p_x+1] = 0;
        211								ps[p_y][p_x+1].graphics.clear();
        212								p_x--;
        213								piece();
        214							}
        215							else if (p[p_y][p_x-1] == 0 && p[p_y+1][p_x-1] == 0) {
        216								p[p_y][p_x-1]   = p[p_y][p_x];
        217								p[p_y+1][p_x-1] = p[p_y+1][p_x];
        218								p[p_y][p_x]     = 0;
        219								p[p_y+1][p_x]   = 0;
        220								ps[p_y][p_x].graphics.clear();
        221								ps[p_y+1][p_x].graphics.clear();
        222								p_x--;
        223								piece();
        224							}
        225						}
        226					}
        227					else if (e.keyCode == 39) {   // 右矢印(右移動)
        228						if (rot == 0) {
        229							if (p_x < col-2 && p[p_y][p_x+2] == 0) {
        230								p[p_y][p_x+2] = p[p_y][p_x+1];
        231								p[p_y][p_x+1] = p[p_y][p_x];
        232								p[p_y][p_x]   = 0;
        233								ps[p_y][p_x].graphics.clear();
        234								p_x++;
        235								piece();
        236							}
        237						}
        238						else {
        239							if (p_x < col-1 && p[p_y][p_x+1] == 0 && p[p_y+1][p_x+1] == 0) {
        240								p[p_y][p_x+1]   = p[p_y][p_x];
        241								p[p_y+1][p_x+1] = p[p_y+1][p_x];
        242								p[p_y][p_x]     = 0;
        243								p[p_y+1][p_x]   = 0;
        244								ps[p_y][p_x].graphics.clear();
        245								ps[p_y+1][p_x].graphics.clear();
        246								p_x++;
        247								piece();
        248							}
        249						}
        250					}
        251					else if (e.keyCode == 38) {   // 上矢印(上下または左右入れ替え)
        252						if (rot == 0) {
        253							k             = p[p_y][p_x];
        254							p[p_y][p_x]   = p[p_y][p_x+1];
        255							p[p_y][p_x+1] = k;
        256						}
        257						else {
        258							k             = p[p_y][p_x];
        259							p[p_y][p_x]   = p[p_y+1][p_x];
        260							p[p_y+1][p_x] = k;
        261						}
        262						piece();
        263					}
        264					else if (e.keyCode == 40) {   // 下矢印(90度または-90度回転)
        265						if (rot == 0 && p[p_y+1][p_x] == 0) {
        266							if (p_y < row-1) {
        267								p[p_y+1][p_x] = p[p_y][p_x+1];
        268								p[p_y][p_x+1] = 0;
        269								ps[p_y][p_x+1].graphics.clear();
        270								rot = 1;
        271								piece();
        272							}
        273						}
        274						else {
        275							if (p_x < col-1 && p[p_y][p_x+1] == 0) {
        276								p[p_y][p_x+1] = p[p_y+1][p_x];
        277								p[p_y+1][p_x] = 0;
        278								ps[p_y+1][p_x].graphics.clear();
        279								rot = 0;
        280								piece();
        281							}
        282						}
        283					}
        284				}
        285			}
        286						//
        287						// ピースの描画
        288						//
        289			private function piece() : void
        290			{
        291				var i1 : int;
        292				var i2 : int;
        293	
        294				for (i1 = 0; i1 < row; i1++) {
        295					for (i2 = 0; i2 < col; i2++) {
        296						if (p[i1][i2] > 0) {
        297							switch (p[i1][i2]) {
        298								case 1:
        299									ps[i1][i2].graphics.beginFill(0xff0000);
        300									break;
        301								case 2:
        302									ps[i1][i2].graphics.beginFill(0xffd700);
        303									break;
        304								case 3:
        305									ps[i1][i2].graphics.beginFill(0x00ffff);
        306									break;
        307								case 4:
        308									ps[i1][i2].graphics.beginFill(0xadff2f);
        309									break;
        310							}
        311							ps[i1][i2].graphics.drawRect(0, 0, p_wh, p_wh);
        312							ps[i1][i2].graphics.endFill();
        313						}
        314					}
        315				}
        316			}
        317						//
        318						// ピースの選択
        319						//
        320			private function select() : void
        321			{
        322				var color : int;
        323	
        324				ok  = true;
        325				rot = 0;
        326				p_y = 0;
        327				p_x = (int)(Math.random() * (col - 1));
        328				if (p_x > col-2)
        329					p_x = col - 2;
        330	
        331				if (p[0][p_x] == 0 && p[0][p_x+1] ==0 ) {
        332					color = (int)(Math.random() * 4) + 1;
        333					if (color > 4)
        334						color = 4;
        335					p[0][p_x] = color;
        336					color = (int)(Math.random() * 4) + 1;
        337					if (color > 4)
        338						color = 4;
        339					p[0][p_x+1] = color;
        340				}
        341				else
        342					game = false;
        343	
        344				piece();
        345			}
        346						//
        347						// 同じ色のピースを探す
        348						//
        349			private function search(k1:int, k2:int, c1:int) : int
        350			{
        351				var c2 : int = c1;
        352	
        353				if (k1 > 0 && p[k1-1][k2] == p[k1][k2] && pp[k1-1][k2] == 0) {
        354					pp[k1-1][k2] = 1;
        355					c2           = search(k1-1, k2, c2+1);
        356				}
        357				if (k1 < row-1 && p[k1+1][k2] == p[k1][k2] && pp[k1+1][k2] == 0) {
        358					pp[k1+1][k2] = 1;
        359					c2           = search(k1+1, k2, c2+1);
        360				}
        361				if (k2 > 0 && p[k1][k2-1] == p[k1][k2] && pp[k1][k2-1] == 0) {
        362					pp[k1][k2-1] = 1;
        363					c2           = search(k1, k2-1, c2+1);
        364				}
        365				if (k2 < col-1 && p[k1][k2+1] == p[k1][k2] && pp[k1][k2+1] == 0) {
        366					pp[k1][k2+1] = 1;
        367					c2           = search(k1, k2+1, c2+1);
        368				}
        369	
        370				return c2;
        371			}
        372						//
        373						// ピースの削除
        374						//
        375			private function p_delete() : void
        376			{
        377				var i1 : int;
        378				var i2 : int;
        379				var i3 : int;
        380				var k1 : int;
        381				var k2 : int;
        382				var k3 : int;
        383								// 削除
        384				for (i1 = 0; i1 < row; i1++) {
        385					for (i2 = 0; i2 < col; i2++) {
        386						if (pp[i1][i2]  > 0) {
        387							p[i1][i2] = 0;
        388							ps[i1][i2].graphics.clear();
        389						}
        390					}
        391				}
        392								// 詰める
        393				for (i1 = 0; i1 < col; i1++) {
        394					k1 = 1;
        395					for (i2 = row-1; i2 > 0 && k1 >= 0; i2--) {
        396						if (p[i2][i1] == 0) {
        397							k1 = -1;
        398							for (i3 = i2-1; i3 >= 0 && k1 < 0; i3--) {
        399								if (p[i3][i1] > 0)
        400									k1 = i3;
        401							}
        402							if (k1 >= 0) {
        403								k2 = i2;
        404								k3 = k2 - k1;
        405								while (k1 >= 0) {
        406									p[k2][i1] = p[k1][i1];
        407									if (p[k1][i1] > 0) {
        408										p[k1][i1] = 0;
        409										ps[k1][i1].graphics.clear();
        410									}
        411									k1--;
        412									k2--;
        413								}
        414								k1++;
        415							}
        416						}
        417					}
        418				}
        419			}
        420		}
        421	}
        					
        017 行目

          作業域として使用するため,ピースの存在を示す 2 次元配列 p と同じ大きさの配列 pp を定義している.

        148 行目~ 167 行目

          ピースが再下端に達するか,または,他のピースの上に乗って停止した場合に対する処理である.150 行目~ 164 行目において,メソッド search( 349 行目~ 371 行目)によって,ピース p[i1][i2] と隣り合っている同じ色のピースの数を調べ,その値が 4 以上である場合は,メソッド p_delete( 375 行目~ 419 行目)によってそれらのピースを削除している.これら全体を 149 行目の while 文によって繰り返しているのは,削除の結果,再び同じ色のピースが繋がる可能性があるからである.

        349 行目~ 371 行目

          ピース p[k1][k2] の上下左右に同じ色のピースがあるか否かを,再帰呼び出しを利用して調べている.最終的に,隣り合った同じ色のピースの数が返される.

        384 行目~ 391 行目

          隣り合った同じ色のピースを削除している.

        393 行目~ 418 行目

          ピースが存在しない空白を詰める処理である.
        • 396 行目: p[i2][i1] が空白のとき以下の処理が行われる
        • 397 行目~ 402 行目: 空白の上にピースが存在するか否かを調べている.存在する場合は,その行番号が変数 k1 に設定され,403 行目以降が実行される.
        • 403 行目~ 414 行目: k2 行,及び,k2 行から k1 行の間にある空白を詰める.

静岡理工科大学 菅沼ホーム ActionScript目次 索引