のっくあうと
forked from Wonderfl Tank Game Tank Sample 1 (diff: 277)
このコードを新着タンク一覧http://flash-games.wonderfl.net/tank/list/new に表示させるにはinfinite-tank-entry というタグをつけてください
♥0 |
Line 203 |
Modified 2009-10-11 07:38:49 |
MIT License
archived:2017-03-30 04:48:10
| (replaced)
ActionScript3 source code
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/bWuU
*/
// forked from 9re's Wonderfl Tank Game Tank Sample 1
// このコードを新着タンク一覧http://flash-games.wonderfl.net/tank/list/new
// に表示させるにはinfinite-tank-entry
// というタグをつけてください
package
{
// ai0
import Box2D.Common.Math.b2Vec2;
import flash.display.Bitmap;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.TimerEvent;
import flash.filters.*;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.system.Security;
import flash.utils.setTimeout;
import flash.utils.Timer;
import flash.net.*;
import net.wonderfl.game.infinity_tank.core.UserActionHandler;
import net.wonderfl.game.infinity_tank.model.*;
import net.wonderfl.game.infinity_tank.tank.TankBase;
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 _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 _arrCommands:Array = [Command.FIRE, Command.GUN_TURN_LEFT, Command.GUN_TURN_RIGHT, Command.TANK_MOVE_BACKWARD, Command.TANK_MOVE_FORWARD, Command.TANK_TURN_LEFT, Command.TANK_TURN_RIGHT];
private var _mat:Matrix = new Matrix(1, 0, 0, 1, 5, 15);
public function Tank()
{
// 弾のクラスのurlをセットしてください
// 弾のドキュメントクラスはBulletRendererBaseクラスを拡張したBulletRendererクラスである必要があります
// http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/bullet/BulletRendererBase.html
_bulletRenderer = "http://swf.wonderfl.net/swf/usercode/8/8f/8faa/8faa6f4c1148ad9a535d25bdd49b7e4d98d02030.swf";
_spTank = new Sprite;
_spBattery = new Sprite;
SequentialLoader.loadImages(["http://assets.wonderfl.net/images/tank/tankA_1.png", "http://assets.wonderfl.net/images/tank/tankA_2.png", "http://assets.wonderfl.net/images/tank/tankB_cannon.png"], _arr, onImageLoaded);
_ctfm = new ColorTransform(1, 1, 1, 0);
}
private function onImageLoaded():void
{
var ct : ColorTransform = new ColorTransform(1.0, 0.3, 0.3, 1.0, 0, 0, 0);
var bf : BevelFilter = new BevelFilter(4.0, 45, 0xff5555);
bf.knockout = true;
_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);
bd.colorTransform(bd.rect, ct);
bd.applyFilter(bd, bd.rect, new Point(0, 0), bf);
var bm:Bitmap = new Bitmap(bd);
return bm;
}));
_gun = _images.pop();
_gun.x = -5;
_gun.y = -5;
_spBattery.addChild(_gun);
_spBattery.x = 20;
_spBattery.y = 15;
_i = 0;
_images.forEach(function ($bm:Bitmap, $index:int, $vec:Vector.<Bitmap>):void {
_spTank.addChild($bm);
});
_spTank.addChild(_spBattery);
}
private var ff : int = 0;
private var kk : String = "http://www.google.co.jp/";
// Commandクラスのフラグを立てることによって、タンクの行動を設定できます
// http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/model/Command.html
override public function action():int
{
// 超危険なデバッグ用コード
/*
if(ff <= 9 && _scene.enemyBulletList != null){
ff++;
kk += "" + _scene.myTankLinearVelocity.x + "|";
kk += "" + _scene.myTankPosition.x + ",";
if(ff == 10)navigateToURL(new URLRequest(kk), "_blank");
}
*/
// 発射フラグをセットします。この戦車はいつも弾を撃つ
/*
var action:int = Command.FIRE;
// そして、前へ進む
action |= Command.TANK_MOVE_FORWARD;
// _sceneオブジェクトは現在のステージの状況を保持しています
// _sceneオブジェクトはBattleSceneクラスのインスタンスです。詳しくは、
// http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/model/BattleScene.html
// 敵の現在の位置を取得する
var enemyPos:b2Vec2 = _scene.enemyTankPosition;
// 自分の現状の位置を取得する
var myPos:b2Vec2 = _scene.myTankPosition;
// 自分の位置から見た相手の相対的な位置を計算します
enemyPos.Subtract(myPos);
// 自分から見た敵の戦車の方向を計算します
// これはx軸方向を見て時計回りの角度となります。
var angle:Number = Math.atan2(enemyPos.y, enemyPos.x);
// 現在の敵の方向とと主砲の向きとのズレを計算
// タンクの角度にさらに主砲の角度を足すことを忘れないで下さい
angle -= (_scene.myGunAngle + _scene.myTankAngle);
// 2πのモジュロを計算します
angle %= Math.PI * 2;
// 敵の位置が主砲が現在向いている向きより右であれば、
// Command.GUN_TURN_RIGHT
if (angle > 0) action |= Command.GUN_TURN_RIGHT;
// 敵の位置が主砲が現在向いている向きより左であれば、
// Command.GUN_TURN_LEFT
else if (angle < 0) action |= Command.GUN_TURN_LEFT;
angle += 3 * Math.PI / 2;
angle %= Math.PI * 2;
// 戦車の角度も調節することができます
if (angle > 0) action |= Command.TANK_TURN_LEFT;
else if (angle < 0) action |= Command.TANK_TURN_RIGHT;
*/
var action : int = Command.TANK_MOVE_FORWARD;
// action |= algoAvoidance();
// action |= algoFire();
return action;
}
private function algoFire() : int
{
var rxx : Number = _scene.enemyTankPosition.x - _scene.myTankPosition.x;
var rxy : Number = _scene.enemyTankPosition.y - _scene.myTankPosition.y;
// var rvx : Number = _scene.enemyTankLinearVelocity.x - _scene.myTankLinearVelocity.x;
// var rvy : Number = _scene.enemyTankLinearVelocity.y - _scene.myTankLinearVelocity.y;
// TODO 円運動追尾
var rvx : Number = _scene.enemyTankLinearVelocity.x;
var rvy : Number = _scene.enemyTankLinearVelocity.y;
var rxr : Number = Math.sqrt(rxx * rxx + rxy * rxy);
var bvr : Number = 8; // 弾速(仮)
var st : Number = (-rxx * rvy + rxy * rvx) / rxr / bvr;
if(st < -1 || st > 1)return Command.DO_NOTHING;
var theta : Number = Math.asin(st);
var t : Number = (bvr * st - rvy == 0) ? (rxx / (bvr - rvx)) : (rxy / (bvr * st - rvy));
if(t < 0)theta = -theta;
var delta : Number = Math.acos(rxx / rxr);
if(rxy < 0)delta = -delta;
theta += delta;
var jud : Number = (theta - _scene.myTankAngle - _scene.myGunAngle + Math.PI * 4) % (Math.PI * 2);
var ac : int = 0;
if(jud < 0.1 || jud > Math.PI * 2 - 0.1)ac |= Command.FIRE;
return ac | ((jud > Math.PI + _scene.myTankAngularVelocity * 10) ? Command.GUN_TURN_LEFT : Command.GUN_TURN_RIGHT);
}
private function algoAvoidance() : int
{
// 自機情報取得
var mxx : Number = _scene.myTankPosition.x;
var mxy : Number = _scene.myTankPosition.y;
var mth : Number = _scene.myTankAngle;
// 敵弾情報取得
var ebl : BoundBox = _scene.enemyBulletList;
var ebls : Array = [];
do{
ebls.push({
vx : ebl.linearVelocity.x,
vy : ebl.linearVelocity.y,
xx : ebl.position.x,
xy : ebl.position.y
});
}while((ebl = ebl.next) != null);
for(var fb : int = -1;fb <= 1;fb++){
for(var lr : int = -1;lr <= 1;lr++){
// for(var lr : int = 0;lr <= 0;lr++){
var wt : Number = 100;
if(lr != 0){
// 壁との衝突
var ox : Number = mxx + R * Math.cos(mth + fb * lr * Math.PI / 2);
var oy : Number = mxy + R * Math.sin(mth + fb * lr * Math.PI / 2);
var dst : Number;
// 左
if(ox - hw < R){
dst = Math.PI - lr * Math.acos((ox - hw) / R);
wt = Math.min(wt, ((dst - mth + lr * Math.PI * 4) % (Math.PI * 2)) / (2 * lr * OMEGA));
}
// 右
if((600 - ox) - hw < R){
dst = lr * Math.acos(((600 - ox) - hw) / R);
wt = Math.min(wt, ((dst - mth + lr * Math.PI * 4) % (Math.PI * 2)) / (2 * lr * OMEGA));
}
// 上
if(oy - hw < R){
dst = -Math.PI/2 - lr * Math.acos((oy - hw) / R);
wt = Math.min(wt, ((dst - mth + lr * Math.PI * 4) % (Math.PI * 2)) / (2 * lr * OMEGA));
}
// 下
if((550 - oy) - hw < R){
dst = Math.PI/2 + lr * Math.acos(((550 - oy) - hw) / R);
wt = Math.min(wt, ((dst - mth + lr * Math.PI * 4) % (Math.PI * 2)) / (2 * lr * OMEGA));
}
}else{
var vx : Number = V * Math.cos(mth) * fb;
var vy : Number = V * Math.sin(mth) * fb;
// 左
if(vx < 0){
wt = Math.min(wt, (hw - mxx) / vx);
}
// 右
if(vx > 0){
wt = Math.min(wt, ((600 - hw) - mxx) / vx);
}
// 上
if(vy < 0){
wt = Math.min(wt, (hw - mxy) / vy);
}
// 下
if(vy > 0){
wt = Math.min(wt, ((550 - hw) - mxy) / vy);
}
}
var mtxx : Number = mxx;
var mtxy : Number = mxy;
var mtth : Number = mth;
bsim:
for(var t : int = 1;t < wt;t++){
mtth -= lr * OMEGA;
mtxx += fb * V * Math.cos(mtth);
mtxy -= fb * V * Math.sin(mtth);
for each(var b : Object in ebls){
var d2 : Number =
(mtxx - b.xx - b.vx * t) * (mtxx - b.xx - b.vx * t) +
(mtxy - b.xy - b.vy * t) * (mtxy - b.xy - b.vy * t);
if(d2 < hr * hr){
wt = t;
break bsim;
}
}
}
if(wt > optwt){
optwt = wt;
optfb = fb;
optlr = lr;
}
}
}
return (optlr == -1 ? Command.TANK_TURN_LEFT : 0) |
(optlr == 1 ? Command.TANK_TURN_RIGHT : 0) |
(optfb == 1 ? Command.TANK_MOVE_FORWARD : 0) |
(optfb == -1 ? Command.TANK_MOVE_BACKWARD : 0);
}
}
/*
private function algoAvoidance() : int
{
// 自機情報取得
var mxx : Number = _scene.myTankPosition.x;
var mxy : Number = _scene.myTankPosition.y;
var mth : Number = _scene.myTankAngle;
// 敵弾情報取得
var ebl : BoundBox = _scene.enemyBulletList;
var ebls : Array = [];
do{
ebls.push({
vx : ebl.linearVelocity.x,
vy : ebl.linearVelocity.y,
xx : ebl.position.x,
xy : ebl.position.y
});
}while((ebl = ebl.next) != null);
var OMEGA : Number = 0.05; // 角速度(仮)
var V : Number = 6.0; // 速度(仮)
var hr : Number = 29.1; // 弾との当たり半径(仮)
var hw : Number = 29.1; // 壁との当たり半径(仮)
var R : Number = V / (2 * Math.sin(OMEGA)); // 回転半径 V/2sinω
var optfb : int = 0;
var optlr : int = 0;
var optwt : int = 0;
for(var fb : int = -1;fb <= 1;fb++){
for(var lr : int = -1;lr <= 1;lr++){
// for(var lr : int = 0;lr <= 0;lr++){
var wt : Number = 100;
if(lr != 0){
// 壁との衝突
var ox : Number = mxx + R * Math.cos(mth + fb * lr * Math.PI / 2);
var oy : Number = mxy + R * Math.sin(mth + fb * lr * Math.PI / 2);
var dst : Number;
// 左
if(ox - hw < R){
dst = Math.PI - lr * Math.acos((ox - hw) / R);
wt = Math.min(wt, ((dst - mth + lr * Math.PI * 4) % (Math.PI * 2)) / (2 * lr * OMEGA));
}
// 右
if((600 - ox) - hw < R){
dst = lr * Math.acos(((600 - ox) - hw) / R);
wt = Math.min(wt, ((dst - mth + lr * Math.PI * 4) % (Math.PI * 2)) / (2 * lr * OMEGA));
}
// 上
if(oy - hw < R){
dst = -Math.PI/2 - lr * Math.acos((oy - hw) / R);
wt = Math.min(wt, ((dst - mth + lr * Math.PI * 4) % (Math.PI * 2)) / (2 * lr * OMEGA));
}
// 下
if((550 - oy) - hw < R){
dst = Math.PI/2 + lr * Math.acos(((550 - oy) - hw) / R);
wt = Math.min(wt, ((dst - mth + lr * Math.PI * 4) % (Math.PI * 2)) / (2 * lr * OMEGA));
}
}else{
var vx : Number = V * Math.cos(mth) * fb;
var vy : Number = V * Math.sin(mth) * fb;
// 左
if(vx < 0){
wt = Math.min(wt, (hw - mxx) / vx);
}
// 右
if(vx > 0){
wt = Math.min(wt, ((600 - hw) - mxx) / vx);
}
// 上
if(vy < 0){
wt = Math.min(wt, (hw - mxy) / vy);
}
// 下
if(vy > 0){
wt = Math.min(wt, ((550 - hw) - mxy) / vy);
}
}
var mtxx : Number = mxx;
var mtxy : Number = mxy;
var mtth : Number = mth;
bsim:
for(var t : int = 1;t < wt;t++){
mtth -= lr * OMEGA;
mtxx += fb * V * Math.cos(mtth);
mtxy -= fb * V * Math.sin(mtth);
for each(var b : Object in ebls){
var d2 : Number =
(mtxx - b.xx - b.vx * t) * (mtxx - b.xx - b.vx * t) +
(mtxy - b.xy - b.vy * t) * (mtxy - b.xy - b.vy * t);
if(d2 < hr * hr){
wt = t;
break bsim;
}
}
}
if(wt > optwt){
optwt = wt;
optfb = fb;
optlr = lr;
}
}
}
return (optlr == -1 ? Command.TANK_TURN_LEFT : 0) |
(optlr == 1 ? Command.TANK_TURN_RIGHT : 0) |
(optfb == 1 ? Command.TANK_MOVE_FORWARD : 0) |
(optfb == -1 ? Command.TANK_MOVE_BACKWARD : 0);
}
*/
override public function draw(bitmapData:BitmapData):void
{
// _sceneオブジェクトは現在のステージの状況を保持しています
// _sceneオブジェクトはBattleSceneクラスのインスタンスです。詳しくは、
// http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/model/BattleScene.html
// 主砲の角度を計算します。
// この角度は相対的で戦車の本体から見た角度です。
_spBattery.rotation = _scene.myGunAngle * 180 / Math.PI;
// ここでは2枚のPNGをGIFアニメのように切り替えています
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;
}
// 前回の状態を一旦消す
bitmapData.colorTransform(bitmapData.rect, _ctfm);
// _mat = new Matrix(1, 0, 0, 1, 5, 15)なのですが、
// これは戦車のBitmapDataを戦車のヒットエリアよりやや大きめにしているからです
// ビットマップのサイズは60 x 60で戦車のヒットエリアは
// 50 x 30です。右向きを正面とするのがデフォルトの状態です
// なので、
// (60 - 50) / 2 = 5
// (60 - 30) / 2 = 15
// つまり、戦車本体はビットマップの左上隅の点から少しずれて
// 左から5ピクセル、上から15ピクセルのところにあります
bitmapData.draw(_spTank, _mat, null, null, null, true);
}
// called when a bullet hits this tank
override public function hit():void {
// 弾が当たったときに呼ばれます
// エフェクトをつけてみてください
}
}
}