AS3でブロック崩し

Filed under AS3



簡単なブロック崩しの練習です。

サンプルはこちら

以下、ソースです。

package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;

	public class breakout extends Sprite
	{
		// 描写するキャンバスのサイズ
		private static const CANVAS_WIDTH:Number=640;
		private static const CANVAS_HEIGHT:Number=480;

		// ボールに関する定数(半径・直径・初期位置・初期移動速度・制限)
		private static const BALL_RADIUS:Number=5;
		private static const BALL_SIZE:Number = 10;
		private static const BALL_SPEED:Number=5;
		private static const BALL_LIMIT_X:Number=CANVAS_WIDTH - BALL_SIZE;

		// バーに関する定数(サイズ・yの位置・制限)
		private static const BAR_WIDTH:Number=100;
		private static const BAR_HEIGHT:Number=10;
		private static const BAR_Y:Number=410;
		private static const BAR_LIMIT_X:Number=CANVAS_WIDTH - BAR_WIDTH;

		// ブロックのサイズ
		private static const BLOCK_WIDTH:Number = 80;
		private static const BLOCK_HEIGHT:Number = 25;
		private static const BLOCK_NUM_W:int = 7;
		private static const BLOCK_NUM_H:int = 5;
		private static const BLOCK_START_X:int=25;
		private static const BLOCK_START_Y:int=20;
		private static const BLOCK_SPACE:int=5;

		// キャンバス
		private var canvas:BitmapData;
		private var canvas_bmp:Bitmap;

		// ボールを描写するBitmapData・位置・移動速度
		private var ball:BitmapData;
		private var ball_x:Number;
		private var ball_y:Number;
		private var ball_dx:Number;
		private var ball_dy:Number;

		// バーのy座標
		private var bar_x:Number;

		// ブロックを保存する配列
		private var container:Array;

		// コンストラクタ
		public function breakout()
		{
			// ステージの設定
			stage.scaleMode=StageScaleMode.NO_SCALE;
			stage.align=StageAlign.TOP_LEFT;
			stage.quality=StageQuality.HIGH;
			stage.frameRate=60;

			// 全体を描写するキャンバス
			canvas=new BitmapData(CANVAS_WIDTH, CANVAS_HEIGHT, false, 0x000000);
			canvas_bmp=addChild(new Bitmap(canvas)) as Bitmap;
			onResize();

			// ブロックの位置を計算
			container = [];
			for(var i:int=0 ; i<BLOCK_NUM_W ; i++)
			{
				for(var j:int=0 ; j<BLOCK_NUM_H ; j++)
				{
					var block:Block = new Block(BLOCK_START_X + i*(BLOCK_SPACE + BLOCK_WIDTH), BLOCK_START_Y + j*(BLOCK_SPACE + BLOCK_HEIGHT));
					container.push(block);
				}
			}

			// "Click here."を作成して、canvasに描写
			var tf:TextField = new TextField;
			tf.autoSize = TextFieldAutoSize.LEFT;
			tf.text = "Click."
			tf.textColor = 0xffffff;
			canvas.draw(tf, new Matrix(1,0,0,1,(CANVAS_WIDTH-tf.width)/2, (CANVAS_HEIGHT-tf.height)/2));

			// ボールを描いたBitmapDataを作成
			var tmp:Shape=new Shape;
			var g:Graphics=tmp.graphics;
			g.beginFill(0xffffff, 1);
			g.drawCircle(BALL_RADIUS, BALL_RADIUS, BALL_RADIUS);
			g.endFill();
			ball=new BitmapData(BALL_SIZE, BALL_SIZE, false, 0x000000);
			ball.draw(tmp);

			// イベント追加
			stage.addEventListener(MouseEvent.CLICK, onClick);
		}

		// クリック後に実行
		private function onClick(e:MouseEvent):void
		{
			// クリックイベントの削除
			canvas.fillRect(canvas.rect, 0x000000);
			stage.removeEventListener(MouseEvent.CLICK, onClick);

			// ボールの移動に関する変数の初期化
			ball_x= canvas_bmp.mouseX + BAR_WIDTH/2;
			ball_y=BAR_Y-BALL_SIZE;
			ball_dx = Math.cos(45*Math.PI/180)*BALL_SPEED;
			ball_dy = Math.sin(45*Math.PI/180)*BALL_SPEED;

			// イベントの追加
			addEventListener(Event.ENTER_FRAME, onFrame);
			stage.addEventListener(Event.RESIZE, onResize);
		}

		// 毎フレーム実行される関数
		private function onFrame(e:Event):void
		{
			canvas.fillRect(canvas.rect, 0x000000);

			// バーの位置を更新
			bar_x=canvas_bmp.mouseX;
			if (bar_x < 0) bar_x=0;
			if (bar_x > BAR_LIMIT_X) bar_x=BAR_LIMIT_X;

			// ボールと壁の当たり判定
			if (ball_x < 0)
			{
				ball_x=0;
				ball_dx*= -1;
			}
			if (ball_x > BALL_LIMIT_X)
			{
				ball_x=BALL_LIMIT_X;
				ball_dx*= -1;
			}
			if(ball_y < 0)
			{
				ball_y = 0;
				ball_dy*= -1;
			}

			// ボールとバーの衝突判定
			if(ball_y + BALL_SIZE < BAR_Y){
			}else if(ball_x + BALL_SIZE < bar_x){
			}else if(ball_x > bar_x + BAR_WIDTH){
			}else if(ball_y > BAR_Y + BAR_HEIGHT){
			}else
			{
				ball_y = BAR_Y - BALL_SIZE;
				ball_dy *= -1;

				// ボールの反射角度を計算
				var ball_centerX:Number = ball_x + BALL_RADIUS;
				var ball_centerY:Number = ball_y + BALL_RADIUS;
				var bar_centerX:Number = bar_x + BAR_WIDTH/2;
				var bar_centerY:Number = BAR_Y + BAR_HEIGHT/2;
				var rad:Number = Math.atan2(ball_centerY - bar_centerY, ball_centerX - bar_centerX);
				ball_dx = Math.cos(rad)*BALL_SPEED;
				ball_dy = Math.sin(rad)*BALL_SPEED;
			}

			// 描写開始
			canvas.lock();

			// Blockとの衝突判定&描写
			var len:int = container.length;
			while(len--)
			{
				var block:Block = container[len];

				if(ball_y > block.y + BLOCK_HEIGHT){
				}else if(ball_x + BALL_SIZE < block.x){
				}else if(ball_x > block.x + BLOCK_WIDTH){
				}else if(ball_y + BALL_SIZE < block.y){
				}else
				{
					if(ball_y >= block.y + BLOCK_HEIGHT - 5 || ball_y + BALL_SIZE <= block.y + 5)	ball_dy *= -1;
					else if(ball_x + BALL_SIZE <= block.x + 3 || ball_x  >= block.x + BLOCK_WIDTH - 3) ball_dx *= -1;

					container.splice(len,1);
					continue;
				}

				canvas.fillRect(new Rectangle(block.x, block.y, BLOCK_WIDTH, BLOCK_HEIGHT), 0xffffff);
			}

			// バーの描写
			canvas.fillRect(new Rectangle(bar_x, BAR_Y, BAR_WIDTH, BAR_HEIGHT), 0xffffff);

			// ボールの描写
			canvas.copyPixels(ball, ball.rect, new Point(ball_x, ball_y));
			canvas.unlock();

			// ボールが範囲の外 or ブロックを崩し終わったら終了
			len = container.length;
			if(ball_y > CANVAS_HEIGHT || len == 0)
			{
				canvas.fillRect(canvas.rect, 0x000000);
				removeEventListener(Event.ENTER_FRAME, onFrame);
			}

			// ボールの位置を更新
			ball_x+=ball_dx;
			ball_y+=ball_dy;
		}

		// リサイズイベント
		private function onResize(e:Event=null):void
		{
			canvas_bmp.x = (stage.stageWidth - CANVAS_WIDTH) / 2;
			canvas_bmp.y = (stage.stageHeight - CANVAS_HEIGHT) / 2;
		}
	}
}

// ブロックを表すクラス
class Block
{
	public var x:Number;
	public var y:Number;

	public function Block(x:Number, y:Number)
	{
		this.x = x;
		this.y = y;
	}
}

Post a Comment

Your email is never published nor shared.