In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

【弾幕シリーズ】スペカ:マウンテン・オブ・フェイス風処理v0.3

【弾幕シリーズ】スペカ:マウンテン・オブ・フェイス風処理v0.3
2段目の発生はまだ再現してません。
弾の移動角度が綺麗に思いつかなかったので目算で入力してます
かなり無理やり
弾の描画順番までは考慮してません
Get Adobe Flash player
by okoi 25 Mar 2010
/**
 * Copyright okoi ( http://wonderfl.net/user/okoi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/2Qp6
 */

//
//	【弾幕シリーズ】スペカ:マウンテン・オブ・フェイス風処理v0.3
//		2段目の発生はまだ再現してません。
//		弾の移動角度が綺麗に思いつかなかったので目算で入力してます
//		かなり無理やり
//		弾の描画順番までは考慮してません
//
package 
{
	import flash.display.BitmapData;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	
	[SWF(backgroundColor = "0x000000", frameRate = "60")]
	
	/**
	 * メインクラス
	 * @author okoi
	 */
	public class Main extends Sprite 
	{
		private var _canvas:BitmapData;
		private var _bullets:Array = new Array();
		private var _pattern:Pattern;
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			_canvas = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x00000000 );
			addChild(new Bitmap(_canvas));
			
			_pattern = new Pattern();
			_pattern.Start(stage.stageWidth/2, stage.stageHeight/2);
			
			addEventListener( Event.ENTER_FRAME, EnterFrame );
		}
		
		private	function EnterFrame(event:Event):void 
		{
			var i:int = 0;
			
			//	弾発生
			if ( !_pattern.isEnd() )
			{
				var res:Array = _pattern.Update();
				
				if ( res.length > 0 )
				{
					_bullets = _bullets.concat( res );
				}
			}
			
			//	弾移動
			for ( i = _bullets.length - 1; i >= 0; i-- )
			{
				var b:Bullet = _bullets[i];
				b.Move();
				
				if ( b._x < -50 || b._x > stage.stageWidth + 50 || b._y < -50 || b._y > stage.stageHeight + 50 )
				{
					_bullets.splice( i, 1 );
				}
			}
			
			_canvas.lock();
			_canvas.fillRect(_canvas.rect, 0x000000);
			for ( i = 0; i < _bullets.length; i++ )
			{
				_bullets[i].DrawSprite(_canvas);
			}
			_canvas.unlock();
		}
		
	}
	
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
import flash.display.Graphics;
import flash.display.BitmapData;
import flash.geom.Point;
import flash.display.Shape;

/**************************************************************************
 * 弾クラス
 */
class Bullet {
	
	public var _x:Number;
	public var _y:Number;
	public var _bmp:BitmapData;
	
	private	var	moveCmd:Array = new Array();
	
	public	function Bullet(__bmp:BitmapData, __x:Number = 0, __y:Number = 0) 
	{
		_x = __x;
		_y = __y;
		_bmp = __bmp; 
	}
	public	function Move():void 
	{
		if ( moveCmd.length > 0 )
		{
			var cmd:BulletMove = moveCmd[moveCmd.length - 1];
			
			switch( cmd._type )
			{
			case	BulletMove.TYPE_WAIT:
				break;
			case	BulletMove.TYPE_DIR:
				_x += Math.cos( cmd._angle * Math.PI / 180 ) * cmd._speed;
				_y += Math.sin( cmd._angle * Math.PI / 180 ) * cmd._speed;
				break;
			case	BulletMove.TYPE_ACCELE:
				if ( cmd._speed < cmd._maxspeed )
				{
					cmd._speed += cmd._accele;
					if ( cmd._speed >= cmd._maxspeed ) cmd._speed = cmd._maxspeed;
				}
				_x += Math.cos( cmd._angle * Math.PI / 180 ) * cmd._speed;
				_y += Math.sin( cmd._angle * Math.PI / 180 ) * cmd._speed;			
				break;
			}
			
			if ( cmd._step >= 0 )
			{
				cmd._step--;
				if ( cmd._step <= 0 )	moveCmd.pop();
			}
		}
		
	}
	public	function DrawSprite(canvas:BitmapData):void
	{
		canvas.copyPixels(_bmp, _bmp.rect, new Point(_x - _bmp.width / 2, _y - _bmp.height / 2));
	}

	public	function AddMoveCmd(cmd:BulletMove):void 
	{
		moveCmd.push( cmd );
	}	
}
/**************************************************************************
 * 弾移動データクラス
 */
class BulletMove {
	
	public	static	const	TYPE_WAIT:int = 0;
	public	static	const	TYPE_DIR:int = 1;
	public	static	const	TYPE_ACCELE:int = 2;
	
	public	var _type:int;
	public	var _step:int;
	public	var _angle:Number;
	public	var _speed:Number;
	public	var _maxspeed:Number;
	public	var	_accele:Number;

