forked from: Open colony
/**
* Copyright mapache ( http://wonderfl.net/user/mapache )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/8Uv4
*/
// forked from andyshang's Open colony
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.filters.BlurFilter;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.ui.Keyboard;
import idv.cjcat.stardust.common.clocks.Clock;
import idv.cjcat.stardust.common.clocks.SteadyClock;
import idv.cjcat.stardust.common.emitters.Emitter;
import idv.cjcat.stardust.twoD.renderers.PixelRenderer;
[SWF(width=640, height=480, backgroundColor=0, fps=30)]
public class OpenColony extends Sprite
{
public static const ZERO_POINT:Point = new Point();
private const BLUR:BlurFilter = new BlurFilter(1.2,1.2,3);
private var emitters:Array = [];
private var deadEmitters:Array = [];
private var W:int = 480;
private var H:int = 360;
private var MARGIN:int = 10;
private var clock:Clock = new SteadyClock(1);
private var afterSteps:int = 24;
private var _matrix:Matrix = new Matrix(0.25, 0, 0, 0.25);
private var _canvas:BitmapData = new BitmapData(W, H, true, 0x00000000);
private var _blurEffect:BitmapData = new BitmapData(W, H, true, 0x00000000);
private var _kirakira:BitmapData = new BitmapData(W / 4, H / 4, true, 0x000000);
private var renderer:PixelRenderer = new PixelRenderer(_canvas);
public var stars:Array = [];
private var YOU:Player;
private var COM:Player;
private var container:Sprite;
private var selection:Star;
private var command:int = 0;
public function OpenColony()
{
addEventListener(Event.ADDED_TO_STAGE, function(event:Event):void
{
removeEventListener(event.type, arguments.callee);
stage.scaleMode = "noScale";
stage.align = StageAlign.TOP_LEFT;
container = new Sprite();
addChild(container)
container.x = (640 - W) / 2
container.y = (480 - H) / 2
container.addChild(new Bitmap(_blurEffect));
container.addChild(new Bitmap(_canvas));
startGame();
});
stage.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void
{
if(selection)
{
selection.filters = [];
selection = null;
}
});
}
private function createEffect():void
{
var bmp:Bitmap = new Bitmap(_kirakira, "never", true);
bmp.scaleX = bmp.scaleY = 4;
bmp.smoothing = true;
bmp.blendMode = BlendMode.ADD;
container.addChild(bmp);
}
private function updateEffect():void
{
//add the kirakira effect, err... you know kirakira is a Japanese word
//means shining :P
_kirakira.fillRect(_kirakira.rect, 0x00000000);
_kirakira.draw(_canvas, _matrix);
_blurEffect.draw(_canvas);
_blurEffect.applyFilter(_blurEffect, _canvas.rect, ZERO_POINT, BLUR);
_canvas.fillRect(_canvas.rect, 0x00000000);
}
private function startGame():void
{
YOU = new Player("Jiong", 0x1220FB);
COM = new AI(this, YOU, 0xFF0000);
COM.reset();
YOU.reset();
stars.forEach(function(star:Star, ...args):void
{
container.removeChild(star);
});
stars = [];
createStars();
placeStarts();
addEventListener(Event.ENTER_FRAME, loop);
}
private function end(w:Boolean):void
{
removeEventListener(Event.ENTER_FRAME, loop);
stage.addEventListener(KeyboardEvent.KEY_DOWN, function(event:KeyboardEvent):void
{
if(event.keyCode == Keyboard.SPACE)
{
stage.removeEventListener(event.type, arguments.callee);
startGame();
}
});
}
private function loop(event:Event):void
{
//check if the game was ended
if(YOU.colonies.length < 1)
{
end(false)
}
else if(COM.colonies.length < 1)
{
end(true)
}
//clear the graphics of dead emitters
if(command -- < 0)
{
container.graphics.clear();
}
//update ai
if(COM is AI)
{
AI(COM).update();
}
//update stars
stars.forEach(function(star:Star, ...args):void
{
star.grow();
});
//clear the dead emitter
deadEmitters.forEach(function(emitter:ShipEmitter, ...args):void
{
emitter.clearActions();
emitter.clearInitializers();
emitter.clearParticles();
emitters.splice(emitters.indexOf(emitter),1);
});
deadEmitters.splice(0,deadEmitters.length);
//check if the emitter has been dead, this is a double check
emitters.forEach(function(emitter:ShipEmitter, ...args):void
{
afterSteps = 16;
emitter.step();
if(!emitter.active && emitter.numParticles == 0)
{
deadEmitters.push(emitter);
}
});
if(emitters.length == 0)
{
if(afterSteps < 0)
{
return;
}
afterSteps --;
}
updateEffect();
}
/**
* send ships from one star to target
*/
public function send(from:Star, target:Star):Boolean
{
if(from == target)
{
return false;
}
var _emitter:Emitter = new ShipEmitter(clock,from,target);
emitters.push(_emitter);
renderer.addEmitter(_emitter);
return true;
}
private function createStars():void
{
for(var i:int = 0;i<12;i++)
{
var star:Star
if(i==2)
{
star = new Star(100, 0.05);
COM.occupy(star);
}
else if(i==9)
{
star = new Star(100, 0.05);
YOU.occupy(star);
}
else
{
star = new Star(35 * Math.random(), 0.05 * Math.random());
}
container.addChild(star);
stars.push(star);
addListener(star);
}
}
/**
* listen the click event of star
* @param star
*/
private function addListener(star:Star):void
{
star.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void
{
event.stopPropagation();
if(selection == null)
{
if(event.currentTarget.owner != YOU)
{
return;
}
selection = event.currentTarget as Star;
selection.filters = [new GlowFilter()];
}
else
{
if(selection == event.currentTarget)
{
selection.filters = [];
selection = null;
return;
}
if(selection.owner != YOU)
{
selection.filters = [];
selection = null;
return;
}
send(selection, event.currentTarget as Star);
container.graphics.clear();
container.graphics.lineStyle(3,YOU.color, 0.8);
container.graphics.moveTo(selection.x, selection.y)
container.graphics.lineTo(event.currentTarget.x, event.currentTarget.y)
if(!event.shiftKey)
{
selection.filters = [];
selection = null;
}
command = 8;
}
});
}
private function placeStarts():void
{
var c:int = 0;
for(var i:int=0;i<stars.length;i++)
{
var star:Star = stars[c++];
star.x = 85 * Math.random() + (i % 4) * 125
star.y = 85 * Math.random() + int(i/4) * 125;
if(star.x < 0)
{
star.x = 0;
}
if(star.y < 0)
{
star.y = 0;
}
}
}
}
}
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.filters.GlowFilter;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.Dictionary;
import idv.cjcat.stardust.common.actions.Die;
import idv.cjcat.stardust.common.clocks.Clock;
import idv.cjcat.stardust.common.emitters.Emitter;
import idv.cjcat.stardust.common.initializers.Color;
import idv.cjcat.stardust.common.particles.Particle;
import idv.cjcat.stardust.twoD.actions.DeathZone;
import idv.cjcat.stardust.twoD.actions.FollowWaypoints;
import idv.cjcat.stardust.twoD.actions.Move;
import idv.cjcat.stardust.twoD.actions.SpeedLimit;
import idv.cjcat.stardust.twoD.actions.waypoints.Waypoint;
import idv.cjcat.stardust.twoD.emitters.Emitter2D;
import idv.cjcat.stardust.twoD.initializers.Position;
import idv.cjcat.stardust.twoD.zones.CircleZone;
class Player
{
public var color:uint;
public var name:String;
public var numColonies:int;
public var growth:Number = 0;
public var colonies:Array = [];
public function Player(name:String, color:uint)
{
this.name = name;
this.color = color;
}
public function reset():void
{
colonies = [];
}
public function occupy(star:Star):void
{
if(star.owner != this)
{
star.owner.colonies.splice(star.owner.colonies.indexOf(star),1);
star.owner = this;
colonies.push(star);
}
}
}
class ShipEmitter extends Emitter2D
{
private static var wayPoints:Dictionary = new Dictionary();
private static var positions:Dictionary = new Dictionary();
private var _numShip:int;
public var owner:Player;
public function get numShip():int
{
return _numShip;
}
public function ShipEmitter(clock:Clock, start:Star, end:Star)
{
super(clock);
var waypoints:Array = [
getWayPoint(start),
getWayPoint(end)
];
owner = start.owner;
_numShip = start.checkout();
if(_numShip == 0)
{
active = false;
return;
}
addInitializer(new Color(owner.color));
addInitializer(getPosition(start));
addAction(new Target(end));
addAction(new FollowWaypoints(waypoints, false, false));
addAction(new Move());
addAction(new SpeedLimit(1));
end.notice(this);
}
private function getWayPoint(star:Star):Waypoint
{
if(wayPoints[star] == null)
{
wayPoints[star] = new Waypoint(star.x, star.y,star.width/2);
}
return wayPoints[star];
}
private function getPosition(star:Star):Position
{
if(positions[star] == null)
{
positions[star] = new Position(new CircleZone(star.x, star.y, star.width/2));
}
return positions[star];
}
}
/**
* star
*/
class Star extends Sprite
{
public static const MID:Player = new Player("mid", 0x666666);
private static var tf:TextFormat = new TextFormat(null, 15, 0xFFFFFF, true);
private var _owner:Player;
public var userData:*;
private var t:TextField = new TextField();
public var visitors:Array = [];
public var ships:Number = 100;
public var growth:Number = 0.01;
private var r:Number;
public function Star(ships:Number, growth:Number):void
{
this.growth = growth;
this.ships = ships;
r = getR(growth);
addChild(t);
t.autoSize = "center"
t.x = -t.width / 2;
t.y = -12;
t.selectable = false;
t.setTextFormat(tf);
t.defaultTextFormat = tf;
owner = MID;
draw();
}
public function get owner():Player
{
return _owner;
}
public function set owner(p:Player):void
{
if(_owner != null)
{
_owner.growth -= growth;
}
_owner = p;
p.growth += growth;
filters = [new GlowFilter(owner.color,0.5, 50,50,getR(growth)*4,1,true)]
draw();
graphics.beginFill(owner.color);
graphics.drawCircle(0,0,r);
t.visible = !(p is AI)
}
public function draw():void
{
t.text = int(ships).toString();
}
private function getR(growth:Number):int
{
return 16 + growth*300;
}
public function checkout():int
{
var res:int = ships/2
ships -= res;
if(ships < 0)
{
ships = 0;
}
draw()
return res;
}
public function checkin(player:Player):void
{
if(player == owner)
{
ships ++;
}
else
{
ships --;
if(int(ships) <= 0)
{
ships = 0;
player.occupy(this);
}
}
draw()
}
public function grow():void
{
if(owner == MID)
{
return;
}
ships += growth;
draw();
}
public function notice(emitter:ShipEmitter, clear:Boolean=false):void
{
clear?visitors.splice(visitors.indexOf(emitter),1)
:visitors.push(emitter);
}
public function clone():Star
{
var res:Star = new Star(ships, growth);
res.owner = owner;
res.x = x;
res.y = y;
return res;
}
}
/**
* target
*/
class Target extends DeathZone
{
private var star:Star;
private var numArrive:int = 0;
private static var die:Die = new Die()
public function Target(star:Star)
{
super(new CircleZone(star.x, star.y, star.width/2.5));
this.star = star;
}
override public function update(e:Emitter, p:Particle, t:Number):void
{
super.update(e,p,t);
if(e.numParticles >= ShipEmitter(e).numShip)
{
e.active = false;
}
if(p.isDead)
{
if(ShipEmitter(e).numShip <= numArrive++)
{
e.active = false;
e.addAction(die);
star.notice(ShipEmitter(e), true);
return;
}
star.checkin(ShipEmitter(e).owner);
}
}
}
/**
* AI
*/
class AI extends Player
{
private var game:OpenColony;
private var op:Player;
private var _ships:Number;
private var _opships:Number;
private var cooldown:int = 0;
public function AI(game:OpenColony, op:Player, color:uint)
{
super("computer", color);
this.game = game;
this.op = op;
}
override public function reset():void
{
super.reset();
_ships = 0;
_opships = 0;
cooldown = 0;
}
public function update():void
{
_ships = 0;
_opships = 0;
var i:int
for(i=0;i<colonies.length;i++)
{
_ships += colonies[i].ships;
}
for(i=0;i<op.colonies.length;i++)
{
_opships += op.colonies[i].ships;
}
sort();
if(-- cooldown <= 0)
{
var target:Star = game.stars[0];
for(i=0;i<colonies.length;i++)
{
var c:Star = colonies[i];
var shipped:int = 0;
var step:int = ships;
if(target.userData < 40)
{
cooldown = 20;
return;
}
if(shipped < ships / 10 && (ships > 30 || ships > _opships))
{
if(game.send(c, target))
{
step /= 2
shipped += step;
cooldown += shipped > 60?60:shipped;
}
}
};
}
}
private function sort():void
{
for(var i:int=0;i<game.stars.length;i++)
{
weight(game.stars[i]);
}
game.stars.sortOn("userData", Array.DESCENDING | Array.NUMERIC);
}
private function weight(s:Star):void
{
if(isColonized(s))
{
if(_ships < _opships * 1.3 && enemyApproaching(s))
{
s.userData = 9999;
}
else
{
s.userData = 0;
}
}
else if(s.owner == Star.MID)
{
s.userData = s.growth * 5000 - s.ships*3 - ships/2;
}
else
{
if(_ships > _opships * 1.3)
{
s.userData = 9999;
}
else
{
s.userData = ships + 150 - s.ships * 2;
}
}
}
public function isColonized(star:Star):Boolean
{
return star.owner == this;
}
public function get ships():Number
{
return _ships;
}
public function distance(a:Star, b:Star):Number
{
return ((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y)) / 3;
}
public function isGoal(f:Star, t:Star):Boolean
{
if(enemyApproaching(f))
{
return false;
}
if(t.owner != this)
{
return ships / 2 > t.ships;
}
return false;
}
public function enemyApproaching(s:Star):Boolean
{
for(var i:int =0;i<s.visitors.length;i++)
{
var e:ShipEmitter = s.visitors[i];
if(e.owner != this)
{
return true;
}
}
return false;
}
}