2getank

by 2get forked from Wonderfl Tank Game Tank Sample 1 (diff: 257)
このコードを新着タンク一覧http://flash-games.wonderfl.net/tank/list/new
に表示させるにはinfinite-tank-entry
というタグをつけてください
♥0 | Line 203 | Modified 2011-06-03 18:58:56 | MIT License | (replaced)
play

Related images

ActionScript3 source code

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

// forked from 9re's Wonderfl Tank Game Tank Sample 1
// このコードを新着タンク一覧http://flash-games.wonderfl.net/tank/list/new
// に表示させるにはinfinite-tank-entry
// というタグをつけてください
package 
{
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.utils.setTimeout;
    import flash.utils.Timer;
    import flash.utils.getTimer;
    
    import net.wonderfl.game.infinity_tank.development.*;
    import net.wonderfl.math.*;
    import net.wonderfl.utils.SequentialLoader;
    /**
     * @author 9re
     */
    // クラス名は必ずTankにして、TankBaseクラスを拡張して下さい
    // http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/tank/TankBase.html
    public class Tank extends TankBase
    {
        private var _gunFlag:Boolean = true;
        private var _lastBulletCount:int = 0;
        private var _spTank:Sprite;
        private var _spBattery:Sprite;
        private var _ctfm:ColorTransform;
        private var _images:Vector.<Bitmap>;
        private var _gun:Bitmap;
        private var _arr:Array = [];
        private var _i:int = -1;
        private var _j:int = 0;
        private var _mat:Matrix = new Matrix(1, 0, 0, 1, 5, 15);
        
        public function Tank() 
        {
           // 弾のクラスのurlをセットしてください
            // 弾のドキュメントクラスはBulletRendererBaseクラスを拡張したBulletRendererクラスである必要があります
            // 弾の一覧は、http://flash-games.wonderfl.net/tank/list/bullets
            // にあります.
            // http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/development/BulletRendererBase.html
            _bulletRenderer = "http://swf.wonderfl.net/swf/usercode/0/04/046c/046cee45b4334c4f2dac8dfa7ec9ea2b2b2eb27d.swf";
            
            _spTank = new Sprite;
            _spBattery = new Sprite;
            
            SequentialLoader.loadImages(["http://assets.wonderfl.net/images/related_images/4/4f/4f0a/4f0af9e62a6b3ff17c6a535e52cae463b39a381c","http://assets.wonderfl.net/images/related_images/4/4f/4f0a/4f0af9e62a6b3ff17c6a535e52cae463b39a381c","http://assets.wonderfl.net/images/related_images/7/7f/7f4a/7f4a88e6b34089be3f935a0b4818d734a69c01cb"],_arr, onImageLoaded);
            _ctfm = new ColorTransform(1, 1, 1, 0);
            
            
            
            super();
        }

        private function onImageLoaded():void
        {
            _images = Vector.<Bitmap>(_arr.map(function ($ldr:Loader, $index:int, $arr:Array):Bitmap {
                var mat:Matrix = new Matrix;
                var bd:BitmapData = new BitmapData($ldr.width, $ldr.height, true, 0x00ffffff);
                bd.draw($ldr, mat);
                var bm:Bitmap = new Bitmap(bd);
                bm.x = -bm.width / 2;
                bm.y = -bm.height / 2;
                
                return bm;
            }));
            
            _gun = _images.pop();
            _gun.x = -5;
            
            _gun.y = -5;
            _spBattery.addChild(_gun);
            _i = 0;
            _images.forEach(function ($bm:Bitmap, $index:int, $vec:Vector.<Bitmap>):void {
                _spTank.addChild($bm);
            });
            _spTank.addChild(_spBattery);
        }
    
        private var hosei:Number = 0;
        private var tempPoint:WVector2D = new WVector2D(0, 0);
        private var lastFire:Number = 0;
        private var isMovingForward:Boolean = true;
        private var isMovingDirection:Boolean = true;
        private var changeCount:int = 5;
        private var lastPos:WVector2D = new WVector2D(-100, 0);
        
        // 5フレームに1度呼ばれるcallback
        // 現在のゲームの状態を見るには、_sceneオブジェクトのプロパティーを
        // 調べます.
        // @see http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/development/BattleScene.html
        override public function action():int
        {
            changeCount--;
            lastPos.subtract(_scene.myTankPosition);
            if (lastPos.normalize() < 7 && changeCount < 0) {
                isMovingForward = !isMovingForward;
                changeCount = 5;
            }
            lastPos.x = _scene.myTankPosition.x;
            lastPos.y = _scene.myTankPosition.y;
            
            // フラグによって、撃つか撃たないかを判断
            //var action:int = (_gunFlag) ? Command.FIRE : Command.TANK_MOVE_FORWARD;
            var action:int = (isMovingForward) ? Command.TANK_MOVE_FORWARD : Command.TANK_MOVE_BACKWARD;
            
            // 敵の位置を取得
            var enemyPos:WVector2D = _scene.enemyTankPosition;
            // 自分の位置を取得
            var myPos:WVector2D = _scene.myTankPosition;
            
            // 自分の位置から見た相手の相対的な位置を計算
            enemyPos.subtract(myPos);
            // 敵との距離
            var enemyDistance:Number = enemyPos.length;
            
            // 敵の速度を取得
            var enemySpeed:WVector2D = _scene.enemyTankLinearVelocity;
            // 0.5秒の位置を線形で予想
            enemySpeed.scale(0.3);
            enemyPos.add(enemySpeed);
            
            // 自分からみた敵の方向を計算する.
            var angle:Number = Math.atan2(enemyPos.y, enemyPos.x);
            // 敵の方向をコピー
            var direction:Number = angle;
            
            // 敵の方向と自分の砲台の向いている方向の差を計算
            angle -= (_scene.myTankAngle + _scene.myGunAngle);
            // 敵の方向と自分のタンクの向いている方向の差を計算
            direction -= _scene.myTankAngle;
            
            // 偏差撃ちさんのコード
            var enemyVec:WVector2D = _scene.enemyTankLinearVelocity;
            var enemyAngVel:Number = _scene.enemyTankAngularVelocity;
            var tempMat:WMatrix2D = new WMatrix2D();
            tempMat.setRotationMatrix(enemyAngVel);
            enemyVec.applyMatrix(tempMat);
            var enemyVecP:Point = new Point(enemyVec.x, enemyVec.y);
            var enemyVecNorm:Number = enemyVecP.length;
            enemyVecP.normalize(1);
            var yd:Number = enemyVecP.x * enemyPos.x + enemyVecP.y * enemyPos.y;
            var x:Number = Math.sqrt(enemyPos.x * enemyPos.x + enemyPos.y * enemyPos.y - yd * yd);
            var bulletSpeed:Number = 150 + 100 * Math.cos(hosei);
            var vd:Number = enemyVecNorm * enemyVecNorm;
            var md:Number = bulletSpeed * bulletSpeed;
            
            var alpha:Number = yd * yd * vd - (x * x + yd * yd) * (vd - md);
            var sign:int = (alpha >= 0) ? 1: -1;
            
            var meetTime:Number = sign * (yd * enemyVecNorm - Math.sqrt(sign * alpha)) / (vd - md);
            var limit:int = 1;
            if (enemyPos.length < 20) meetTime = 0;
            tempPoint = new WVector2D(enemyPos.x + meetTime * enemyVec.x, enemyPos.y + meetTime * enemyVec.y);
            while ((tempPoint.x > 600 || tempPoint.x < 0 || tempPoint.y > 550 || tempPoint.y < 0) && limit--) {
                meetTime *= 0.75;
                tempPoint = new WVector2D(enemyPos.x + meetTime * enemyVec.x, enemyPos.y + meetTime * enemyVec.y);
            }
            var angle2:Number = Math.atan2(tempPoint.y, tempPoint.x);
            angle2 -= (_scene.myGunAngle + _scene.myTankAngle);
            
            // 角度を0~2πに丸める
            angle = WMath.modulo2PI(angle2);
            direction = WMath.modulo2PI(direction);
            
            // 角度が0~πの場合は敵は砲台より右側にいる.
            if (angle <= Math.PI)
                action |= Command.GUN_TURN_RIGHT;
            // 角度がπより大きい場合は敵は砲台の左側にいる.
            else 
                action |= Command.GUN_TURN_LEFT;
            
            if (Math.abs(angle) < 0.30 || meetTime < 0.6) {
                if (getTimer() - lastFire > 400) {
                    action |= Command.FIRE;
                    lastFire = getTimer();
                    hosei += 0.2;
                }
            }
            // 角度が0~πの場合は敵は自分の向いている方向の右側にいる.
            if (direction <= Math.PI) {
                action |= Command.TANK_TURN_RIGHT;
                isMovingDirection = true;
            }
            // 角度がπより大きい場合は敵は自分の向いている方向の左側にいる.
            else { 
                action |= Command.TANK_TURN_LEFT;
                isMovingDirection = false;
            }
            
            return action;
        }
        
        private function clearGunFlag():void
        {
            _gunFlag = true;
        }
        
        // 毎フレームごとに呼ばれる描画callback
        // stageと同じ大きさのBitmapDataが渡されます.
        // 現在のゲームの状態を見るには、_sceneオブジェクトのプロパティーを
        // 調べます.
        // @see http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/development/BattleScene.html
        override public function draw(bitmapData:BitmapData):void
        {
            // 砲台の向きをセットします.
            // 砲台はタンクのSpriteの子供のスプライトです.
            _spBattery.rotation = _scene.myGunAngle * 180 / Math.PI;
            
            
            if (_i > -1) {
                _i = (_j & 1) ? 1 : 0;
                var bm:Bitmap = _images[_i];
                bm.visible = true;
                _i = 1 - _i;
                bm = _images[_i];
                bm.visible = false;
                _j++;
                _j &= 3;
            }
            
            // 単位行列にセット
            _mat.identity();
            // タンクの傾きをセット
            _mat.rotate(_scene.myTankAngle);
            // タンクの位置に平行移動. タンクのグラフィックは中心座標となっています.
            _mat.translate(_scene.myTankPosition.x, _scene.myTankPosition.y);
            
            // 一度BitmapDataをクリア
            bitmapData.colorTransform(bitmapData.rect, _ctfm);
            // BitmapDataを描画
            bitmapData.draw(_spTank, _mat, null, null, null, true);
        }
        
        // called when a bullet hits this tank
        override public function hit():void {
            // 被弾したときに呼ばれるcallbackです.
            isMovingForward = !isMovingForward;
            if (isMovingDirection)
                Command.TANK_TURN_LEFT;
            else
                Command.TANK_TURN_RIGHT;
            changeCount = 5;
        }
        
        // called when this tank fires
        override public function fire():void 
        {
            // 弾が発射される時に呼ばれるcallbackです.
        }
        
        private function bresenham(x1:int, y1:int, x2:int, y2:int):int {
            var thresh:int = 0;
            var Xunit = 1;
            var Yunit = 1;
            var Xdiff = x2 - x1;
            var Ydiff = y2 - y1;
            
            if (Xdiff < 0) {
                Xdiff = -Xdiff;
                Xunit = -1;
            }
            if (Xdiff > Ydiff) {
                for (var index:int = 0; index < Xdiff + 1; index++) {
                    todo(x1, y1);
                    x1 += Xunit;
                    thresh += Ydiff;
                    if (thresh >= Xdiff) {
                        thresh -= Xdiff;
                        y1 += Yunit;
                    }
                }
            } else {
                for (var index:int = 0; index < Ydiff + 1; index++) {
                    todo(x1, y1);
                    y1 += Yunit;
                    thresh += Ydiff;
                    if (thresh >= Ydiff) {
                        thresh -= Ydiff;
                        x1 += Xunit;
                    }
                }
            }
        }
    }
}