	public	static	function CreateWait(__step:int):BulletMove 
	{
		var obj:BulletMove = new BulletMove();
		obj._type = TYPE_WAIT;
		obj._step = __step;
		obj._angle = 0;
		obj._speed = 0;
		return	obj;
	}
	public	static	function CreateDir(__step:int,__angle:Number,__speed:Number):BulletMove 
	{
		var obj:BulletMove = new BulletMove();
		obj._type = TYPE_DIR;
		obj._step = __step;
		obj._angle = __angle;
		obj._speed = __speed;
		return	obj;
	}
	public	static	function CreateAccele(__step:int,__angle:Number,__speed:Number,__accele:Number,__max:Number):BulletMove 
	{
		var obj:BulletMove = new BulletMove();
		obj._type = TYPE_ACCELE;
		obj._step = __step;
		obj._angle = __angle;
		obj._speed = __speed;
		obj._accele = __accele;
		obj._maxspeed = __max;
		return	obj;
	}
	
	
}

/***************************************************************************
 * 弾テンプレートクラス
 */
class BulletTemplate {
	
	private static	var	instance:BulletTemplate = null;
	private static	var	callGetInstance:Boolean = false;
	
	private var _BULLET_TYPE_1:BitmapData;
	private var _BULLET_TYPE_2:BitmapData;
	private var _BULLET_TYPE_3:BitmapData;
	public	function get BULLET_TYPE_1():BitmapData { return	_BULLET_TYPE_1;	}
	public	function get BULLET_TYPE_2():BitmapData { return	_BULLET_TYPE_2;	}
	public	function get BULLET_TYPE_3():BitmapData { return	_BULLET_TYPE_3;	}
	
	public	function BulletTemplate() 
	{
		if ( callGetInstance ) {
			callGetInstance = false;
			Init();
		}else
		{
			throw new Error("BulletTemplate コンストラクタの直接呼び出しは禁止");
		}
	}
	
	public	static	function getInstance():BulletTemplate
	{
		if ( BulletTemplate.instance == null )
		{
			callGetInstance = true;
			BulletTemplate.instance = new BulletTemplate();
		}
		return	BulletTemplate.instance;
	}
	
	private	function Init():void 
	{
		var s : Shape = new Shape();
		var g : Graphics = s.graphics;
		
		g.beginFill(0xff5555);
		g.drawCircle(5, 5, 5);
		g.endFill();
		g.beginFill(0xffffff, 0.5);
		g.drawCircle(5, 5, 3);
		g.endFill();
		_BULLET_TYPE_1 = new BitmapData(10, 10, true, 0x00000000);
		_BULLET_TYPE_1.draw(s);
		
		g.beginFill(0xFF55FF);
		g.drawCircle(5, 5, 5);
		g.endFill();
		g.beginFill(0xffffff, 0.5);
		g.drawCircle(5, 5, 3);
		g.endFill();		
		_BULLET_TYPE_2 = new BitmapData(10, 10, true, 0x00000000);
		_BULLET_TYPE_2.draw(s);
		
		g.beginFill(0x5555FF);
		g.drawCircle(5, 5, 5);
		g.endFill();
		g.beginFill(0xffffff, 0.5);
		g.drawCircle(5, 5, 3);
		g.endFill();		
		_BULLET_TYPE_3 = new BitmapData(10, 10, true, 0x00000000);
		_BULLET_TYPE_3.draw(s);		
	}
}
/**************************************************************************
 * 弾幕パターン定義クラス
 */
class Pattern {
	
	private	var	runFlag:Boolean = false;
	private var step:uint = 0;
	private var _x:Number;
	private var _y:Number;
	
	private static const R36:Number = 36 * Math.PI / 180;	//	36°のラジアン
	private static const CIRCLE_1R:Number = 40;											//	円小までの距離と半径
	private static const CIRCLE_2R:Number = Math.cos(R36) * (2 * CIRCLE_1R); 			//	円中までの距離
	private static const CIRCLE_2_2R:Number = Math.sin(R36) * (2 * CIRCLE_1R); 			//	円中の半径
	private static const CIRCLE_3R:Number = Math.cos(R36) * (CIRCLE_2R + CIRCLE_2_2R);	//	円大までの距離
	private static const CIRCLE_3_2R:Number = Math.sin(R36) * (CIRCLE_2R + CIRCLE_2_2R);//	円大の半径
	
	private static const STEP1_FRM:uint = 80;
	private static const STEP2_FRM:uint = 40;
	private static const STEP3_FRM:uint = 40;
	private static const STEP_MAX:uint = STEP1_FRM + STEP2_FRM + STEP3_FRM + 400;
	
	public	function Pattern() 
	{
		
	}
	
