forked from: 爆裂カブトムシ

by medadotter
爆裂カブトムシっぽい何か。そろそろインタラクション関連の処理が重い。
♥0 | Line 428 | Modified 2012-03-17 02:32:17 | MIT License
play

ActionScript3 source code

/**
 * Copyright medadotter ( http://wonderfl.net/user/medadotter )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/a2Ut
 */

package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.geom.Point;
    import flash.ui.Keyboard;
    
    /**
     * 爆裂カブトムシっぽい何か。そろそろ処理が思い。updateEnemys、updateBulletsに纏わる
     * @author DT
     */
    [SWF(width="465",height="465")]
    
    public class STGMain extends Sprite
    {
        public function STGMain()
        {
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
            var world:World = new World(stage.stageWidth, stage.stageHeight);
            addChild(world);
            world.x = (stage.stageWidth - world.stageWidth) / 2;
            world.y = (stage.stageHeight - world.stageHeight) / 2;
            
            addEventListener(Event.ENTER_FRAME, world.onEnterFrame);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, world.onKeyDown);
        }
    
    }

}
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.geom.Point;
import flash.ui.Keyboard;

class World extends Sprite
{
    private var _stageWidth:Number;
    private var _stageHeight:Number;
    
    private var player:Player;
    private var enemies:Vector.<Enemy> = new Vector.<Enemy>();
    private var bullets:Vector.<Bullet> = new Vector.<Bullet>();
    private var velocities:Array = [];
    private var frames:uint = 0;
    private var comingRange:Number;
    
    static private const radius:Number = 5;
    static private const easing:Number = 0.1;
    static private const friction:Number = -1.0;
    
    static private const rate:Number = 4;
    static private const speed:Number = 10;
    static private const timer:Number = 16;
    
    public function World(stageWidth:Number = 465, stageHeight:Number = 465)
    {
        this.stageWidth = stageWidth;
        this.stageHeight = stageHeight;
        this.comingRange = Math.sqrt(stageWidth * stageWidth + stageHeight * stageHeight) / 2 + radius;
        makePlayer();
        
        makeVelocityTable();
    }
    
    public function onKeyDown(event:KeyboardEvent):void
    {
        if (event.keyCode == Keyboard.SPACE)
            addToBullets(shotBullet());
    }
    
    public function onEnterFrame(event:Event):void
    {
        if (frames++ % rate == 0)
            addToEnemies(makeEnemy());
        
        checkBurst();
        updatePlayer();
        updateEnemies();
        updateBullets();
    }
    
    private function checkBurst():void
    {
        for (var i:int = bullets.length - 1; i >= 0; i--)
        {
            var bullet:Bullet = bullets[i];
            for (var j:int = enemies.length - 1; j >= 0; j--)
            {
                var enemy:Enemy = enemies[j];
                if (hitCheck(bullet, enemy))
                {
                    removeFromBullets(i);
                    removeFromEnemies(j);
                    burst(enemy);
                }
            }
        }
    }
    
    private function updatePlayer():void
    {
        var mouse:Point = new Point(mouseX, mouseY);
        var dx:Number = mouse.x - player.x;
        var dy:Number = mouse.y - player.y;
        var radius:Number = player.radius;
        player.x = Math.max( /*0+*/radius, Math.min(stageWidth - radius, player.x + dx * easing));
        player.y = Math.max( /*0+*/radius, Math.min(stageHeight - radius, player.y + dy * easing));
    }
    
    private function updateEnemies():void
    {
        for (var i:int = enemies.length - 1; i >= 0; i--)
        {
            var enemy:Enemy = enemies[i];
            enemy.update();
            reflectEnemy(enemy);
        }
    }
    
    private function updateBullets():void
    {
        for (var i:int = bullets.length - 1; i >= 0; i--)
        {
            var bullet:Bullet = bullets[i];
            bullet.update();
            if (!onArea(bullet) || !bullet.alive())
                removeFromBullets(i);
        }
    }
    
    private function hitCheck(bullet:Bullet, enemy:Enemy):Boolean
    {
        var dx:Number = enemy.x - bullet.x;
        var dy:Number = enemy.y - bullet.y;
        var lengthSQ:Number = dx * dx + dy * dy;
        var range:Number = bullet.radius + enemy.radius;
        return lengthSQ < range * range;
    }
    
