Tank =
exports['Tank'] =
-Unit.subclass('Tank', function(Tank){
+Unit.subclass('Tank', {
+ isUnit : true,
+ isCombatant : true,
+ lootTable : '',
- Y.core.descriptors(this, {
- isUnit : true,
- isCombatant : true,
- lootTable : '',
-
- colors : {
- body : '#83BB32',
- turret : '#1C625B',
- barrel : '#D43B24'
- },
-
- hasBarrel : true,
- barrel: {
- width : 'unit.width * 0.75',
- height : 'unit.height / 6',
- originX : 2,
- originY : '50%',
- x : '50%',
- y : '50%'
- },
-
- // Bounding box
- width : REF_SIZE*0.55,
- height : REF_SIZE*0.55,
-
- // Attributes
- stats : {},
-
- // AI "Cooldowns" (max frequency of each action per sec)
- ai : {},
-
- projectile : 'bullet',
- defaultProjectile : null,
-
- /// Instance ///
-
- align : null,
- buffs : null,
-
+ colors : {
+ body : '#83BB32',
+ turret : '#1C625B',
+ barrel : '#D43B24'
+ },
+
+ hasBarrel : true,
+ barrel: {
+ width : 'unit.width * 0.75',
+ height : 'unit.height / 6',
+ originX : 2,
+ originY : '50%',
+ x : '50%',
+ y : '50%'
+ },
+
+ // Bounding box
+ width : REF_SIZE*0.55,
+ height : REF_SIZE*0.55,
+
+ // Attributes
+ stats : {},
+
+ // AI "Cooldowns" (max frequency of each action per sec)
+ ai : {},
+
+ projectile : 'bullet',
+ defaultProjectile : null,
+
+ /// Instance ///
+
+ align : null,
+ buffs : null,
+
+ trajectory : null,
+ currentMove : null,
+ currentPath : null,
+ forceCurrentMove : false,
+ currentMoveLimit : -1,
+
+ recoil : {
trajectory : null,
- currentMove : null,
- currentPath : null,
- forceCurrentMove : false,
- currentMoveLimit : -1,
-
- recoil : {
- trajectory : null,
- remaining : 0,
- speed : 0
- },
-
- nShots : 0
- });
+ remaining : 0,
+ speed : 0
+ },
+
+ nShots : 0,
- this['init'] =
- function initTank(align){
+
+ init : function initTank(align){
Unit.init.call(this, align);
this.atkGauge = new CooldownGauge(this.cooldowns.attack, this.width+1,this.height+1);
- };
-
- // Lootable.mixInto(Tank);
+ },
- this['act'] =
- function act(elapsed, now){
+ act : function act(elapsed, now){
var ai = this.ai
, map = this.game.map
, mobile = this.stats.move.val > 0
if (mobile) this.applyRecoilMove();
- // Check to see if we should obey our last decision, and not recalc
- if (mobile && this.forceCurrentMove && this.forceCurrentMove() && this.currentMoveLimit > now) {
- // console.log('forced!', this.currentMove);
- this.continueMove();
- return this;
- } else
- this.forceCurrentMove = false;
-
// Try to shoot down nearby bullets
if (ai.shootIncoming.ready && this.ableToShoot()) {
}
}
+ // Check to see if we should obey our last decision, and not recalc
+ if (mobile && this.forceCurrentMove && this.forceCurrentMove() && this.currentMoveLimit > now) {
+ // console.log('forced!', this.currentMove);
+ this.continueMove();
+ return this;
+ } else
+ this.forceCurrentMove = false;
+
// Dodge incoming bullet
if (mobile && ai.dodge.ready) {
var bs = map.willCollide(this, map.findNearBullets(this, 71), 5);
if (mobile) this.continueMove();
this.components.invoke('act', elapsed, now);
return this;
- };
+ },
- /**
- * Fires this agent's cannon. If a target location is omitted, the shot
- * will be fired in the direction of the tank's current barrel rotation.
- *
- * @param {Number} [x] Target X coordinate.
- * @param {Number} [y] Target Y coordinate.
- */
- // this['shoot'] =
- // function shoot(x,y){
- // if ( this.nShots >= this.stats.shots.val || !this.cooldowns.attack.ready )
- // return null;
- //
- // if (x instanceof Array) { y = x[_Y]; x = x[_X]; }
- // var xydef = (x !== undefined && y !== undefined);
- // if (xydef)
- // this.rotateBarrel(x,y);
- //
- // // Additional space on each side which must be clear around the
- // // shot to ensure we don't shoot ourself in the foot (literally)
- // var WIGGLE = 2
- // , Projectile = this.projectile
- // , pw2 = Projectile.fn.width/2, ph2 = Projectile.fn.height/2
- //
- // , tloc = this.getTurretLoc()
- // , tx = tloc.x, ty = tloc.y
- //
- // , x1 = tx - pw2 - WIGGLE, y1 = ty - ph2 - WIGGLE
- // , x2 = tx + pw2 + WIGGLE, y2 = ty + ph2 + WIGGLE
- // , blockers = this.game.map.get(x1,y1, x2,y2).filter(filterShoot, this)
- // ;
- //
- // if ( blockers.size() )
- // return null; // console.log('squelch!', blockers);
- //
- // if (!xydef) {
- // var theta = this.barrelShape.transform.rotate
- // , sin = Math.sin(theta), cos = Math.cos(theta);
- // x = tx + REF_SIZE*cos;
- // y = ty + REF_SIZE*sin;
- // }
- //
- // this.cooldowns.attack.activate(this.now);
- // this.nShots++;
- //
- // var p = new Projectile(this, tx,ty, x,y);
- // p.on('destroy', this.onBulletDeath);
- // return p;
- // };
- function filterShoot(v){
- return (v !== this)
- && (v.density === DensityType.BOUNDARY || (v.isWall && v.density === DensityType.DENSE));
- }
- this['ableToShoot'] =
- function ableToShoot(){
- return this.nShots < this.stats.shots.val && this.cooldowns.attack.ready;
- };
- /**
- * @return {this}
- */
- // this['move'] =
- // function move(x,y){
- // if (x instanceof Array) { y=x[_Y]; x=x[_X]; }
- //
- // var loc = this.loc;
- // this.trajectory = new LinearTrajectory(this, loc.x,loc.y, x,y, this.movePerMs());
- //
- // var tvsl = new Traversal(this)
- // , to = tvsl.traverse(this.elapsed, x,y) ;
- //
- // this.game.moveThingTo(this, to.x,to.y);
- //
- // return this;
- // };
-
- this['continueMove'] =
- function continueMove(){
+ continueMove : function continueMove(){
if ( (!this.currentMove || this.ai.path.ready) && this.game.pathsThisTick < 1 ){
var target = this.game.map.findNearEnemies(this).shift();
if (target)
this.currentMove = ((path && path.length) ? path.shift() : null);
// console.log('--> next move:', this.currentMove, 'path: ['+path.invoke('toString')+']');
}
- };
+ },
- this['calculatePath'] =
- function calculatePath(end){
+ calculatePath : function calculatePath(end){
if ( !end || this.game.pathsThisTick >= 1 || !this.ai.path.activate() ) return;
// this.currentMove = null;
, to = this.currentMove = path.shift()
;
// console.log('calculatePath()', start, 'toward:', end, 'next:', this.currentMove, 'path: '+path.invoke('toString'));
- };
+ },
- this['moveAwayFrom'] =
- function moveAwayFrom(agent){
+ moveAwayFrom : function moveAwayFrom(agent){
var map = this.game.map
, mid = this.midpoint
, trj = agent.trajectory.tangent(mid)
// console.log(' --> Dodge', agent, 'away from', wall, 'to', to);
return to;
- };
+ },
* Sets up unit appearance for minimal updates. Called once at start,
* or when the world needs to be redrawn from scratch.
*/
- this['render'] =
- function render(parent){
+ render : function render(parent){
if (this.shape) this.shape.remove();
var colors = this.colors
.fill( colors.barrel ) ;
return this;
- };
+ },
- this['tankColors'] =
- function tankColors(bodyColor, turretColor, barrelColor){
+ tankColors : function tankColors(bodyColor, turretColor, barrelColor){
var colors = this.colors;
if (arguments.length === 0)
return colors;
if (turretColor) colors.turret = turretColor;
if (barrelColor) colors.barrel = barrelColor;
return this;
- };
+ },
- this['getTurretLoc'] =
- function getTurretLoc(){
+ getTurretLoc : function getTurretLoc(){
var WIGGLE = 2
, loc = this.loc
, barrel = this.barrelShape
, y = loc.y + len*sin
;
return new Vec(x,y);
- };
+ },
- this['getBarrelAngle'] =
- function getBarrelAngle(){
+ getBarrelAngle : function getBarrelAngle(){
return this.barrelShape.transform.rotate;
- };
+ },
- this['rotateBarrel'] =
- function rotateBarrel(x,y){
+ rotateBarrel : function rotateBarrel(x,y){
this.barrelShape.rotate(this.angleTo(x,y));
return this;
- };
+ },
// FIXME: delegate to Barrel
- this['rotateBarrelRelPage'] =
- function rotateBarrelRelPage(pageX, pageY){
+ rotateBarrelRelPage : function rotateBarrelRelPage(pageX, pageY){
var shape = this.shape
, off = shape.offset()
, w = this.width, h = this.height
;
this.barrelShape.rotate(theta);
return this;
- };
+ }
});