	/**
	 * 弾幕生成スタート
	 * @param	_defX	弾幕の基点となる座標
	 * @param	_defY
	 */
	public	function Start(_defX:Number = 0, _defY:Number = 0):void  
	{
		runFlag = true;
		step = 0;
		_x = _defX;
		_y = _defY;
	}
	
	public	function End():void
	{
		runFlag = false;
	}	
	public	function	isEnd() : Boolean {	return	!runFlag;	}
	
	/**
	 * 弾発生処理
	 * @return	Array	今回発生させた弾のリストを返す
	 */
	public	function Update():Array 
	{
		var	bullets:Array = new Array();
		var tpl:BulletTemplate = BulletTemplate.getInstance();
		var i:int = 0;
		var cangle:Number;	//	中心角度
		var bangle:Number;	//	弾角度
		var radians:Number;
		var bX:Number;
		var bY:Number;
		var b:Bullet;
		
		var sstep:uint = step % STEP_MAX;
				
		for ( i = 0; i < 5; i++ )
		{
			var	arate:Number;
			
			//	小サイズの円発生 288°
			if( sstep < STEP1_FRM )
			{
				arate = sstep / STEP1_FRM;
				
				//	発生円の中心位置を求める
				cangle = (342 + i*72) % 360;
				radians = cangle * Math.PI / 180;
				bX = _x + Math.cos( radians ) * CIRCLE_1R;	//	中心位置
				bY = _y + Math.sin( radians ) * CIRCLE_1R;
				
				//	中心位置から一定距離上に出すので再度計算
				bangle = (cangle + 3*72) % 360 + (arate * 288);
				radians = bangle * Math.PI / 180;
				bX += Math.cos( radians ) * CIRCLE_1R;
				bY += Math.sin( radians ) * CIRCLE_1R;
				
				b = new Bullet(tpl.BULLET_TYPE_1, bX, bY);
				b.AddMoveCmd( BulletMove.CreateAccele( -1, (cangle + 3*72) % 360 + 190 + (310 * arate) - (arate * 100)%10, 0.1, 0.01, 1 ) );
				b.AddMoveCmd( BulletMove.CreateWait( STEP3_FRM + STEP2_FRM + STEP1_FRM - sstep ) );
				bullets.push( b );
				
			}else
			//	中サイズの円発生
			if ( sstep < STEP1_FRM + STEP2_FRM )
			{
				arate = (sstep - STEP1_FRM) / STEP2_FRM;
	
				cangle = (90 + i * 72) % 360;
				radians = cangle * Math.PI / 180;
				bX = _x + Math.cos( radians ) * CIRCLE_2R;	//	中心位置
				bY = _y + Math.sin( radians ) * CIRCLE_2R;
				
				//	中心位置から一定距離上に出すので再度計算
				bangle =	(cangle - 90)%360 + arate * 180;
				radians = bangle * Math.PI / 180;
				bX += Math.cos( radians ) * CIRCLE_2_2R;
				bY += Math.sin( radians ) * CIRCLE_2_2R;
				
				b = new Bullet(tpl.BULLET_TYPE_2, bX, bY);
				b.AddMoveCmd( BulletMove.CreateAccele(-1, (cangle - 90)%360 + 190 + (180 * arate) - (arate * 100)%10*0.5, 0.1, 0.01, 1 ));
				b.AddMoveCmd( BulletMove.CreateWait( STEP3_FRM + STEP2_FRM + STEP1_FRM - sstep + 50 ) );
				bullets.push( b );
				
			}else
			//	大サイズの円発生
			if ( sstep < STEP1_FRM + STEP2_FRM + STEP3_FRM )
			{
				arate = (sstep - (STEP1_FRM + STEP2_FRM) ) / STEP3_FRM;
				
				//	発生円の中心位置を求める
				cangle = (342 + i*72) % 360;
				radians = cangle * Math.PI / 180;
				bX = _x + Math.cos( radians ) * CIRCLE_3R;	//	中心位置
				bY = _y + Math.sin( radians ) * CIRCLE_3R;
				
				//	中心位置から一定距離上に出すので再度計算
				bangle = (cangle - 90) % 360 + arate * 180;
				radians = bangle * Math.PI / 180;
				bX += Math.cos( radians ) * CIRCLE_3_2R;
				bY += Math.sin( radians ) * CIRCLE_3_2R;
				
				b = new Bullet(tpl.BULLET_TYPE_3, bX, bY);
				b.AddMoveCmd( BulletMove.CreateAccele( -1, (cangle - 90) % 360 + 190 + (180 * arate) - (arate * 100) % 10 * 0.5, 0.1, 0.01, 1) );
				b.AddMoveCmd( BulletMove.CreateWait(STEP3_FRM + STEP2_FRM + STEP1_FRM - sstep + 100) );	
				bullets.push( b );	
			}
		}
		
		step++;
		//if ( step % STEP_MAX == 0 ) End();	//	1回で止めたい場合
		return	bullets;
	}
}