    private function burst(enemy:Enemy):void
    {
        for (var i:int = 0; i < 6; i++)
        {
            var bullet:TimedBullet = new TimedBullet(timer, radius);
            
            bullet.position = enemy.position;
            bullet.velocity = velocities[i];
            
            addToBullets(bullet);
        }
    }
    
    private function onArea(bullet:Bullet):Boolean
    {
        var right:Number = bullet.x + bullet.radius;
        var left:Number = bullet.x - bullet.radius;
        var bottom:Number = bullet.y + bullet.radius;
        var top:Number = bullet.y - bullet.radius;
        //完全に境界オーバするまで。
        if (right >= 0 && left < stageWidth && bottom >= 0 && top < stageHeight)
            return true;
        return false;
    }
    
    private function makeEnemy():Enemy
    {
        var enemy:Enemy = new Enemy(radius, Math.random() * 0xffffff);
        var angle:Number = (Math.random() - 0.5) * (Math.PI - Math.PI / 6) - Math.PI / 2;
        enemy.x = comingRange * Math.cos(angle) + stageWidth / 2;
        enemy.y = comingRange * Math.sin(angle) + stageHeight / 2;
        
        var tx:Number = Math.random() * stageWidth;
        var ty:Number = stageHeight / 2;
        var dx:Number = tx - enemy.x;
        var dy:Number = ty - enemy.y;
        var len:Number = Math.sqrt(dx * dx + dy * dy);
        enemy.velocity.x = speed * dx / len;
        enemy.velocity.y = speed * dy / len;
        
        return enemy;
    }
    
    private function reflectEnemy(enemy:Enemy):void
    {
        //radius考慮してないので注意。
        var prevX:Number = enemy.x - enemy.velocity.x;
        var prevY:Number = enemy.y - enemy.velocity.y;
        var radius:Number = enemy.radius;
        if (prevX - radius > 0 && enemy.x - radius < 0)
        {
            enemy.x = /*2 * 0*/ -enemy.x + 2 * radius;
            enemy.velocity.x *= friction;
        }
        else if (prevX + radius < stageWidth && enemy.x + radius > stageWidth)
        {
            enemy.x = 2 * stageWidth - enemy.x - 2 * radius;
            enemy.velocity.x *= friction;
        }
        
        if (prevY - radius > 0 && enemy.y - radius < 0)
        {
            enemy.y = /*2 * 0*/ -enemy.y + 2 * radius;
            enemy.velocity.y *= friction;
        }
        else if (prevY + radius < stageHeight && enemy.y + radius > stageHeight)
        {
            enemy.y = 2 * stageHeight - enemy.y - 2 * radius;
            enemy.velocity.y *= friction;
        }
    
    }
    
    private function shotBullet():Bullet
    {
        var bullet:Bullet = new Bullet(radius);
        bullet.x = player.x;
        bullet.y = player.y - player.radius
        bullet.velocity.y = -speed;
        return bullet;
    }
    
    private function makePlayer():void
    {
        player = new Player(radius);
        player.x = stageWidth / 2;
        player.y = stageHeight - player.height / 2;
        
        addChild(player);
    }
    
    private function addToEnemies(enemy:Enemy):void
    {
        enemies.push(enemy);
        addChild(enemy);
    }
    
    private function removeFromEnemies(index:int):void
    {
        removeChild(enemies[index]);
        enemies.splice(index, 1);
    }
    
    private function addToBullets(bullet:Bullet):void
    {
        bullets.push(bullet);
        addChild(bullet);
    }
    
    private function removeFromBullets(index:int):void
    {
        removeChild(bullets[index]);
        bullets.splice(index, 1);
    }
    
    private function makeVelocityTable():void
    {
        for (var i:int = 0; i < 6; i++)
        {
            var vel:Point = new Point();
            vel.x = speed * Math.cos(i * Math.PI / 3);
            vel.y = speed * Math.sin(i * Math.PI / 3);
            velocities[i] = vel;
        }
    }
    
    public function get stageWidth():Number
    {
        return _stageWidth;
    }
    
    public function set stageWidth(value:Number):void
    {
        _stageWidth = value;
    }
    
    public function get stageHeight():Number
    {
        return _stageHeight;
    }
    
    public function set stageHeight(value:Number):void
    {
        _stageHeight = value;
    }

}

class Actor extends Sprite
{
    private var _position:Point = new Point();
    private var _velocity:Point = new Point();
    private var _radius:Number;
    
