/**
* Copyright bradsedito ( http://wonderfl.net/user/bradsedito )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/atVW
*/
// forked from greentec's Ship Attack
// forked from greentec's Ship Placement
// forked from greentec's Circle Placement
package {
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import com.bit101.components.Label;
import com.bit101.components.Style;
// import flash.geom.Matrix;
public class CirclePlacement extends Sprite {
public var circle:Circle;
public var circs:Array=[];
public var num:uint=15;
public var H:Number=stage.stageHeight;
public var W:Number=stage.stageWidth;
public var _sumLabel:Label;
public var _infoLabel1:Label;
public var _infoLabel2:Label;
public var _infoLabel3:Label;
public var _infoLabel4:Label;
public var bg_Sp:Sprite;
public var bgData:BitmapData;
public var bg:Bitmap;
public var starNum:uint=300;
public var ships:Array=[];
public var time:uint=0;
public var laser_Sp:Sprite;
public var laser_R:int=30;
public function CirclePlacement() {
bg_Sp=new Sprite();
addChild(bg_Sp);
laser_Sp=new Sprite();
//addChild(laser_Sp);
Draw_Space();
addEventListener(Event.ENTER_FRAME, onAdd);
Style.LABEL_TEXT = 0xffffff;
_sumLabel = new Label(this, 0, 0, "Num : 0");
_sumLabel.filters=[new DropShadowFilter(2.0, 45,0x00ff00)];
_infoLabel1 = new Label(this, 0, 405, "Gene : ");
_infoLabel1.filters=[new DropShadowFilter(2.0, 45,0x0000ff)];
_infoLabel2 = new Label(this, 0, 420, "HP : ");
_infoLabel2.filters=[new DropShadowFilter(2.0, 45,0x6666ff)];
_infoLabel3 = new Label(this, 0, 435, "Speed : ");
_infoLabel3.filters=[new DropShadowFilter(2.0, 45,0xaaaaff)];
_infoLabel4 = new Label(this, 0, 450, "Attack: ");
_infoLabel4.filters=[new DropShadowFilter(2.0, 45,0xddddff)];
}
public function Draw_Space():void
{
bgData=new BitmapData(465,465,false,0);
for(var i:uint=0;i<starNum;i++)
{
var r:uint=Math.random()*100+155;
var g:uint=Math.random()*100+155;
var b:uint=Math.random()*100+155;
var cl:uint=(r<<16)|(g<<8)|b;
bgData.setPixel(Math.random()*465,Math.random()*465,cl);
}
bg=new Bitmap(bgData);
bg_Sp.addChild(bg);
}
public function onAdd(e:Event):void
{
var sw:Boolean=false;
circle=new Circle();
circle.x=Math.random()*W;
circle.y=Math.random()*H;
var circ2:Circle;
var i:int;
if(circs.length==0)
{
addChild(circle);
circs.push(circle);
}
else
{
for(i=circs.length-1;i>-1;i--)
{
circ2=circs[i];
if(circ2.hitTestObject(circle)==true)
{
sw=true;
}
}
if(sw==false)
{
addChild(circle);
circs.push(circle);
_sumLabel.text="Num : "+circs.length;
}
}
if(circs.length==num)
{
removeEventListener(Event.ENTER_FRAME, onAdd);
Ship_Placement();
addEventListener(Event.ENTER_FRAME, wipeCircleOut);
}
}
public function wipeCircleOut(e:Event):void
{
for(var i:int=0;i<circs.length;i++)
{
circs[i].alpha-=0.02;
if(circs[i].alpha<0)
{
removeEventListener(Event.ENTER_FRAME, wipeCircleOut);
}
}
}
public function Ship_Placement():void
{
var ship:Ship;
for(var i:int=0;i<circs.length;i++)
{
var r1:Number=Math.random();
var r2:Number=Math.random();
var r3:Number=Math.random();
var total:Number=r1+r2+r3;
var totalpoint:int=15;
var dp:int=1+r1/total*totalpoint;
var ap:int=1+r2/total*totalpoint;
var ep:int=1+r3/total*totalpoint;
ship=new Ship(dp,ap,ep);
ship.x=circs[i].x;
ship.y=circs[i].y;
ship.rotation=Math.random()*360;
ship.addEventListener(MouseEvent.CLICK, ship_click);
addChild(ship);
ships.push(ship);
}
addChild(laser_Sp);
Ship_targeting();
addEventListener(Event.ENTER_FRAME, Ship_Move);
}
public function Ship_targeting():void
{
var ship:Ship, enemy:Ship;
var mindist:Number;
var target:int;
var dx:Number, dy:Number, dist:Number;
var err1:Number, err2:Number, err3:Number, err4:Number;
var dx1:Number, dy1:Number;
for(var i:int=0;i<ships.length;i++)
{
ship=ships[i];
if(ship.unpowered==false)
{
mindist=999999;
for(var j:int=ships.length-1;j>-1;j--)
{
if(i!=j)
{
enemy=ships[j];
dx=ship.x-enemy.x;
dy=ship.y-enemy.y;
dist=Math.abs(dx*dx+dy*dy);
if(dist<mindist && enemy.unpowered==false)
{
mindist=dist;
target=j;
}
}
}
ship.target=target;
enemy=ships[target];
if(ship.inSight(enemy)==true && enemy.unpowered==false)
{
with(laser_Sp)
{
if(Math.random()<0.5)
{
graphics.lineStyle(0.5,0x00ff00);
}
else
{
graphics.lineStyle(0.5,0xff0000);
}
err1=Math.random()*5-2.5;
err2=Math.random()*5-2.5;
err3=Math.random()*5-2.5;
err4=Math.random()*5-2.5;
dx1=Math.cos(ship.rotation*Math.PI/180)*8;
dy1=Math.sin(ship.rotation*Math.PI/180)*8;
graphics.moveTo(ship.x+err1+dx1,ship.y+err2+dy1);
graphics.lineTo(enemy.x+err3,enemy.y+err4);
}
enemy.hp-=ship.atk;
if(enemy.hp<=0)
{
enemy.hp=0;
enemy.unpowered=true;
enemy.alpha=0.4;
}
}
}
}
}
public function Ship_Move(e:Event):void
{
var ship:Ship;
for(var i:int=0;i<ships.length;i++)
{
ship=ships[i];
if(ship.unpowered==false)
{
//ship.seek(ships[ship.target].position);
ship.pursue(ships[ship.target]);
ship.update();
}
}
time++;
if(time%10==0)
{
laser_Sp.graphics.clear();
Ship_targeting();
}
}
public function ship_click(e:MouseEvent):void
{
var clicked:Ship=Ship(e.target);
_infoLabel1.text="Gene : [ "+clicked.dp+" "+clicked.ap+" "+clicked.ep+" ]";
_infoLabel2.text="HP : "+int(clicked.hp*10)/10+" / "+int(clicked.fullhp*10)/10;
_infoLabel3.text="Speed : "+int(clicked.vel*10)/10;
_infoLabel4.text="Attack: "+int(clicked.atk*10)/10;
}
}
}
import flash.display.Sprite;
import flash.geom.Matrix;
class Circle extends Sprite
{
public var r:Number, color:Number;
public function Circle(r:Number=0, color:uint=0x333333)
{
var m:Matrix;
r=Math.random()*10+35;
this.graphics.lineStyle(0,0xffffff);
this.graphics.beginGradientFill("radial",[0xffffff,0x0000ff],[0.7,0],[0,100],m=new Matrix(400,400,Math.PI/2,0,0));
this.graphics.drawCircle(0,0,r);
this.graphics.endFill();
//this.blendMode="screen";
}
}
class Vector2D
{
import flash.display.Graphics;
/**
* A basic 2-dimensional vector class.
*/
private var _x:Number;
private var _y:Number;
/**
* Constructor.
*/
public function Vector2D(x:Number = 0, y:Number = 0)
{
_x = x;
_y = y;
}
/**
* Can be used to visualize the vector. Generally used for debug purposes only.
* @param graphics The Graphics instance to draw the vector on.
* @param color The color of the line used to represent the vector.
*/
public function draw(graphics:Graphics, color:uint = 0):void
{
graphics.lineStyle(0, color);
graphics.moveTo(0, 0);
graphics.lineTo(_x, _y);
}
/**
* Generates a copy of this vector.
* @return Vector2D A copy of this vector.
*/
public function clone():Vector2D
{
return new Vector2D(x, y);
}
/**
* Sets this vector's x and y values, and thus length, to zero.
* @return Vector2D A reference to this vector.
*/
public function zero():Vector2D
{
_x = 0;
_y = 0;
return this;
}
/**
* Whether or not this vector is equal to zero, i.e. its x, y, and length are zero.
* @return Boolean True if vector is zero, otherwise false.
*/
public function isZero():Boolean
{
return _x == 0 && _y == 0;
}
/**
* Sets / gets the length or magnitude of this vector. Changing the length will change the x and y but not the angle of this vector.
*/
public function set length(value:Number):void
{
var a:Number = angle;
_x = Math.cos(a) * value;
_y = Math.sin(a) * value;
}
public function get length():Number
{
return Math.sqrt(lengthSQ);
}
/**
* Gets the length of this vector, squared.
*/
public function get lengthSQ():Number
{
return _x * _x + _y * _y;
}
/**
* Gets / sets the angle of this vector. Changing the angle changes the x and y but retains the same length.
*/
public function set angle(value:Number):void
{
var len:Number = length;
_x = Math.cos(value) * len;
_y = Math.sin(value) * len;
}
public function get angle():Number
{
return Math.atan2(_y, _x);
}
/**
* Normalizes this vector. Equivalent to setting the length to one, but more efficient.
* @return Vector2D A reference to this vector.
*/
public function normalize():Vector2D
{
if(length == 0)
{
_x = 1;
return this;
}
var len:Number = length;
_x /= len;
_y /= len;
return this;
}
/**
* Ensures the length of the vector is no longer than the given value.
* @param max The maximum value this vector should be. If length is larger than max, it will be truncated to this value.
* @return Vector2D A reference to this vector.
*/
public function truncate(max:Number):Vector2D
{
length = Math.min(max, length);
return this;
}
/**
* Reverses the direction of this vector.
* @return Vector2D A reference to this vector.
*/
public function reverse():Vector2D
{
_x = -_x;
_y = -_y;
return this;
}
/**
* Whether or not this vector is normalized, i.e. its length is equal to one.
* @return Boolean True if length is one, otherwise false.
*/
public function isNormalized():Boolean
{
return length == 1.0;
}
/**
* Calculates the dot product of this vector and another given vector.
* @param v2 Another Vector2D instance.
* @return Number The dot product of this vector and the one passed in as a parameter.
*/
public function dotProd(v2:Vector2D):Number
{
return _x * v2.x + _y * v2.y;
}
/**
* Calculates the cross product of this vector and another given vector.
* @param v2 Another Vector2D instance.
* @return Number The cross product of this vector and the one passed in as a parameter.
*/
public function crossProd(v2:Vector2D):Number
{
return _x * v2.y - _y * v2.x;
}
/**
* Calculates the angle between two vectors.
* @param v1 The first Vector2D instance.
* @param v2 The second Vector2D instance.
* @return Number the angle between the two given vectors.
*/
public static function angleBetween(v1:Vector2D, v2:Vector2D):Number
{
if(!v1.isNormalized()) v1 = v1.clone().normalize();
if(!v2.isNormalized()) v2 = v2.clone().normalize();
return Math.acos(v1.dotProd(v2));
}
/**
* Determines if a given vector is to the right or left of this vector.
* @return int If to the left, returns -1. If to the right, +1.
*/
public function sign(v2:Vector2D):int
{
return perp.dotProd(v2) < 0 ? -1 : 1;
}
/**
* Finds a vector that is perpendicular to this vector.
* @return Vector2D A vector that is perpendicular to this vector.
*/
public function get perp():Vector2D
{
return new Vector2D(-y, x);
}
/**
* Calculates the distance from this vector to another given vector.
* @param v2 A Vector2D instance.
* @return Number The distance from this vector to the vector passed as a parameter.
*/
public function dist(v2:Vector2D):Number
{
return Math.sqrt(distSQ(v2));
}
/**
* Calculates the distance squared from this vector to another given vector.
* @param v2 A Vector2D instance.
* @return Number The distance squared from this vector to the vector passed as a parameter.
*/
public function distSQ(v2:Vector2D):Number
{
var dx:Number = v2.x - x;
var dy:Number = v2.y - y;
return dx * dx + dy * dy;
}
/**
* Adds a vector to this vector, creating a new Vector2D instance to hold the result.
* @param v2 A Vector2D instance.
* @return Vector2D A new vector containing the results of the addition.
*/
public function add(v2:Vector2D):Vector2D
{
return new Vector2D(_x + v2.x, _y + v2.y);
}
/**
* Subtacts a vector to this vector, creating a new Vector2D instance to hold the result.
* @param v2 A Vector2D instance.
* @return Vector2D A new vector containing the results of the subtraction.
*/
public function subtract(v2:Vector2D):Vector2D
{
return new Vector2D(_x - v2.x, _y - v2.y);
}
/**
* Multiplies this vector by a value, creating a new Vector2D instance to hold the result.
* @param v2 A Vector2D instance.
* @return Vector2D A new vector containing the results of the multiplication.
*/
public function multiply(value:Number):Vector2D
{
return new Vector2D(_x * value, _y * value);
}
/**
* Divides this vector by a value, creating a new Vector2D instance to hold the result.
* @param v2 A Vector2D instance.
* @return Vector2D A new vector containing the results of the division.
*/
public function divide(value:Number):Vector2D
{
return new Vector2D(_x / value, _y / value);
}
/**
* Indicates whether this vector and another Vector2D instance are equal in value.
* @param v2 A Vector2D instance.
* @return Boolean True if the other vector is equal to this one, false if not.
*/
public function equals(v2:Vector2D):Boolean
{
return _x == v2.x && _y == v2.y;
}
/**
* Sets / gets the x value of this vector.
*/
public function set x(value:Number):void
{
_x = value;
}
public function get x():Number
{
return _x;
}
/**
* Sets / gets the y value of this vector.
*/
public function set y(value:Number):void
{
_y = value;
}
public function get y():Number
{
return _y;
}
/**
* Generates a string representation of this vector.
* @return String A description of this vector.
*/
public function toString():String
{
return "[Vector2D (x:" + _x + ", y:" + _y + ")]";
}
}
class Vehicle extends Sprite
{
protected var _edgeBehavior:String = BOUNCE;
protected var _mass:Number = 50.0;
protected var _maxSpeed:Number = 10;
protected var _position:Vector2D;
protected var _velocity:Vector2D;
// potential edge behaviors
public static const WRAP:String = "wrap";
public static const BOUNCE:String = "bounce";
/**
* Constructor.
*/
public function Vehicle()
{
_position = new Vector2D();
_velocity = new Vector2D();
draw();
}
/**
* Default graphics for vehicle. Can be overridden in subclasses.
*/
protected function draw():void
{
/*graphics.clear();
graphics.lineStyle(0);
graphics.moveTo(10, 0);
graphics.lineTo(-10, 5);
graphics.lineTo(-10, -5);
graphics.lineTo(10, 0);*/
}
/**
* Handles all basic motion. Should be called on each frame / timer interval.
*/
public function update():void
{
// make sure velocity stays within max speed.
_velocity.truncate(_maxSpeed);
// add velocity to position
_position = _position.add(_velocity);
// handle any edge behavior
if(_edgeBehavior == WRAP)
{
wrap();
}
else if(_edgeBehavior == BOUNCE)
{
bounce();
}
// update position of sprite
x = position.x;
y = position.y;
// rotate heading to match velocity
rotation = _velocity.angle * 180 / Math.PI;
}
/**
* Causes character to bounce off edge if edge is hit.
*/
private function bounce():void
{
if(stage != null)
{
if(position.x > stage.stageWidth)
{
position.x = stage.stageWidth;
velocity.x *= -0.7;
}
else if(position.x < 0)
{
position.x = 0;
velocity.x *= -0.7;
}
if(position.y > stage.stageHeight)
{
position.y = stage.stageHeight;
velocity.y *= -0.7;
}
else if(position.y < 0)
{
position.y = 0;
velocity.y *= -0.7;
}
}
}
/**
* Causes character to wrap around to opposite edge if edge is hit.
*/
private function wrap():void
{
if(stage != null)
{
if(position.x > stage.stageWidth) position.x = 0;
if(position.x < 0) position.x = stage.stageWidth;
if(position.y > stage.stageHeight) position.y = 0;
if(position.y < 0) position.y = stage.stageHeight;
}
}
/**
* Sets / gets what will happen if character hits edge.
*/
public function set edgeBehavior(value:String):void
{
_edgeBehavior = value;
}
public function get edgeBehavior():String
{
return _edgeBehavior;
}
/**
* Sets / gets mass of character.
*/
public function set mass(value:Number):void
{
_mass = value;
}
public function get mass():Number
{
return _mass;
}
/**
* Sets / gets maximum speed of character.
*/
public function set maxSpeed(value:Number):void
{
_maxSpeed = value;
}
public function get maxSpeed():Number
{
return _maxSpeed;
}
/**
* Sets / gets position of character as a Vector2D.
*/
public function set position(value:Vector2D):void
{
_position = value;
x = _position.x;
y = _position.y;
}
public function get position():Vector2D
{
return _position;
}
/**
* Sets / gets velocity of character as a Vector2D.
*/
public function set velocity(value:Vector2D):void
{
_velocity = value;
}
public function get velocity():Vector2D
{
return _velocity;
}
/**
* Sets x position of character. Overrides Sprite.x to set internal Vector2D position as well.
*/
override public function set x(value:Number):void
{
super.x = value;
_position.x = x;
}
/**
* Sets y position of character. Overrides Sprite.y to set internal Vector2D position as well.
*/
override public function set y(value:Number):void
{
super.y = value;
_position.y = y;
}
}
class Ship extends Vehicle
{
public var color:Number;
public var dp:int;//durability - increases HP, decreases velocity
public var ap:int;//armed - increases attack, decreases velocity
public var ep:int;//engine - increases velocity, decreases HP
public var hp:Number;
public var fullhp:Number;
public var vel:Number;
public var Min_vel:int=1;
public var atk:Number;
public var unpowered:Boolean=false;
public var target:uint;
private var _steeringForce:Vector2D;
private var _maxForce:Number = 1;
private var _inSightDist:int=30;//laser_Range
public function Ship(dp:int, ap:int, ep:int, color:uint=0xffffff)
{
var col:uint=(((ap/18)*0xff) << 16) | ((dp/18)*0xff << 8) | ((ep/18)*0xff);
//ap - red color, dp - green color, ep - blue color
graphics.beginFill(col,0.8);
graphics.lineStyle(0,color);
graphics.moveTo(8,0);
graphics.lineTo(-8,4);
graphics.lineTo(-8,-4);
graphics.lineTo(8,0);
graphics.endFill();
this.unpowered=false;
this.dp=dp;
this.ap=ap;
this.ep=ep;
this.hp=(dp+10)*5-ep*2;
this.fullhp=this.hp;
this.vel=ep*2-(dp*0.1+ap*0.3);
if(this.vel<=Min_vel)
this.vel=Min_vel;
this.atk=ap;
this._mass=100-this.vel*2;
if(this.vel<10)
{
this._maxSpeed=this.vel/2;
}
else
{
this._maxSpeed=5;
}
_steeringForce = new Vector2D();
super();
}
override public function update():void
{
_steeringForce.truncate(_maxForce);
_steeringForce = _steeringForce.divide(_mass);
_velocity = _velocity.add(_steeringForce);
_steeringForce = new Vector2D();
super.update();
}
public function seek(target:Vector2D):void
{
var desiredVelocity:Vector2D = target.subtract(_position);
desiredVelocity.normalize();
desiredVelocity = desiredVelocity.multiply(_maxSpeed);
var force:Vector2D = desiredVelocity.subtract(_velocity);
_steeringForce = _steeringForce.add(force);
}
public function pursue(target:Vehicle):void
{
var lookAheadTime:Number = position.dist(target.position) / _maxSpeed;
var predictedTarget:Vector2D = target.position.add(target.velocity.multiply(lookAheadTime));
seek(predictedTarget);
}
public function inSight(vehicle:Vehicle):Boolean
{
if(_position.dist(vehicle.position) > _inSightDist) return false;
var heading:Vector2D = _velocity.clone().normalize();
var difference:Vector2D = vehicle.position.subtract(_position);
var dotProd:Number = difference.dotProd(heading);
if(dotProd < 0.5) return false;//120 degree
return true;
}
}