【弾幕シリーズ】スペカ:マウンテン・オブ・フェイス風処理v0.3
【弾幕シリーズ】スペカ:マウンテン・オブ・フェイス風処理v0.3
2段目の発生はまだ再現してません。
弾の移動角度が綺麗に思いつかなかったので目算で入力してます
かなり無理やり
弾の描画順番までは考慮してません
/**
* 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;
}
}