forked from: You have no business (撃ち漏らし低減バージョン)
弾と対象の対応マップを設けて、弾が消えるときまで管理することで、
弾が他の対象にあたることによる撃ち漏らしを防ぐよ!
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/joAR
*/
// forked from uwi's You have no business
// 弾と対象の対応マップを設けて、弾が消えるときまで管理することで、
// 弾が他の対象にあたることによる撃ち漏らしを防ぐよ!
package {
import flash.display.*;
import flash.text.*;
import flash.utils.*;
import flash.events.*;
import flash.geom.*;
import flash.ui.Keyboard;
// 弾を打って隕石を撃ち落とそう!
// 左右キーとスペースキーで真ん中の砲台を操作できるよ!
// 破壊すれば+100点、うちもらすと、弾ひとつにつき-50点だよ!
// 心強い味方がついてくれてるから地球も安心だね!
// 左側にいるのは最速破壊くんで、
// 右側にいるのは最速発射くんだよ!
[SWF(frameRate=60)]
public class Test extends Sprite {
// private var _tf : TextField;
private var _batteries : Array; // 砲台
private var _meteors : Array; // 隕石
private var _bullets : Array; // 弾
private var _explosions : Array; // 爆発
private var _bmdMeteors : Array;
private var _bmdBullets : Array;
private var _bmdExplosions : Array;
private var _canvas : BitmapData;
private var _locked : Dictionary; // ロック済み隕石(弱参照)
private var _targMap : Dictionary;
private var _self : Battery;
private var _tfScore : TextField;
private var _time : Number = 0;
private var _score : Number = 0;
private var _keyLeft : Boolean = false;
private var _keyRight : Boolean = false;
private var _keyShoot : Boolean = false;
public function Test() {
var i : uint;
graphics.beginFill(0x111111);
graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
graphics.endFill();
var s : Shape = new Shape();
var g : Graphics = s.graphics;
// meteor
_bmdMeteors = [];
var matOff : Matrix = new Matrix();
g.beginFill(0x993333);
g.drawCircle(0, 0, 10);
g.endFill();
var sup : uint = 50;
for(i = 0;i < sup;i++){
matOff = new Matrix();
matOff.rotate(2*Math.PI * i / sup);
matOff.translate(10, 10);
var bmdMeteor : BitmapData = new BitmapData(21, 21, true, 0x00000000);
bmdMeteor.draw(s, matOff);
_bmdMeteors.push(bmdMeteor);
}
// bullet
g.clear();
g.beginFill(0xcccccc);
g.drawRect(-5, -2, 10, 4);
g.endFill();
_bmdBullets = [];
sup = 32;
for(i = 0;i < sup;i++){
matOff = new Matrix();
matOff.rotate(2*Math.PI * i / sup);
matOff.translate(5, 5);
var bmdBullet : BitmapData = new BitmapData(11, 11, true, 0x00000000);
bmdBullet.draw(s, matOff);
_bmdBullets.push(bmdBullet);
}
// explosion
sup = 30;
_bmdExplosions = [];
for(i = 0;i < sup;i++){
g.clear();
g.beginFill(0xff0000);
g.drawCircle(0, 0, i+3);
g.endFill();
g.beginFill(0xffffff);
g.drawCircle(0, 0, i+1);
g.endFill();
matOff = new Matrix();
matOff.translate(i + 3, i + 3);
var bmdExplosion : BitmapData = new BitmapData((i + 3) * 2, (i + 3) * 2, true, 0x00000000);
bmdExplosion.draw(s, matOff);
_bmdExplosions.push(bmdExplosion);
}
_canvas = new BitmapData(465, 465, false, 0x111111);
addChild(new Bitmap(_canvas));
_batteries = [];
var bat : Battery;
bat = new Battery(15, 0.1, 1);
addChild(bat); bat.x = 100; bat.y = 400;
_batteries.push(bat);
bat = new Battery(15, 0.1, 2);
addChild(bat); bat.x = 350; bat.y = 400;
_batteries.push(bat);
bat = new Battery(15, 0.1, 0);
addChild(bat); bat.x = 230; bat.y = 400;
_batteries.push(bat);
_self = bat;
_meteors = [];
_bullets = [];
_explosions = [];
_locked = new Dictionary(true);
_targMap = new Dictionary(true);
/*
_tf = new TextField();
_tf.width = 465;
_tf.height = 465;
_tf.textColor = 0xffffff;
addChild(_tf);
*/
_tfScore = new TextField();
_tfScore.width = 150;
_tfScore.height = 60;
_tfScore.selectable = false;
_tfScore.textColor = 0xeeeeee;
_tfScore.x = 10;
_tfScore.y = 410;
_tfScore.defaultTextFormat = new TextFormat("Impact", 30);
addChild(_tfScore);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
private function onEnterFrame(e : Event) : void
{
makeMeteor();
algo();
move();
render();
_time++;
}
private function onKeyDown(e : KeyboardEvent) : void
{
if(e.keyCode == Keyboard.LEFT){
_keyLeft = true;
}
if(e.keyCode == Keyboard.RIGHT){
_keyRight = true;
}
if(e.keyCode == Keyboard.SPACE){
_keyShoot = true;
}
}
private function onKeyUp(e : KeyboardEvent) : void
{
if(e.keyCode == Keyboard.LEFT){
_keyLeft = false;
}
if(e.keyCode == Keyboard.RIGHT){
_keyRight = false;
}
if(e.keyCode == Keyboard.SPACE){
_keyShoot = false;
}
}
private function makeMeteor() : void
{
if(_time % 3 == 0){
_meteors.push(
new Meteor(Math.random() * 465, -10, (Math.random() - 0.5) * 3, (Math.random() -0.5) * 2, 10, Math.random() * 2 * Math.PI, (Math.random() - 0.5) * 0.2)
);
}
}
private function algo() : void
{
for each(var bat : Battery in _batteries){
if(bat.algoType == 1){
algoFastestDestruction(bat);
}else if(bat.algoType == 2){
algoFastestShoot(bat);
}
}
}
// 最速破壊アルゴリズム
private function algoFastestDestruction(bat : Battery) : void
{
var G : Number = 0.2;
var minu : int = 50;
var mint : uint = 999;
var minsg : int = 0;
var targ : Meteor = null;
for each(var m : Meteor in _meteors){
if(_locked[m])continue;
for(var sg : int = -1;sg <= 1;sg++){
var omega : Number = bat.omega * sg;
for(var t : int = 0;t <= minu;t++){
var c : Number = Math.cos(bat.theta + omega * t);
var s : Number = Math.sin(bat.theta + omega * t);
var Ax : Number = -(- bat.vBullet * c + m.vx);
var Ay : Number = -(G * t - bat.vBullet * s + m.vy);
var Bx : Number = - bat.vBullet * c * t + bat.x + 20 * c - m.xx;
var By : Number = G * t * t / 2 - bat.vBullet * s * t + bat.y + 20 * s - m.xy;
var ip : Number = Ax * Bx + Ay * By;
if(ip > 0)continue;
// var cr2 : Number = (5 + m.r) * (5 + m.r);
var cr2 : Number = m.r * m.r;
var D : Number = ip*ip - (Ax*Ax+Ay*Ay)*(Bx*Bx+By*By-cr2);
if(D < 0)continue;
var u : int = Math.ceil((-ip + Math.sqrt(D)) / (Ax*Ax+Ay*Ay));
// var u : int = Math.ceil(-ip / (Ax*Ax+Ay*Ay));
// _tf.appendText("" + t + "\t" + u + "\n");
if(t <= u && u < minu){
minu = u;
mint = t;
minsg = sg;
targ = m;
}
}
}
}
if(mint <= 0){
_locked[targ] = bat;
var bl : Bullet = bat.shoot();
_targMap[bl] = targ;
_bullets.push(bl);
}else{
bat.rotate(minsg);
}
}
// 最速発射アルゴリズム
private function algoFastestShoot(bat : Battery) : void
{
var G : Number = 0.2;
var mint : uint = 50;
var minsg : int = 0;
var targ : Meteor = null;
for each(var m : Meteor in _meteors){
if(_locked[m])continue;
for(var sg : int = -1;sg <= 1;sg++){
var omega : Number = bat.omega * sg;
for(var t : int = 0;t <= mint;t++){
var c : Number = Math.cos(bat.theta + omega * t);
var s : Number = Math.sin(bat.theta + omega * t);
var Ax : Number = -(- bat.vBullet * c + m.vx);
var Ay : Number = -(G * t - bat.vBullet * s + m.vy);
var Bx : Number = - bat.vBullet * c * t + bat.x + 20 * c - m.xx;
var By : Number = G * t * t / 2 - bat.vBullet * s * t + bat.y + 20 * s - m.xy;
var ip : Number = Ax * Bx + Ay * By;
if(ip > 0)continue;
// var cr2 : Number = (5 + m.r) * (5 + m.r);
var cr2 : Number = m.r * m.r;
var D : Number = ip*ip - (Ax*Ax+Ay*Ay)*(Bx*Bx+By*By-cr2);
if(D < 0)continue;
if(t < mint){
mint = t;
minsg = sg;
targ = m;
break;
}
}
}
}
if(mint <= 0){
_locked[targ] = bat;
var bl : Bullet = bat.shoot();
_targMap[bl] = targ;
_bullets.push(bl);
}else{
bat.rotate(minsg);
}
}
private static function removeElement(a : Array, ind : uint) : Array
{
if(ind == a.length - 1){
a.pop();
}else{
a[ind] = a.pop();
}
return a;
}
private function move() : void
{
var i : int;
// meteor
for(i = _meteors.length - 1;i >= 0;i--){
var m : Meteor = _meteors[i];
m.step();
if(m.xy > 465 + 10 || m.xx < -10 || m.xx > 465 + 10){
removeElement(_meteors, i);
}
}
// bullet
for(i = _bullets.length - 1;i >= 0;i--){
var b : Bullet = _bullets[i];
b.step();
if(b.xy > 465 + 10 || b.xy < -10 || b.xx < -10 || b.xx > 465 + 10){
_score -= 50;
removeElement(_bullets, i);
continue;
}
for(var j : int = _meteors.length - 1;j >= 0;j--){
m = _meteors[j];
if((m.xx - b.xx) * (m.xx - b.xx) + (m.xy - b.xy) * (m.xy - b.xy) <= (m.r + b.r) * (m.r + b.r)){
removeElement(_bullets, i);
removeElement(_meteors, j);
if(_targMap[b] != m){
_locked[_targMap[b]] = null;
}
_explosions.push(new Explosion(m.xx, m.xy));
_score += 100;
break;
}
}
}
// explosion
for(i = _explosions.length - 1;i >= 0;i--){
var e : Explosion = _explosions[i];
e.t++;
if(e.t == 30){
removeElement(_explosions, i);
}
}
// self
if(_keyLeft)_self.rotate(-1);
if(_keyRight)_self.rotate(1);
if(_keyShoot)_bullets.push(_self.shoot());
}
private function render() : void
{
var ind : uint;
_tfScore.text = "" + _score;
_canvas.lock();
_canvas.fillRect(_canvas.rect, 0x111111);
// meteor
for each(var m : Meteor in _meteors){
ind = ((uint(m.rot / (2 * Math.PI) * 50) % 50) + 50) % 50;
_canvas.copyPixels(
_bmdMeteors[ind],
_bmdMeteors[0].rect,
new Point(m.xx - _bmdMeteors[0].width/2, m.xy - _bmdMeteors[0].height / 2)
);
}
// bullet
var sup : uint = 32;
for each(var b : Bullet in _bullets){
var theta : Number = Math.atan2(b.vy, b.vx);
ind = ((uint(theta / (2 * Math.PI) * sup) % sup) + sup) % sup;
_canvas.copyPixels(
_bmdBullets[ind],
_bmdBullets[0].rect,
new Point(b.xx - _bmdBullets[0].width/2, b.xy - _bmdBullets[0].height / 2)
);
}
// explosion
for each(var e : Explosion in _explosions){
ind = e.t;
var be : BitmapData = _bmdExplosions[ind];
_canvas.copyPixels(be, be.rect, new Point(e.xx - be.width / 2, e.xy - be.height / 2));
}
_canvas.unlock();
}
/*
private function tr(...o : Array) : void
{
_tf.appendText(o + "\n");
}
*/
}
}
import flash.display.*;
class Bullet
{
public var xx : Number;
public var xy : Number;
public var vx : Number;
public var vy : Number;
public var r : Number;
public function Bullet(xx : Number, xy : Number, vx : Number, vy : Number, r : Number)
{
this.xx = xx; this.xy = xy;
this.vx = vx; this.vy = vy;
this.r = r;
}
public function step() : void
{
xx += vx; xy += vy;
vy += 0.2;
}
}
class Meteor extends Bullet
{
public var rot : Number;
public var omega : Number;
public function Meteor(xx : Number, xy : Number, vx : Number, vy : Number, r : Number, rot : Number, omega : Number)
{
super(xx, xy, vx, vy, r);
this.rot = rot;
this.omega = omega;
}
}
class Battery extends Sprite
{
public var theta : Number;
private var _head : Shape;
public var vBullet : Number;
public var omega : Number;
public var algoType : uint;
public function Battery(vBullet : Number, omega : Number, algoType : uint)
{
super();
this.vBullet = vBullet;
this.omega = omega;
this.algoType = algoType;
var g : Graphics = graphics;
g.beginFill(0x999999);
g.drawCircle(0, 0, 10);
g.endFill();
/*
g.beginFill(0x111111);
g.drawRect(-10, 0, 20, 10);
g.endFill();
*/
_head = new Shape();
_head.graphics.beginFill(0x999999);
_head.graphics.drawRect(5, -2, 15, 4);
_head.graphics.endFill();
addChild(_head);
Theta = -Math.PI / 2;
}
public function set Theta(val:Number) : void { theta = val; _head.rotation = theta * 180 / Math.PI; }
public function shoot() : Bullet
{
var c : Number = Math.cos(theta);
var s : Number = Math.sin(theta);
return new Bullet(
x + 20 * c, y + 20 * s,
vBullet * c, vBullet * s,
5);
}
public function rotate(sg : int) : void
{
Theta = theta + omega * sg;
}
}
class Explosion
{
public var xx : Number;
public var xy : Number;
public var t : uint;
public function Explosion(xx : Number, xy : Number) : void
{
this.xx = xx; this.xy = xy;
t = 0;
}
}