forked from: 俺の弾幕を越えていけ(Shooting AI)
<Control>
Start: click or key 'x'.
Move: arrow key.
Shot: key 'z'.
弾幕を避けるAIを作ろう企画
入力をフックして弾幕を避けるAIを作ってみてください (ゲーム自体は弄らず、inputAuto関数あたりを書き換える)
最終的な被弾数が一番少ない美しいAIを作った人が勝ち
敵(青・赤・紫)に当たり判定ないです。弾(白・黄色)だけ当たります
スコアはついで。約1分半。
普通に遊びたい人はクリック。
_skipFrameの値を多くするとフレームスキップします。さっさと動かしたい人向け
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/mxBP
*/
// forked from heriet's 俺の弾幕を越えていけ(Shooting AI)
// <Control>
// Start: click or key 'x'.
// Move: arrow key.
// Shot: key 'z'.
//
// 弾幕を避けるAIを作ろう企画
// 入力をフックして弾幕を避けるAIを作ってみてください (ゲーム自体は弄らず、inputAuto関数あたりを書き換える)
// 最終的な被弾数が一番少ない美しいAIを作った人が勝ち
//
// 敵(青・赤・紫)に当たり判定ないです。弾(白・黄色)だけ当たります
// スコアはついで。約1分半。
//
// 普通に遊びたい人はクリック。
//
// _skipFrameの値を多くするとフレームスキップします。さっさと動かしたい人向け
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import net.hires.debug.Stats;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "0x202030")]
public class Main extends Sprite
{
public static var root:Main;
private static const END_FRAME:int = 4600;
public static const SCREEN_WIDTH:int = 465;
public static const SCREEN_HEIGHT:int = 465;
public static const BACKGROUND_COLOR:uint = 0x202030;
private static const ENEMY_COLOR_TRANSFORMS:Vector.<ColorTransform> = Vector.<ColorTransform>([
new ColorTransform(1.0, 1.0, 1.0, 1.0, -32, -48, -48), new ColorTransform(1.25, 1.0, 1.0, 1.0, -12, -24, -32),
new ColorTransform(1.0, 1.0, 1.0, 1.0, -24, -24, -24), new ColorTransform(1.0, 1.0, 1.0, 1.0, -24, -24, -24),
]);
private static const NONENEMY_COLOR_TRANSFORMS:Vector.<ColorTransform> = Vector.<ColorTransform>([
new ColorTransform(1.0, 1.0, 1.0, 1.25, -32, -16, 0), new ColorTransform(1.0, 1.0, 1.0, 1.0, -16, -8, -16),
new ColorTransform(1.0, 1.0, 1.0, 1.0, -12, -8, -12), new ColorTransform(1.0, 1.0, 1.0, 1.0, -24, -24, -8),
]);
private static const MOTION_DATA:String =
"2***y00|4***b00|4***w00|g***000,3***J00|3***r00|4***w00|g***000,"
+ "0 g* ** 00|Y ** 1* 10, 0 M* ** 00|Y ** 1* 10, 0000000, 0000000, 0000000, 0000000, 0000000,"
+ "4 ** *A 00|4 ** *a 00|0 ** *0 00, 4 ** *w 00|4 ** *2 00|0 ** *0 00, 4 ** ** 00|4 ** *a 00|0 ** *0 00,"
+ "4 ** ** 00|4 ** *2 00|0 ** *0 00, 0000000, 0000000, 0000000,"
+ "0000000, 0000000, 0000000, 0000000, 0000000, 0000000, 0000000,"
+ "0000000, 0000000, 0000000, 0000000, 0000000, 0000000, 0000000,"
+ "0000000, 0000000, 0000000, 0000000, 0000000,"
+ "8 ** *2 00|8 ** *F 00|Y *8 w0 00|u ** *A 00,"
+ "8 ** *2 00|8 ** *A 00|Y *4 *0 00,"
+ "8 ** *4 00|8 ** *F 00|Y *g z0 00|Y *g z0 00|u ** *w 00,"
+ "g ** *2 01|g ** *0 01|u ** *y 01|u ** 11 00|0 ** *1 00,"
+ "_ ** ** 00|u ** 1* 00|u ** 0* 00|g ** 12 00|u ** 00 00,"
+ "_ ** ** 00|4 ** w* 00|_ ** *1 00,"
+ "a ** *1 01|8 ** *0 01|g ** *w 01|g ** 11 00|0 ** *2 00,"
+ "8 ** *2 00|8 ** *A 00|Y *0 *0 00|Y ** ** 00|Y ** *2 00,"
+ "2 ** *2 00|2 ** *A 00|Y *8 10 00|Y *8 10 00|Y *8 10 00|Y 0* *2 00";
private static const SHOT_DATA:String =
"90a0 000k 1000 0010 313, 8000 000h 1100 0010 223, 90a0 000o 1a00 0010 1t3,"
+"91b0 000a 2000 171a 1E5, 8000 000h 1200 00b0 3A6, 82b0 000a 1000 0712 2Y8,"
+"91b0 00w4 0000 251a 515, 95c0 000v 1600 a100 081, 90a0 000o 1100 0030 0a1,"
+"91b0 0004 1500 1538 3A6, 91b0 0002 1500 1548 3A6, 91b0 0002 1100 1536 3Z8,"
+"80a0 000v 15v0 0020 029, 84b0 000o 15v0 0g0v 0vg, 90a0 Z00f 131f 0090 09o|90b0 f00a 13zn 0090 0ao,"
+"84b0 000o 15v0 090g 0_g, 93c0 0006 1000 070k 616, 95d0 000a 1700 fi00 2_6";
private static const STAGE_DATA:String
= "0A 23a a001|1A 23b A001|30 25a a001|40 25b A001|3A 85c 8000|4A 15d L000|5A 15e 8000|6A 15f L000|"
+ "8A k3l v000|2A _3g v000|90 26i d00z|cA 23j g00z|eA 23k A00z|"
+ "h0 26i d00z|iA 23a A001|jA 36l g000|mA 36m _000|"
+ "rA 38n T101|tA 38o c101|vA 2an T101|xA 2ao c101|yA 28n T101|y_ 2go c101|zA 28n T101|zA 28o c101|"
+ "B0 1gp H101|BA 1gp 6101|DA 1gp H101|D_ 1gp 6101|EA 1gp H101|E_ 1gp 6101|"
+ "GA 42q px0H|I_ 42r _x0H|M0 g7v a001|MA g4w A001|"
+ "TA 11s 0000|X_ 11t 0000|XA 11u 0000|_A 11s 0000|__ 11t 0000|__ 11u 0000";
private static const ENEMY_DATA:String =
"a 12 0a 300, a wx 0a 400, a 12 0a 300|a wx 0a 400, a 22 00 070|a x2 00 070, a 12 0g 3d0|a wx 0g 4d0, b 44 00 040|b z4 00 040, 00000000, 00000000, 00000000,"
+"b o2 Ea 022, b 82 ma 022, b 21 wa A10, b t1 wa A10, b 51 wk Ah0, b q1 wk Ah0,"
+"c 61 wa Ba5, c 61 wa Ba0, a 21 wa D30, b 21 ta E43, b t2 Ja F52, b 32 w3 064, b r2 w3 064,"
+"a t1 wa G80, a 21 wa G80, a f1 wa G90, c 41 wg He6, c p1 wg He6, d g1 wg If0, c p1 wg Hg0, c 41 wg Hg0,"
+ "b o2 Ja 0i1, b 82 ma 0i1";
private var _resultTextField:TextField = new TextField();
private var _stats:Stats = new Stats();
private var _enemyLayer:BitmapData = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0);
private var _enemyScreen:Bitmap = new Bitmap(_enemyLayer);
private var _nonEnemyLayer:BitmapData = new BitmapData(SCREEN_WIDTH, SCREEN_HEIGHT, false, 0);
private var _nonEnemyScreen:Bitmap = new Bitmap(_nonEnemyLayer);
public var motionManager:DataManager = new DataManager(MOTION_DATA, MotionData);
public var shotManager:ShotManager = new ShotManager(SHOT_DATA);
private var _stageManager:StageManager = new StageManager(STAGE_DATA, ENEMY_DATA);
private var _bullets:TokenContainer = new TokenContainer(Bullet, _enemyLayer);
private var _enemys:TokenContainer = new TokenContainer(Enemy, _enemyLayer);
private var _shots:TokenContainer = new TokenContainer(Bullet, _nonEnemyLayer);
private var _effects:TokenContainer = new TokenContainer(Effect, _nonEnemyLayer);
public var player:Player = new Player();
private var _skipFrame:int = 0;
private var _isAuto:Boolean = true;
private var _gameFrame:int, _hitCount:int, _score:int;
public var inputKey:InputKey = new InputKey();
private var _lcg:LinearCongruentialGenerator = new LinearCongruentialGenerator();
public function Main() {
Main.root = this;
stage.addEventListener(MouseEvent.CLICK, startPlayer);
stage.addEventListener(KeyboardEvent.KEY_DOWN, checkStartPlayerKey);
_enemyScreen.blendMode = BlendMode.ADD;
_nonEnemyScreen.blendMode = BlendMode.ADD;
_resultTextField.defaultTextFormat = new TextFormat(null, 10, 0xFFFFFF);
_resultTextField.x = SCREEN_WIDTH - 128;
_resultTextField.selectable = false;
graphics.beginFill(0x202030);
graphics.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
startGame();
}
private function startPlayer(event:Event = null):void {
_isAuto = false;
stage.focus = this;
stage.removeEventListener(MouseEvent.CLICK, startPlayer);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, checkStartPlayerKey);
startGame();
}
private function startGame(isFirst:Boolean = true):void {
while (numChildren > 0) { removeChildAt(0) }
if (!_isAuto) {
stage.addEventListener(KeyboardEvent.KEY_DOWN, inputKey.onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, inputKey.onKeyUp);
}
else{
if(!isFirst)
addMessage("Your Result\n\nDamaged: " + String(_hitCount) + "\nScore : " + String(_score) + "\n\n click or key 'x' to start");
else
addMessage("click to start");
}
_gameFrame = 0, _score = 0, _hitCount = 0;
inputKey.initialize();
_lcg.initialize();
_stageManager.initialize();
if(_isAuto)
initializeInputAuto();
_nonEnemyLayer.fillRect(_nonEnemyLayer.rect, 0);
addChild(_nonEnemyScreen);
_enemyLayer.fillRect(_enemyLayer.rect, 0);
addChild(_enemyScreen);
_bullets.clear(); _enemys.clear();
_shots.clear(); _effects.clear();
player.initialize(1, (SCREEN_WIDTH << Token.FIELD_SCALE) / 2, ((SCREEN_HEIGHT - 32) << Token.FIELD_SCALE));
updateResult();
addChild(_resultTextField);
addChild(_stats);
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function enterFrameHandler(event:Event):void {
_enemyLayer.lock(); _nonEnemyLayer.lock();
for (var i:int = 0; i <= _skipFrame; i++) {
_gameFrame++;
_enemyLayer.fillRect(_enemyLayer.rect, 0x000000);
_nonEnemyLayer.fillRect(_nonEnemyLayer.rect, 0x000000);
// _enemyLayer.colorTransform(_enemyLayer.rect, ENEMY_COLOR_TRANSFORMS[_gameFrame % 4]);
// _nonEnemyLayer.colorTransform(_nonEnemyLayer.rect, NONENEMY_COLOR_TRANSFORMS[_gameFrame % 4]);
_stageManager.update(_gameFrame);
_enemys.update(); _bullets.update();
_shots.update(); _effects.update();
checkAttackEnemy();
if(!player.isInvincible)
checkAttackPlayer();
if (_isAuto)
inputKey.pushed = inputAuto(_gameFrame, player, _enemys.tokens, _bullets.tokens, _enemyLayer)
player.update();
player.draw(_nonEnemyLayer);
}
_enemyLayer.unlock(); _nonEnemyLayer.unlock();
if (_gameFrame == END_FRAME) {
endGame();
}
}
private function endGame():void {
removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
if (!_isAuto){
_isAuto = true;
stage.removeEventListener(KeyboardEvent.KEY_DOWN, inputKey.onKeyDown);
stage.removeEventListener(KeyboardEvent.KEY_UP, inputKey.onKeyUp);
stage.addEventListener(MouseEvent.CLICK, startPlayer);
stage.addEventListener(KeyboardEvent.KEY_DOWN, checkStartPlayerKey);
}
addEventListener(Event.ENTER_FRAME, restart);
}
private function restart(event:Event):void {
removeEventListener(Event.ENTER_FRAME, restart);
startGame(false);
}
private function checkStartPlayerKey(event:KeyboardEvent):void
{
if (event.keyCode == 88) // keydown 'x'
startPlayer();
}
private function checkAttackPlayer():void {
var lx:int = player.x >> Token.FIELD_SCALE;
var ly:int = player.y >> Token.FIELD_SCALE;
if ((_enemyLayer.getPixel(lx, ly) & 0xFF0000) == 0) // rough check
return;
if (checkCollisionPoint(player.x, player.y, _bullets.tokens)) {
_hitCount++; updateResult();
player.damage();
}
}
private function checkAttackEnemy():void {
var tokens:Vector.<IToken> = _shots.tokens;
var n:int = tokens.length;
for (var i:int = 0; i < n; i++ ) {
var token:Token = tokens[i] as Token;
var lx:int = token.x >> Token.FIELD_SCALE;
var ly:int = token.y >> Token.FIELD_SCALE;
if ((_enemyLayer.getPixel(lx, ly) & 0xFF0000) != 0 && checkCollisionEnemy(token))
token.vanish();
}
}
private function checkCollisionEnemy(shot:IToken):Boolean {
var tokens:Vector.<IToken> = _enemys.tokens;
var n:int = tokens.length;
for (var i:int = 0; i < n; i++ ) {
var enemy:Token = tokens[i] as Token;
if (enemy.isCollision(shot.x, shot.y)) {
enemy.damage();
return true;
}
}
return false;
}
private function checkCollisionPoint(x:int, y:int, tokens:Vector.<IToken>):Boolean {
var n:int = tokens.length;
for (var i:int = 0; i < n; i++ ) {
var token:Token = tokens[i] as Token;
if (token.isCollision(x, y)) {
return true;
}
}
return false;
}
private function addMessage(message:String):void {
var textField:TextField = new TextField();
var textFormat:TextFormat = new TextFormat(null, 20, 0xFFFFFF, true);
textField.defaultTextFormat = textFormat;
textField.selectable = false;
textField.width = SCREEN_WIDTH;
textField.height = 256;
textField.text = message;
addChild(textField);
textField.x = (SCREEN_WIDTH - textField.textWidth) / 2;
textField.y = (SCREEN_HEIGHT - textField.textHeight) / 2;
}
public function addBullet(id:int=0, x:int=0, y:int=0, direction:int=0, speed:int=0, motionID:int=0, shotID:int=0):Token {
return _bullets.addToken(id, x, y, direction, speed, motionID, shotID);
}
public function addEnemy(id:int=0, x:int=0, y:int=0, direction:int=0, speed:int=0, motionID:int=0, shotID:int=0):Token {
return _enemys.addToken(id, x, y, direction, speed, motionID, shotID);
}
public function addShot(id:int=0, x:int=0, y:int=0, direction:int=0, speed:int=0, motionID:int=0, shotID:int=0):Token {
return _shots.addToken(id, x, y, direction, speed, motionID, shotID);
}
public function addEffect(id:int=0, x:int=0, y:int=0, direction:int=0, speed:int=0, motionID:int=0, shotID:int=0):Token {
return _effects.addToken(id, x, y, direction, speed, motionID, shotID);
}
public function random():uint {
return _lcg.random()
}
public function addScore(value:int):void {
_score += value; updateResult();
}
private function updateResult():void {
_resultTextField.text = "Damaged: " + String(_hitCount) + "\nScore : " + String(_score);
}
}
}
import flash.display.BitmapData;
import flash.geom.Point;
import flash.events.KeyboardEvent;
// Enemy shoot bullet.
// When bullet collides with player, player is damaged.
// However, player is not damaged when enemy collides with player.
// Player moveable x is [8*16, 465-8*16] and y is [8*16, 465-8*16].
// Player's hit rect size is Rectangle(0, 0, 1*16, 1*16). It means a dot of screen.
// Player's hit rect area is Rectangle(token.x, token.y, 1*16, 1*16) on game field
// and Rectangle(token.x, token.y, 1, 1) on screen bitmap.
// Bullet's hit rect size is Rectangle(0, 0, 16*16, 16*16).
// Center of hit rect is Point(token.x, token.y).
// So, Bullet's hit rect area is Rectangle(token.x - 8*16, token.y - 8*16, 16*16, 16*16) on game field
// and Rectangle(token.x / 8 - 8, token.y / 8 - 8, 16, 16) and on screen bitmap.
function inputAuto(gameFrame:int, player:IToken, enemys:Vector.<IToken>, bullets:Vector.<IToken>, enemyScreen:BitmapData):int
{
return InputAutoNearestBulletOtherSide(gameFrame, player, enemys, bullets, enemyScreen)
}
var centeringFlag:Boolean;
function initializeInputAuto():void
{
centeringFlag = false;
}
// tekito-
function InputAutoNearestBulletOtherSide(gameFrame:int, player:IToken, enemys:Vector.<IToken>, bullets:Vector.<IToken>, enemyScreen:BitmapData):int
{
var pushedKey:int = InputKey.KEY_SHOT; // always shoot
if (bullets.length == 0)
return pushedKey;
if (centeringFlag) {
if ((465/2-100)*16 < player.x && player.x < (465/2+100)*16) {
centeringFlag = false;
return pushedKey;
}
else if (player.x < 465 / 2 * 16)
return pushedKey | InputKey.KEY_RIGHT;
else
return pushedKey | InputKey.KEY_LEFT;
}
if (player.x < Player.MIN_X + 30 * 16) {
centeringFlag = true;
return pushedKey | InputKey.KEY_RIGHT;
}
if (player.x > Player.MAX_X - 30 * 16) {
centeringFlag = true;
return pushedKey | InputKey.KEY_LEFT;
}
var nearestIndex:int = 0;
var nearestLength:Number = Math.pow(player.x - bullets[0].x, 2) + Math.pow(player.y - bullets[0].y, 2)
var n:int = bullets.length;
for (var i:int = 1; i < n; i++ ) {
var bullet:IToken = bullets[i];
var len:Number = Math.pow(player.x - bullet.x, 2) + Math.pow(player.y - bullet.y, 2);
if (len < nearestLength) {
nearestLength = len;
nearestIndex = i;
}
}
bullet = bullets[nearestIndex];
if (player.x < bullet.x)
pushedKey |= InputKey.KEY_LEFT;
else
pushedKey |= InputKey.KEY_RIGHT;
return pushedKey;
}
interface IToken
{
function get id():int; // 0: null, 1: player, 2:player's Shot, 3-5: effect, 6-9: enemy's bullet, 10-:enemy
function get x():int; // screen x * 16, [0, 465 * 16]
function get y():int; // screen y * 16, [0, 465 * 16]
function get vx():int; // velocity x
function get vy():int; // velocity y
function get direction():int; // degree, [0, 360)
function get speed():int;
function get accelDirection():int; // degree, [0, 360)
function get accelSpeed():int;
function get frame():int; // alive frame count
function get isVanished():Boolean; // When isVanished is true, token will remove
}
class InputKey {
public static const KEY_UP:int = 1;
public static const KEY_RIGHT:int = 1 << 1;
public static const KEY_DOWN:int = 1 << 2;
public static const KEY_LEFT:int = 1 << 3;
public static const KEY_SHOT:int = 1 << 4;
private static const KEYS:Object = { up:KEY_UP, right:KEY_RIGHT, down:KEY_DOWN, left:KEY_LEFT, shot:KEY_SHOT }
private static const KEY_CODE:Object = { up:38, right:39, down:40, left:37, shot:90 };
public var pushed:int;
public function initialize():void {
pushed = 0;
}
private function readKeyFlag(event:KeyboardEvent):int {
for(var key:String in KEY_CODE)
if (event.keyCode == KEY_CODE[key])
return KEYS[key];
return 0;
}
public function onKeyDown(event:KeyboardEvent):void {
var changedKeyFlag:int = readKeyFlag(event);
pushed |= changedKeyFlag;
}
public function onKeyUp(event:KeyboardEvent):void {
var changedKeyFlag:int = readKeyFlag(event);
pushed ^= changedKeyFlag;
}
}
class Token implements IToken {
public function get id():int { return _id }
public function get x():int { return _parent == null ? _x : _x + _parent.x }
public function set x(value:int):void { _x = value }
public function get y():int { return _parent == null ? _y : _y + _parent.y }
public function set y(value:int):void { _y = value }
public function get vx():int { return _vx }
public function get vy():int { return _vy }
public function get direction():int { return _direction }
public function get speed():int { return _speed }
public function get accelDirection():int { return _accelDirection }
public function set accelDirection(value:int):void { _accelDirection = value }
public function get accelSpeed():int { return _accelSpeed }
public function set accelSpeed(value:int):void { _accelSpeed = value}
public function get frame():int { return _frame }
public function get isVanished():Boolean {return _isVanished}
protected var _id:int, _frame:int;
protected var _x:int, _y:int, _vx:int, _vy:int;
protected var _direction:int, _speed:int, _accelDirection:int, _accelSpeed:int;
protected var _isVanished:Boolean;
protected var _parent:IToken;
public function set parent(value:IToken):void { _parent = value }
private var _motionGroup:Array; /* Array of MotionData */
private var _currentMotion:MotionData;
private var _motionFrame:int, _motionState:int;
private var _shotGroup:Array; /* Array of ShotData */
private static var tmpPoint:Point = new Point();
public static const FIELD_SCALE:int = 4;
private static const FIELD_WIDTH:int = Main.SCREEN_WIDTH << FIELD_SCALE;
private static const FIELD_HEIGHT:int = Main.SCREEN_HEIGHT << FIELD_SCALE;
public static const DEG_CIRCLE:int = 360;
private static const DEG_HALF:int = DEG_CIRCLE / 2;
private static const DEG_SCALE:int = 100;
private static const PI_DEG_HALF:Number = Math.PI / DEG_HALF;
private static const PI_HALF:Number = Math.PI / 2;
protected static const bitmapDataTable:Vector.<BitmapData> = createBitmapTable();
public static function createBitmapTable():Vector.<BitmapData> {
var table:Vector.<BitmapData> = new Vector.<BitmapData>();
table.push(new BitmapData(1, 1, true, 0)); // null
table.push(new BitmapData(16, 16, true, 0xFFFF4500)); // player
table.push(new BitmapData(16, 16, true, 0xFF606000)); // shot
table.push(new BitmapData(6, 6, true, 0xFFFFD700)); // effect1
table.push(new BitmapData(6, 6, true, 0xFF88672C)); // effect2
table.push(new BitmapData(12, 12, true, 0xFFD040A0)); // effect3
table.push(new BitmapData(16, 16, true, 0xFFFFFFFF)); // bullet1 (no use)
table.push(new BitmapData(16, 16, true, 0xFFFF5050)); // bullet2 (no use)
table.push(new BitmapData(16, 16, true, 0xFFFFDD50)); // bullet3
table.push(new BitmapData(16, 16, true, 0xFFFFEEEE)); // bullut4
table.push(new BitmapData(20, 20, true, 0xFFEE2050)); // child enemy1
table.push(new BitmapData(32, 32, true, 0xFF5050FF)); // enemy1
table.push(new BitmapData(80, 64, true, 0xFF50AAFF)); // enemy2
table.push(new BitmapData(160, 80, true, 0xFFD050FF)); // enemy3
return table;
}
public function initialize(id:int=0, x:int=0, y:int=0, direction:int=0, speed:int=0, motionID:int=0, shotID:int=0):void {
_id = id; _x = x; _y = y; _direction = direction; _speed = speed;
_frame = 0; _isVanished = false; _accelDirection = 0; _accelSpeed = 0;
setVelocity();
_currentMotion = null; _motionGroup = null;
_motionFrame = 0; _motionState = 0; _shotGroup = null; _parent = null;
if (motionID != 0){
_motionGroup = Main.root.motionManager.getDataGroup(motionID);
setMotion();
}
if (shotID != 0){
_shotGroup = Main.root.shotManager.getDataGroup(shotID);
}
}
public function update():void {
_frame++;
motion();
if (_accelSpeed != 0 || _accelDirection != 0) {
setMovement(_direction + _accelDirection, _speed + _accelSpeed);
}
_x += _vx; _y += _vy;
if ((_frame > 8 && _parent == null && (_x < 0 || _x >= FIELD_WIDTH || _y < 0 || _y >= FIELD_HEIGHT)) // out of field
|| (_parent != null && _parent.isVanished)) // parent vanished
_isVanished = true;
else
shot();
}
public function draw(buffer:BitmapData):void {
var bitmapData:BitmapData = bitmapDataTable[_id];
tmpPoint.x = (_x >> FIELD_SCALE) - (bitmapData.width >> 1);
tmpPoint.y = (_y >> FIELD_SCALE) - (bitmapData.height >> 1);
if (_parent != null)
{
tmpPoint.x += _parent.x >> FIELD_SCALE;
tmpPoint.y += _parent.y >> FIELD_SCALE;
}
buffer.copyPixels(bitmapData, bitmapData.rect , tmpPoint, null, null, true);
}
public function setMovement(d:int, s:int) :void {
_direction = d % DEG_CIRCLE;
_speed = s;
setVelocity();
}
public function set direction(d:int) :void {
_direction = d % DEG_CIRCLE;
setVelocity();
}
public function set speed(s:int) :void {
_speed = s;
setVelocity();
}
protected function setVelocity():void {
_vx = (Math.floor(Math.sin(_direction * PI_DEG_HALF) * DEG_SCALE) / DEG_SCALE) * _speed;
_vy = ( -Math.floor(Math.sin(_direction * PI_DEG_HALF + PI_HALF) * DEG_SCALE) / DEG_SCALE) * _speed;
}
protected function setMotion():void {
_currentMotion = _motionGroup[_motionState];
_accelDirection = _currentMotion.accelDirection != int.MAX_VALUE ? _currentMotion.accelDirection : 0;
_accelSpeed = _currentMotion.accelSpeed != int.MAX_VALUE ? _currentMotion.accelSpeed : 0;
if (_currentMotion.direction != int.MAX_VALUE)
_direction = _currentMotion.target ? _currentMotion.direction : _currentMotion.direction + getAimDirection();
if (_currentMotion.speed != int.MAX_VALUE)
_speed = _currentMotion.speed;
setVelocity();
}
protected function motion():void {
if (_currentMotion != null) {
if (_currentMotion.frame <= _motionFrame) {
if (_motionState < _motionGroup.length - 1) {
_motionState = _currentMotion.goto == 0 ? _motionState+1 : _currentMotion.goto-1;
setMotion();
_motionFrame = 0;
}
else {
_currentMotion = null;
}
}
else if (_currentMotion.target) {
direction = getAimDirection();
}
}
_motionFrame++;
}
protected function shot():void {
if (_shotGroup != null) {
var startFrame:int = 0;
var n:int = _shotGroup.length;
for (var i:int = 0; i < n; i++ ) {
var shotData:ShotData = _shotGroup[i];
var f:int = _frame - shotData.startFrame + startFrame;
if ((f >= 0) && (_frame <= startFrame + shotData.endFrame) && (f % shotData.stepFrame == 0))
Main.root.shotManager.shot(this, shotData);
startFrame += shotData.startFrame;
}
}
}
protected function getAimDirection():int {
return ShotManager.getAimDirection(x, y);
}
public function damage():void {
}
public function vanish():void {
_isVanished = true;
}
public function isCollision(x:int, y:int):Boolean {
return false;
}
}
class Effect extends Token {
private var _gravity:int = 0;
private var _aliveFrame:int = 0;
override public function initialize(id:int = 0, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0, motionID:int = 0, shotID:int = 0):void {
super.initialize(id, x, y, direction, speed, motionID, shotID);
if (id == 3) { _gravity = 4; _aliveFrame = 90 }
else if (id == 4) { _gravity = 2; _aliveFrame = 15 }
else if (id == 5) { _gravity = 4; _aliveFrame = 90 }
}
override public function update():void {
super.update();
if (_frame > _aliveFrame)
vanish();
_y += _frame * _gravity;
}
}
class Bullet extends Token {
protected var _hitTopX:int;
protected var _hitTopY:int;
protected var _hitBottomX:int;
protected var _hitBottomY:int;
override public function initialize(id:int = 0, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0, motionID:int = 0, shotID:int = 0):void {
super.initialize(id, x, y, direction, speed, motionID, shotID);
var bitmapData:BitmapData = bitmapDataTable[_id];
_hitTopX = -(bitmapData.width >> 1) << Token.FIELD_SCALE;
_hitTopY = -(bitmapData.height >> 1) << Token.FIELD_SCALE;
_hitBottomX = (bitmapData.width >> 1) << Token.FIELD_SCALE;
_hitBottomY = (bitmapData.height >> 1) << Token.FIELD_SCALE;
}
override public function isCollision(cx:int, cy:int):Boolean {
return (x + _hitTopX < cx) && (y + _hitTopY < cy) && (x + _hitBottomX > cx) && (y + _hitBottomY > cy);
}
}
class Enemy extends Bullet {
private var _life:int = 0;
override public function initialize(id:int = 0, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0, motionID:int = 0, shotID:int = 0):void {
super.initialize(id, x, y, direction, speed, motionID, shotID);
_life = 3;
if (id == 12)
_life += 10;
else if (id == 10)
_life = 1;
else if (id == 13)
_life += 40;
_hitTopX -= 16 << Token.FIELD_SCALE; _hitTopY -= 16 << Token.FIELD_SCALE;
_hitBottomX += 16 << Token.FIELD_SCALE; _hitBottomY += 16 << Token.FIELD_SCALE;
}
override public function damage():void {
_life--;
Main.root.addScore(10);
if (_life == 0) {
n = _parent == null ? 12 + (id - 11) * 8 : 4;
for (i = 0; i < n; i++ ) {
Main.root.addEffect(5, x, y, 240/n*i + int(Main.root.random() % 30) + 210, 64 + int(Main.root.random() % 64), 2)
}
Main.root.addScore(_parent == null ? (id - 10) * 1000 : 5000);
vanish();
}
else
{
var n:int = 4;
for (var i:int = 0; i < n; i++ ) {
Main.root.addEffect(4, x, y, 120/n*i + int(Main.root.random() % 60) + 120, 8 + int(Main.root.random() % 64), 1)
}
}
}
}
class Player extends Token {
public static const MAX_X:int = (Main.SCREEN_WIDTH - 8) << Token.FIELD_SCALE;
public static const MIN_X:int = 8 << Token.FIELD_SCALE;
public static const MAX_Y:int = (Main.SCREEN_HEIGHT - 8) << Token.FIELD_SCALE;
public static const MIN_Y:int = 8 << Token.FIELD_SCALE;
private static const COMMAND_DIRECTIONS:Object = { 1:0, 2:90, 4:180, 8:270, 3:45, 6:135, 9:315, 12:225 }
private static const MOVE_SPEED:int = 32;
private static const MOVE_MAXSPEED:int = 96;
private static const MOVE_BRAKE:int = 32;
private static const SHOT_SPEED:int = 196;
private static const DAMAGED_INVINCIBLE_FRAME:int = 30;
public function get isInvincible():Boolean { return _invincibleFrame > 0 }
private var _invincibleFrame:int;
private var _shotFrame:int;
private var _shotFlag:Boolean;
override public function initialize(id:int = 0, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0, motionID:int = 0, shotID:int = 0):void
{
super.initialize(id, x, y, direction, speed, motionID, shotID);
_invincibleFrame = 0;
_shotFrame = 0;
_shotFlag = false;
}
override public function update():void {
super.update();
command();
if (_invincibleFrame > 0) _invincibleFrame--;
}
override public function draw(buffer:BitmapData):void {
if(_invincibleFrame == 0 || _invincibleFrame % 4 == 0)
super.draw(buffer);
}
override protected function shot():void {
if (_shotFrame != 0) {
if (_shotFrame > 0) {
if (_shotFrame > 12) { _shotFrame = -12; _shotFlag = false; }
else if(_shotFrame % 4 == 1){
Main.root.addShot(2, _x - 256, _y - 32, 0, SHOT_SPEED);
Main.root.addShot(2, _x + 256, _y - 32, 0, SHOT_SPEED);
}
}
_shotFrame++;
if (_shotFrame == 0){
if(_shotFlag) {
_shotFrame = 1; _shotFlag = false;
}
else if (((Main.root.inputKey.pushed & InputKey.KEY_SHOT) != 0)) {
_shotFrame = 1; _shotFlag = false;
}
}
}
}
private function command():void {
var pushedKey:int = Main.root.inputKey.pushed;
var p:int = pushedKey & (InputKey.KEY_UP | InputKey.KEY_RIGHT | InputKey.KEY_DOWN | InputKey.KEY_LEFT)
if (p in COMMAND_DIRECTIONS) {
if (_speed < MOVE_MAXSPEED) _speed += MOVE_SPEED;
direction = COMMAND_DIRECTIONS[p];
setVelocity();
}
else if (_speed > 0) {
var b:int = MOVE_BRAKE;
_speed -= b;
if (_speed < 0)
_speed = 0;
setVelocity();
}
if (_x < MIN_X) { _x = MIN_X }
else if (_x > MAX_X) { _x = MAX_X }
if (_y < MIN_Y) {_y = MIN_Y}
else if (_y > MAX_Y) { _y = MAX_Y }
if ((pushedKey & InputKey.KEY_SHOT) != 0) {
if (_shotFrame == 0)
_shotFrame++;
else
_shotFlag = true;
}
}
override public function damage():void {
_invincibleFrame = DAMAGED_INVINCIBLE_FRAME;
var n:int = 16;
for (var i:int = 0; i < n; i++ ) {
Main.root.addEffect(3, _x, _y, 90/n*i + int(Main.root.random() % 30) + 315, 16 + int(Main.root.random() % 96), 1)
}
}
}
class DataContainer{
protected static const VALUE_TABLE:Object = createValueTable();
protected static function createValueTable():Object {
var i:int; var table:Object = { };
var ca:int = "a".charCodeAt(0); var cA:int = "A".charCodeAt(0);
for (i = 0; i < 10; i++) { table[String(i)] = i }
for (i = 0; i < 26; i++ ) { table[String.fromCharCode(ca + i)] = 10 + i}
for (i = 0; i < 26; i++ ) { table[String.fromCharCode(cA + i)] = 36 + i}
table['-'] = 62; table['_'] = 63; table['*'] = int.MAX_VALUE;
return table;
}
protected function getDeg(value:int):int{return value != int.MAX_VALUE ? Math.floor(value * Token.DEG_CIRCLE / 64) : value}
protected function getInteger(value:int):int {return value != int.MAX_VALUE ? (value < 32 ? value : -(value - 31)) : value}
protected function getInteger2(value:int):int { return value != int.MAX_VALUE ? (value < 32 ? value * 2: -(value - 31)) * 2 : value }
public function setData(data:String):void { }
}
class DataManager {
private var _dataClass:Class;
protected var _dataList:Array = [];
public function DataManager(data:String, dataClass:Class) {
_dataClass = dataClass;
var groupTable:Array = data.replace(/\s/g, "").split(/,/);
var n:int = groupTable.length;
for (var i:int = 0; i < n; i++) {
var elementList:Array = [];
var elementDataList:Array = String(groupTable[i]).split(/\|/);
var m:int = elementDataList.length;
for (var j:int = 0; j < m; j++ ) {
var element:DataContainer = new dataClass();
element.setData(elementDataList[j]);
elementList.push(element);
}
_dataList[i] = elementList;
}
}
public function getDataGroup(dataID:int):Array {
return _dataList[dataID-1];
}
}
class StageEnemyData extends DataContainer{
public var id:int;
public var x:int, y:int;
public var direction:int, speed:int;
public var motion:int, shot:int;
public var children:int;
override public function setData(data:String):void {
id = VALUE_TABLE[data.charAt(0)];
x = Math.floor(getInteger(VALUE_TABLE[data.charAt(1)]) * Main.SCREEN_WIDTH / 32) << Token.FIELD_SCALE;
y = Math.floor(getInteger(VALUE_TABLE[data.charAt(2)]) * Main.SCREEN_HEIGHT / 32) << Token.FIELD_SCALE;
direction = getDeg(VALUE_TABLE[data.charAt(3)]); speed = getInteger2(VALUE_TABLE[data.charAt(4)]);
motion = VALUE_TABLE[data.charAt(5)]; shot = VALUE_TABLE[data.charAt(6)];
children = VALUE_TABLE[data.charAt(7)];
}
}
class StageEnemyFormationData extends DataContainer {
public var startFrame:int, endFrame:int;
public var stepFrame:int, num:int;
public var id:int;
public var stepX:int, stepY:int;
public var stepDirection:int, stepSpeed:int;
override public function setData(data:String):void {
startFrame = VALUE_TABLE[data.charAt(0)] * 64 + VALUE_TABLE[data.charAt(1)];
stepFrame = VALUE_TABLE[data.charAt(2)] * 8;
num = VALUE_TABLE[data.charAt(3)];
endFrame = startFrame + stepFrame * num;
id = VALUE_TABLE[data.charAt(4)];
stepX = getInteger2(VALUE_TABLE[data.charAt(5)]) << Token.FIELD_SCALE;
stepY = getInteger2(VALUE_TABLE[data.charAt(6)]) << Token.FIELD_SCALE;
stepDirection = getDeg(VALUE_TABLE[data.charAt(7)]);
stepSpeed = getInteger2(VALUE_TABLE[data.charAt(8)]);
}
}
class StageManager extends DataManager {
private var _stageEnemyTable:Array = [];
private var _enemyManager:DataManager;
private var _currentStage:int = 0;
private var _activeFormations:Array = [];
public function StageManager(data:String, enemyData:String) {
super(data, StageEnemyFormationData);
_enemyManager = new DataManager(enemyData, StageEnemyData);
var n:int = _dataList.length;
for (var i:int = 0; i < n; i++ ) {
var frameEnemyTable:Object = { };
var m:int = _dataList[i].length
for (var j:int = 0; j < m; j++ ) {
var formation:StageEnemyFormationData = _dataList[i][j];
if (!(formation.startFrame in frameEnemyTable)) {
frameEnemyTable[formation.startFrame] = [];
}
(frameEnemyTable[formation.startFrame] as Array).push(formation);
}
_stageEnemyTable[i] = frameEnemyTable;
}
}
public function initialize():void {
_activeFormations = [];
}
public function update(frame:int):void {
var stageEnemy:Object = _stageEnemyTable[_currentStage];
if (frame in stageEnemy) {
var formations:Array = stageEnemy[frame];
var n:int = formations.length;
for (var i:int = 0; i < n; i++ ) {
_activeFormations.push(formations[i]);
}
}
n = _activeFormations.length;
for (i = 0; i < n; i++ ) {
var formation:StageEnemyFormationData = _activeFormations[i];
if (frame >= formation.endFrame){
_activeFormations.splice(i, 1); n--; i--;
}
else if ((frame - formation.startFrame) % formation.stepFrame == 0){
createFormationEnemy(formation, int((frame - formation.startFrame) / formation.stepFrame));
}
}
}
private function createFormationEnemy(formation:StageEnemyFormationData, step:int):void {
var enemys:Array = _enemyManager.getDataGroup(formation.id);
var n:int = enemys.length;
for (var i:int = 0; i < n; i++ ){
var enemy:StageEnemyData = enemys[i];
var enemyToken:Token = createEnemy(enemy);
enemyToken.x += formation.stepX * step; enemyToken.y += formation.stepY * step;
enemyToken.direction += formation.stepDirection * step; enemyToken.speed += formation.stepSpeed * step;
}
}
private function createEnemy(enemy:StageEnemyData, parent:IToken = null):Token {
var token:Token = Main.root.addEnemy(enemy.id, enemy.x, enemy.y, enemy.direction, enemy.speed, enemy.motion, enemy.shot);
if (parent != null)
token.parent = parent;
if (enemy.children != 0) {
var children:Array = _enemyManager.getDataGroup(enemy.children);
var n:int = children.length;
for (var i:int = 0; i < n; i++ )
createEnemy(children[i], token);
}
return token;
}
}
class MotionData extends DataContainer
{
public var frame:int;
public var direction:int, speed:int;
public var accelDirection:int, accelSpeed:int;
public var goto:int, target:Boolean;
override public function setData(data:String):void {
frame = VALUE_TABLE[data.charAt(0)] * 2;
direction = getDeg(VALUE_TABLE[data.charAt(1)]);
speed = getInteger2(VALUE_TABLE[data.charAt(2)]);
accelDirection = getDeg(VALUE_TABLE[data.charAt(3)]);
accelSpeed = getInteger(VALUE_TABLE[data.charAt(4)]);
goto = VALUE_TABLE[data.charAt(5)];
target = VALUE_TABLE[data.charAt(6)] != 0;
}
}
class ShotData extends DataContainer
{
public var id:int, func:int, motion:int, shot:int;
public var x:int, y:int, direction:int, speed:int;
public var aim:Boolean, deg:int, accelDeg:int, frame:int;
public var len:int, num:int, way:int, wide:int;
public var startFrame:int, stepFrame:int, endFrame:int;
override public function setData(data:String):void {
id = VALUE_TABLE[data.charAt(0)];
func = VALUE_TABLE[data.charAt(1)];
motion = VALUE_TABLE[data.charAt(2)]; shot = VALUE_TABLE[data.charAt(3)];
x = getInteger(VALUE_TABLE[data.charAt(4)]) << Token.FIELD_SCALE;
y = getInteger(VALUE_TABLE[data.charAt(5)]) << Token.FIELD_SCALE;
direction = getDeg(VALUE_TABLE[data.charAt(6)]);
speed = getInteger2(VALUE_TABLE[data.charAt(7)]);
aim = VALUE_TABLE[data.charAt(8)] != 0;
deg = getDeg(VALUE_TABLE[data.charAt(9)]); accelDeg = getDeg(VALUE_TABLE[data.charAt(10)]);
frame = VALUE_TABLE[data.charAt(11)];
len = VALUE_TABLE[data.charAt(12)]; num = VALUE_TABLE[data.charAt(13)];
way = VALUE_TABLE[data.charAt(14)]; wide = VALUE_TABLE[data.charAt(15)];
startFrame = VALUE_TABLE[data.charAt(16)] * 20;
stepFrame = VALUE_TABLE[data.charAt(17)];
endFrame = VALUE_TABLE[data.charAt(18)] * 20;
}
}
class ShotManager extends DataManager{
private static const PI:Number = Math.PI;
private static const SHOT_FUNCS:Vector.<Function> = Vector.<Function>([shotWay, shotLineWay, shotCurve, shotLineToArrow, shotCircle, shotRandom]);
public function ShotManager(data:String) {
super(data, ShotData);
}
public function shot(token:IToken, shotData:ShotData):void {
SHOT_FUNCS[shotData.func](token, shotData);
}
private static function shotBullet(id:int, x:int, y:int, direction:int, speed:int, motionID:int, shotID:int):Token {
return Main.root.addBullet(id, x, y, direction, speed, motionID, shotID);
}
private static function getShotDirection(data:ShotData, bx:int, by:int, direction:int):int {
return data.aim ? data.direction + getAimDirection(bx, by) + direction : data.direction + direction;
}
private static function getDirectionX(direction:int):Number {
return int(Math.sin((direction / 180) * PI) * 100) / 100;
}
private static function getDirectionY(direction:int):Number {
return -int(Math.sin((direction / 180) * PI + PI / 2) * 100) / 100;
}
public static function getAimDirection(x:int, y:int):int {
var player:Player = Main.root.player;
return Math.floor(((Math.atan2(player.y - y, player.x - x) * 180 / PI) + 90)) % 360;
}
private static function shotWay(token:IToken, data:ShotData, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0):void {
if (data.accelDeg != 0) {
var maxFrame:int = data.frame == 0 ? Token.DEG_CIRCLE / data.accelDeg : data.frame;
direction += token.frame % maxFrame * data.accelDeg;
}
var bx:int = token.x + data.x; var by:int = token.y + data.y;
var dir:int = getShotDirection(data, bx, by, direction);
if (data.way % 2 == 1)
shotBullet(data.id, bx, by, dir, data.speed + speed, data.motion, data.shot);
var n:int = data.way / 2;
for (var i:int = 1; i <= n; i++) {
shotBullet(data.id, bx, by, dir + data.deg * i, data.speed + speed, data.motion, data.shot);
shotBullet(data.id, bx, by, dir - data.deg * i, data.speed + speed, data.motion, data.shot);
}
}
private static function shotLineWay(token:IToken, data:ShotData, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0):void {
var bx:int = token.x + data.x; var by:int = token.y + data.y;
var dir:int = getShotDirection(data, bx, by, direction);
if (data.way % 2 == 1) { shotLineBullet(bx, by, dir, data, x, y, direction, speed) }
var n:int = data.way >> 1;
for (var i:int = 1; i <= n; i++) {
shotLineBullet(bx, by, dir + data.deg * i, data, x, y, direction, speed);
shotLineBullet(bx, by, dir - data.deg * i, data, x, y, direction, speed);
}
function shotLineBullet(bx:int, by:int, dir:int, data:ShotData, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0):void
{
var vx:int = getDirectionX(dir) * data.wide;
var vy:int = getDirectionY(dir) * data.wide;
for (var i:int = 0; i < data.num; i++ ){
var bullet:Token = shotBullet(data.id, bx + vx * i, by + vy * i, dir, data.speed + speed - i, data.motion, data.shot);
bullet.accelSpeed = data.len * i;
}
}
}
private static function shotCurve(token:IToken, data:ShotData, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0):void {
var bx:int = token.x + data.x; var by:int = token.y + data.y;
var dir:int = getShotDirection(data, bx, by, direction);
var n:int = data.num / 2;
for (var i:int = 0; i < data.num; i++) {
var bullet:Token = shotBullet(data.id, bx, by, dir + ((i + 1) % data.num - n) * data.wide, data.speed + speed - Math.abs(((i + 1) % data.num - n) * 2), data.motion, data.shot);
bullet.accelSpeed = ((i + 1) % data.num - n) * data.len;
}
}
private static function shotLineToArrow(token:IToken, data:ShotData, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0):void {
var bx:int = token.x + data.x; var by:int = token.y + data.y;
var dir:int = getShotDirection(data, bx, by, direction);
var dir2:int = dir + 90;
var vx:int = (getDirectionX(dir2) * data.wide) << Token.FIELD_SCALE;
var vy:int = (getDirectionY(dir2) * data.wide) << Token.FIELD_SCALE;
if (data.num % 2 == 1)
shotBullet(data.id, bx, by, dir, data.speed + speed, data.motion, data.shot);
var n:int = data.num / 2;
var bullet:Token;
for (var i:int = 1; i <= n; i++) {
bullet = shotBullet(data.id, bx+vx*i, by+vy*i, dir, data.speed + speed, data.motion, data.shot)
bullet.accelSpeed += i * 2;
bullet = shotBullet(data.id, bx-vx*i, by-vy*i, dir, data.speed + speed, data.motion, data.shot)
bullet.accelSpeed += i * 2;
}
}
private static function shotCircle(token:IToken, data:ShotData, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0):void {
var bx:int = token.x + data.x; var by:int = token.y + data.y;
var dir:int = getShotDirection(data, bx, by, direction);
var degUnit:int = 360 / data.num;
for (var i:int = 0; i < data.num; i++ ) {
var vx:int = (getDirectionX(degUnit*i) * data.wide * 2) << Token.FIELD_SCALE;
var vy:int = (getDirectionY(degUnit*i) * data.wide * 2) << Token.FIELD_SCALE;
var bullet:Token = shotBullet(data.id , bx + vy, by + vx, dir, data.speed + speed, data.motion, data.shot);
}
}
private static function shotRandom(token:IToken, data:ShotData, x:int = 0, y:int = 0, direction:int = 0, speed:int = 0):void {
var bx:int = token.x + data.x; var by:int = token.y + data.y;
var dir:int = getShotDirection(data, bx, by, direction);
var deg2:int = data.deg >> 1;
for (var i:int = 0; i < data.num; i++ ) {
var bullet:Token = shotBullet(data.id, bx, by, dir + Main.root.random() % data.deg - deg2, data.speed + speed + Main.root.random() % data.wide, data.motion, data.shot);
if(data.len != 0)
bullet.accelSpeed = Main.root.random() % data.len;
}
}
}
class TokenContainer
{
private var _tokenClass:Class;
private var _layer:BitmapData;
private var _tokens:Vector.<IToken> = new Vector.<IToken>();
public function get tokens():Vector.<IToken> { return _tokens; }
private var _oldTokens:Vector.<Token> = new Vector.<Token>();
public function TokenContainer(tokenClass:Class, layer:BitmapData) {
_tokenClass = tokenClass; _layer = layer;
}
public function addToken(id:int=0, x:int=0, y:int=0, direction:int=0, speed:int=0, motionID:int=0, shotID:int=0):Token {
var token:Token = _oldTokens.length > 0 ? _oldTokens.pop() : new _tokenClass();
token.initialize(id, x, y, direction, speed, motionID, shotID);
_tokens.push(token);
return token;
}
public function update():void {
var n:int = _tokens.length;
for (var i:int = 0; i < n; i++) {
var token:Token = tokens[i] as Token;
token.update();
if (token.isVanished) {
tokens.splice(i, 1); n--; i--;
_oldTokens.push(token);
}
else{
token.draw(_layer);
}
}
}
public function clear():void {
_tokens = new Vector.<IToken>();
}
}
class LinearCongruentialGenerator {
private static const A:Number = 1664525;
private static const C:Number = 1013904223;
private static const M:Number = 0x100000000;
private var x:Number;
public function LinearCongruentialGenerator(seed:Number = 1.0):void {
initialize(seed);
}
public function initialize(seed:Number = 1.0):void {
x = seed;
}
public function random():uint {
x = (x * A + C) % M;
return x;
}
}