    /**
     * @param    radius 当たり判定などに使う半径です。
     */
    public function Actor(radius:Number)
    {
        this.radius = radius;
    }
    
    public function get radius():Number
    {
        return _radius;
    }
    
    public function set radius(value:Number):void
    {
        _radius = value;
        draw();
    }
    
    /**
     * 存在を描画します。中身は空なので派生クラスでオーバーライドすることが必要です。
     */
    protected function draw():void
    {
    }
    
    /**
     * 座標に速度を加算します。
     */
    public function update():void
    {
        x += velocity.x;
        y += velocity.y;
    }
    
    public function alive():Boolean
    {
        return true;
    }
    
    /**
     * x座標を取得します。内部的にPoint型のデータメンバを使用しているので、twipsを越えた精度を持ちますが、
     * setterはSpriteのデータメンバから取得するので精度はtwipsまでです。
     */
    override public function set x(value:Number):void
    {
        position.x = value;
        super.x = position.x;
    }
    
    /**
     * y座標を取得します。内部的にPoint型のデータメンバを使用しているので、twipsを越えた精度を持ちますが、
     * setterはSpriteのデータメンバから取得するので精度はtwipsまでです。
     */
    override public function set y(value:Number):void
    {
        position.y = value;
        super.y = position.y;
    }
    
    /**
     * 速度vxを取得します。velocity.xの簡略ですが、プロパティxが存在することとの整合のためです。
     */
    public function get vx():Number
    {
        return velocity.x;
    }
    
    public function set vx(value:Number):void
    {
        velocity.x = value;
    }
    
    /**
     * 速度vyを取得します。velocity.yの簡略ですが、プロパティyが存在することとの整合のためです。
     */
    public function get vy():Number
    {
        return velocity.y;
    }
    
    public function set vy(value:Number):void
    {
        velocity.y = value;
    }
    
    public function get position():Point
    {
        return _position;
    }
    
    public function set position(value:Point):void
    {
        _position = value;
        super.x = _position.x;
        super.y = _position.y;
    }
    
    public function get velocity():Point
    {
        return _velocity;
    }
    
    public function set velocity(value:Point):void
    {
        _velocity = value;
    }

}

class Player extends Actor
{
    
    public function Player(radius:Number)
    {
        super(radius);
    }
    
    override protected function draw():void
    {
        graphics.lineStyle(0);
        graphics.moveTo(0, -5);
        graphics.lineTo(-5, 5);
        graphics.lineTo(5, 5);
        graphics.lineTo(0, -5);
    }
}

class Enemy extends Actor
{
    private var _color:uint;
    
    public function Enemy(radius:Number = 40, color:uint = 0xff0000)
    {
        super(radius);
        this.color = color;
    }
    
    override protected function draw():void
    {
        graphics.clear();
        graphics.beginFill(color);
        graphics.drawCircle(0, 0, radius);
        graphics.endFill();
    }
    
    public function get color():uint
    {
        return _color;
    }
    
    public function set color(value:uint):void
    {
        _color = value;
        draw();
    }
}

class Bullet extends Actor
{
    private var _color:uint;
    
    public function Bullet(radius:Number = 40, color:uint = 0xff0000)
    {
        super(radius);
        this.color = color;
    }
    
    override protected function draw():void
    {
        graphics.clear();
        graphics.lineStyle(0);
        graphics.beginFill(color);
        graphics.drawCircle(0, 0, radius);
        graphics.endFill();
    }
    
    public function get color():uint
    {
        return _color;
    }
    
    public function set color(value:uint):void
    {
        _color = value;
        draw();
    }

}

class TimedBullet extends Bullet
{
    private var _timer:int = 0;
    
    public function TimedBullet(timer:int, radius:Number = 40, color:uint = 0xff0000)
    {
        this.timer = timer;
        super(radius, color);
    
    }
    
    override protected function draw():void
    {
        graphics.clear();
        graphics.lineStyle(0);
        graphics.beginFill(color);
        graphics.drawCircle(0, 0, radius);
        graphics.endFill();
    }
    
    override public function update():void
    {
        if (timer > 0)
            --timer;
        trace(timer);
        super.update();
    }
    
    override public function alive():Boolean
    {
        if (timer == 0)
            return false;
        return true;
    }
    
    public function get timer():int
    {
        return _timer;
    }
    
    public function set timer(value:int):void
    {
        _timer = value;
    }

}