createGridTable : false
showGridCoords : false
showFpsGraph : false
+ allowViewportScroll : false
map:
refSize : &ref_size 50
rockSizeMin : 12.5
lootTable : ''
stats:
hp : 1 # health
- move : 1.0 # move speed (squares/sec)
+ move : 1.0 # move speed (squares/sec or orbits/sec)
+ rotate : 1.0 # rotation speed (full-turns/sec)
power : 1 # attack power
speed : 0.5 # attack cool (sec)
accuracy : 1.0 # chance of shooting where aiming
turret : '#C13B00'
barrel : '#244792'
-
+ shield:
+ name: Shield Sphere
+ desc: A protective sphere of energy.
+ tags: [ 'shield' ]
+ symbol: tanks/thing/shield.Shield
+ stats:
+ hp : 1
+ move : 0.5
+ power : 1
+ orbit : 9
+ width : 9
+ height : 9
+ color: '#0A9CFF'
+
+
with path('build/versioned-build.html').open('w') as f:
f.write('<script>BUILD="build/{}";</script>\n'.format(git_version))
with path('build/versioned-app.html').open('w') as f:
- f.write('<script src="build/{}/{}";</script>\n'.format(git_version, APP_FILE))
+ f.write('<script src="build/{}/{}"></script>\n'.format(git_version, APP_FILE))
@task
"Builds the Tanks project"
pass
+
+
@task
@needs('build')
def compress(outfile='build/'+APP_FILE, yuic_jar='~/bin/yuic.jar'):
sh('cat %s | java -jar %s --type js -o %s' % (mods.replace('\n', ' '), yuic_jar, outfile))
@task
+@needs('build')
+def compress_each(yuic_jar='~/bin/yuic.jar'):
+ yuic_jar = path(yuic_jar).expand()
+ info('Compressing Each Source File (YUI Compressor=%s)' % yuic_jar)
+ for dirpath, dirs, files in os.walk(BUILD_DIR):
+ dirpath = path(dirpath)
+ for f in files:
+ if not f.endswith('.js') or f.endswith('.min.js'):
+ continue
+ in_ = dirpath / f
+ out = dirpath / f[:-3] + '.min.js'
+ sh('java -jar %s --type js -o %s %s' % (yuic_jar, out, in_))
+
+@task
+def combine_all(outfile='build/'+APP_FILE, minified=True, add_newlines=True):
+ info('Concatenating Source Files')
+ mods = commonjs(file_list=True, capture=True)
+ if minified:
+ mods = mods.replace('.js\n', '.min.js\n')
+ if add_newlines:
+ sh('echo "" > .NL')
+ modlist = mods.replace('\n', ' .NL ')
+ else:
+ modlist = mods.replace('\n', ' ')
+
+ sh('cat %s > %s' % (modlist, outfile))
+
+ if add_newlines:
+ sh('rm .NL')
+
+@task
def clean():
"Cleans dep cache and build files"
commonjs(clean=True)
parentMembers = Parent[P] || {};
}
- // Creates a new function with the appropriate name
- // based on the className.
- var NewClass, constructor =
- 'var '+className+' = NewClass = '+
- (''+_Class).replace(_Class.name, className) + ';';
- eval(constructor);
+ // Creates a new function with the appropriate name based on the className.
+ var constructor = ('('+_Class+')').replace(_Class.name, className)
+ , NewClass = eval(constructor);
// Copy Class statics
for (var i=0, L=classStatics.length; i<L; ++i) {
prototype.toString = classToString;
// Fix Constructors, prototypes
- NewClass[P] = NewClass.fn = prototype;
- prototype.constructor = prototype.__class__ = NewClass;
- NewClass.__super__ = SuperClass; // don't override NewClass.constructor -- it should be Function
- NewClass.className = prototype.className = className;
+ NewClass[P] = NewClass['fn'] = prototype;
+ prototype['constructor'] = prototype['__class__'] = NewClass;
+ NewClass['__super__'] = SuperClass; // don't override NewClass.constructor -- it should be Function
+ NewClass['className'] = prototype['className'] = className;
// Either invoke body constructor...
if ( isFunction(members) ) {
setDesc(prototype, k, getDesc(members,k));
}
- if (prototype.init) NewClass.init = YFunction(prototype.init);
+ if (prototype.init) NewClass['init'] = YFunction(prototype.init);
KNOWN_CLASSES[className] = NewClass;
}
// Add metaprogramming data to Class object
-Class.__super__ = Object;
-Class.fn = Class[P];
-Class.fn.__class__ = Class;
-Class.className = Class.fn.className = "Class";
+Class['__super__'] = Object;
+Class['fn'] = Class[P];
+Class.fn['__class__'] = Class;
+Class['className'] = Class.fn['className'] = "Class";
/* Class Methods */
return new Class(className, this, members);
}
-Class.subclass =
-Class.fn.subclass = YFunction(subclass);
+Class['subclass'] =
+Class.fn['subclass'] = YFunction(subclass);
[ fabricate, instantiate
* Root-class for all Y-objects.
*/
YBase = new Class("YBase", {
- __y__ : true
+ '__y__' : true
});
exports['Class'] =
-exports['subclass'] = Class;
-exports['YBase'] = YBase;
+exports['subclass'] = Class;
+exports['YBase'] = YBase;
// exports['instantiate'] = instantiate;
// exports['fabricate'] = fabricate;
// Creates a new function with the appropriate name
// based on the className.
- var NewClass,
- constructor = [
- 'var '+className,
- (''+ConstructorTemplate).replace(ConstructorTemplate.name, className),
- 'NewClass = '+className, ''
- ].join(';\n');
-
- eval(constructor);
+ var constructor = ('('+ConstructorTemplate+')').replace(ConstructorTemplate.name, className);
+ // var NewClass, constructor =
+ // 'var NewClass, '+className+' = NewClass = '+
+ // (''+_Class).replace(_Class.name, className) + ';';
+ var NewClass = eval(constructor);
// Copy parent methods, then add new instance methods
for (var k in parentMembers) {
--- /dev/null
+var Y = require('Y').Y
+, Vec = require('ezl/math/vec').Vec
+, _X = 0, _Y = 1
+,
+
+Circle =
+exports['Circle'] =
+Y.subclass('Circle', {
+ isCircle : true,
+
+ init : function initCircle(x,y, radius){
+ if (x instanceof Array) { radius=y; y=x[_Y]; x=x[_X]; }
+ this.x = x; // center of circle
+ this.y = y;
+ this.radius = radius;
+ },
+
+ get loc(){ return new Vec(this.x,this.y); },
+ set loc(v){ this.x = v.x; this.y = v.y; },
+
+ parametric : function parametric(t){
+ var r = this.radius
+ , x = this.x + r*Math.cos(t)
+ , y = this.y + r*Math.sin(t)
+ ;
+ return new Vec(x,y);
+ },
+
+ iparametric : function iparametric(x,y){
+ if (x instanceof Array) { y=x[_Y]; x=x[_X]; }
+ var r = this.radius
+ , tx = Math.acos((x - this.x) / r)
+ , ty = Math.asin((y - this.y) / r)
+ ;
+ // tx and ty should be the same number provided (x,y) is on the trajectory
+ return (tx+ty) * 0.5;
+ },
+
+ timeToMove : function timeToMove(dx,dy){
+ if (dx instanceof Array) { dy=dx[1]; dx=dx[0]; }
+ return Math.abs( Math.acos(dx/this.radius) + Math.asin(dy/this.radius) ) * 0.5; // see note at iparametric
+ },
+
+ pointAtX : function pointAtX(x){ return this.parametric(Math.acos((x - this.x)/this.radius)); },
+ pointAtY : function pointAtY(y){ return this.parametric(Math.asin((y - this.y)/this.radius)); }
+
+
+})
+;
-//#exports BoundsType.{PASSABLE,ZONE,BLOCKING,IRREGULAR,COMPLEX}
+//#exports BoundsType.{PASSABLE,ZONE,BLOCKING,IRREGULAR}
//#exports DensityType.{PASSABLE,BOUNDARY,DENSE,SPARSE,IRREGULAR}
//#exports StatInvariant.{NONE,RATIO,FULL}
/** Obstructs other blockers with its BoundingBox. */
BLOCKING : 2,
- /** Potentially obstructs other objects, but requires a special test once a BoundingBox collision has been detected. */
- IRREGULAR : 3,
-
- /** Potentially obstructs other objects, but requires a special test, and may instruct a different object become the target of the collision. */
- COMPLEX : 4
+ /**
+ * Potentially obstructs other objects, but requires a special test once a
+ * BoundingBox collision has been detected, and may instruct a different
+ * object become the target of the collision.
+ */
+ IRREGULAR : 3
},
// Config
gameoverDelay : null,
+ allowViewportScroll : false,
// Instance
levelId : 'test',
this.animations = this.animations.filter(this.tickAnimations, this);
this.draw();
- this.viewport.centerOn( this.player.loc );
+ if ( !this.allowViewportScroll )
+ this.viewport.centerOn( this.player.loc );
if ( this.gameover )
return;
});
-config.updateOnChange('game.gameoverDelay', Game.fn);
+config.updateOnChange(['game.gameoverDelay', 'debug.allowViewportScroll'], Game.fn);
, SECONDTH = ELAPSED / 1000 // Amount of second completed in this tick
, SQUARETH = REF_SIZE * SECONDTH // Amount of square/second covered in this tick
-, PI = Math.PI
-, QUARTER_PI = PI/4
-, HALF_PI = PI/2
-, PI_AND_HALF = PI + HALF_PI
-, TWO_PI = PI*2
-
;
--- /dev/null
+var Y = require('Y').Y
+, op = require('Y/op')
+, Circle = require('ezl/math/circle').Circle
+, BOUND_SIZE_RATIO = 0.75
+,
+
+CircularTrajectory =
+exports['CircularTrajectory'] =
+Circle.subclass('CircularTrajectory', {
+
+ init : function initCircularTrajectory(owner, x,y, radius, radsPerTick, tCurrent){
+ Y.bindAll(this, 'compare'); //, 'closer', 'intersects');
+ this.owner = owner;
+ Circle.init.call(this, x,y, radius);
+ this.radsPerTick = radsPerTick;
+ this.tCurrent = tCurrent || 0;
+ this.tBound = BOUND_SIZE_RATIO * Math.min(owner.width, owner.height);
+ },
+
+ /**
+ * Linear approximation of distance so we don't have to figure out the intersection point.
+ */
+ compare : function compare(a, b){
+ var oa = a, ob = b;
+ if ( a.loc ) a = a.loc;
+ if ( b.loc ) b = b.loc;
+
+ var abs = Math.abs
+ , loc = this.owner.loc
+ , ax = a.x-this.x, ay = a.y-this.y
+ , bx = b.x-this.x, by = b.y-this.y
+ , ta = ax*ax + ay*ay
+ , tb = bx*bx + by*by
+ ;
+
+ return op.cmp(ta, tb);
+ },
+
+ _compare : function compare(a, b){
+ var oa = a, ob = b;
+ if ( a.loc ) a = a.loc;
+ if ( b.loc ) b = b.loc;
+
+ var abs = Math.abs
+ , t = this.tCurrent
+
+ , ta = this.iparametric(a) - t
+ , tb = this.iparametric(b) - t
+ ;
+
+ if (ta < 0 && tb >= 0)
+ return 1;
+ if (tb < 0 && ta >= 0)
+ return -1;
+ return op.cmp(abs(ta), abs(tb));
+ },
+
+})
+;
require('Y').Y
.extend(exports, {
- 'Map' : require('tanks/map/pathing/map').Map,
- 'Traversal' : require('tanks/map/pathing/traversal').Traversal,
- 'Trajectory' : require('tanks/map/pathing/trajectory').Trajectory
+ 'Map' : require('tanks/map/pathing/map').Map,
+ 'Traversal' : require('tanks/map/pathing/traversal').Traversal,
+ 'LinearTrajectory' : require('tanks/map/pathing/linear-trajectory').LinearTrajectory,
+ 'CircularTrajectory' : require('tanks/map/pathing/circular-trajectory').CircularTrajectory
});
,
-Trajectory =
-exports['Trajectory'] =
-Line.subclass('Trajectory', {
+LinearTrajectory =
+exports['LinearTrajectory'] =
+Line.subclass('LinearTrajectory', {
tCurrent : 0,
- init : function initTrajectory(owner, x1,y1, x2,y2, tdist, tCurrent){
+ init : function initLinearTrajectory(owner, x1,y1, x2,y2, tdist, tCurrent){
Y.bindAll(this, 'compare', 'closer', 'intersects');
this.owner = owner;
},
clone : function clone(){
- return new Trajectory(this.owner, this.x1,this.y1, this.x2,this.y2, this.tdist, this.tCurrent);
+ return new LinearTrajectory(this.owner, this.x1,this.y1, this.x2,this.y2, this.tdist, this.tCurrent);
},
_filterBlockers : function _filterBlockers(v){
return (v.blocking === BoundsType.BLOCKING
- || v.blocking === BoundsType.IRREGULAR
- || v.blocking === BoundsType.COMPLEX );
+ || v.blocking === BoundsType.IRREGULAR );
},
wallObstructs : function wallObstructs(line){
_filterBlocked : function filterBlocked(v, r){
// FIXME: calc bbox for new loc to testCollide()
var bbox = null;
- return ( v.blocking === BoundsType.BLOCKING && !(v.isBoundary || v.isProjectile) )
- || ((v.blocking === BoundsType.IRREGULAR || v.blocking === BoundsType.COMPLEX) && v.testCollide(this.agent,this,bbox));
+ return (v.blocking === BoundsType.BLOCKING && !(v.isBoundary || v.isProjectile) )
+ || (v.blocking === BoundsType.IRREGULAR && v.testCollide(this.agent,this,bbox));
},
getNeighbors : function getNeighbors(){
, manhattan = vec.manhattan
, Map = require('tanks/map/pathing/map').Map
-, Trajectory = require('tanks/map/pathing/trajectory').Trajectory
+, LinearTrajectory = require('tanks/map/pathing/linear-trajectory').LinearTrajectory
, Bullet = require('tanks/thing/bullet').Bullet
, _X = 0, _Y = 1
function nearEnemyInSightFilter(agent){
var me = this; // Runs in the context of the 'me' unit; @see this.findNearLike()
return ( agent.isCombatant && agent.align !== me.align &&
- new Trajectory(me, me.loc, agent.loc).canSee(agent) );
+ new LinearTrajectory(me, me.loc, agent.loc).canSee(agent) );
}
Traversal =
exports['Traversal'] =
Y.subclass('Traversal', {
- ignore : null, // objects to ignore when determining blockers
+ thing : null, // agent and its various state-objects
+ game : null,
+ map : null,
+ trajectory : null, // movement path of the agent
+ ignore : null, // objects to ignore when determining blockers
isBlocked : false,
to : null, // furthest point reached
+ bbox : null, // current agent position (cloned)
remaining : 0, // time left unconsumed due to blocker
blocker : null, // blocking object
side : null, // collision side of blocker (Line)
init : function initTraversal(thing, trajectory, ignore){
this.ignore = Y(ignore || []);
- this.thing = thing;
- this.game = thing.game;
- this.map = thing.game.map;
- this.bbox = thing.bbox.clone();
+ this.thing = thing;
+ this.game = thing.game;
+ this.map = thing.game.map;
+ this.bbox = thing.bbox.clone();
this.trajectory = trajectory || thing.trajectory;
},
traverse : function traverse(t, tx,ty){
- var tr = this.trajectory;
this.remaining = t;
do {
* Filters found obstructions to keep only those not ignored and blocking.
*/
checkBlocker : function checkBlocker(blocker){
- var blocking = blocker.blocking
+ var oBlocking = this.thing.blocking
+ , blocking = blocker.blocking
, density = blocker.density;
// All blockers after the first are ignored
// Skip passable objects
|| (blocking === BoundsType.PASSABLE)
- // Ask irregular objects if we hit
- || (blocking === BoundsType.IRREGULAR && !blocker.testCollide(this.thing,this.to,this.bbox,this))
-
- // Ask complex objects if we hit, and recall they might go busta on us
- || blocking === BoundsType.COMPLEX && !blocker.testCollide(this.thing,this.to,this.bbox,this)
+ // Ask irregular objects if we hit (and recall it might change this.ignore or this.blocker)
+ || (oBlocking === BoundsType.IRREGULAR && !this.thing.testCollide(blocker,this.to,null,this))
+ || (blocking === BoundsType.IRREGULAR && !blocker.testCollide(this.thing,this.to,this.bbox,this))
// Filter out Sparse objects if bullet
|| (density === DensityType.SPARSE && this.thing.isProjectile) )
}
this.isBlocked = true;
- if (!this.blocker) this.blocker = blocker; // BoundsType.COMPLEX might switch blockers on us
+ if (!this.blocker) this.blocker = blocker; // BoundsType.IRREGULAR might switch blockers on us
return true;
},
, stat = require('tanks/effects/stat')
, Explosion = require('tanks/fx/explosion').Explosion
, Thing = require('tanks/thing/thing').Thing
-, Trajectory = require('tanks/map/pathing/trajectory').Trajectory
+, LinearTrajectory = require('tanks/map/pathing/linear-trajectory').LinearTrajectory
, Traversal = require('tanks/map/pathing/traversal').Traversal
,
Thing.init.call(this, owner.align);
this.position(x1,y1);
- this.trajectory = new Trajectory(this, x1,y1, x2,y2, this.movePerMs);
+ this.trajectory = new LinearTrajectory(this, x1,y1, x2,y2, this.movePerMs);
this.on('collide', this.onCollide);
},
, Thing = require('tanks/thing/thing').Thing
,
-Accessory =
-exports['Accessory'] =
-Thing.subclass('Accessory', {
- __bind__ : [ 'onCollide' ],
+/**
+ * Units that need to be activated in order after another unit has acted.
+ */
+Component =
+exports['Component'] =
+Thing.subclass('Component', {
// Instance
- blocking : BoundsType.BLOCKING,
+ blocking : BoundsType.IRREGULAR, // Need to allow shields etc to passthrough like-aligned units
- isAccessory : true,
+ isComponent : true,
- active : true, // Agent takes actions?
+ active : false, // Owner will notify us to ensure we go at the right time
isRenderable : true, // Agent will present itself for rendering when ready // FIXME: stupid hack
isReflective : false, // Projectiles bounce off agent rather than explode?
hasInventory : false, // Agent can acquire items?
- init : function initAccessory(owner){
+ init : function initComponent(owner){
this.owner = owner;
this.game = owner.game;
Thing.init.call(this, owner.align);
-
- },
-
- testCollide : function testCollide(agent, to, bbox, traversal){
- return false;
- },
-
- onCollide : function onCollide(evt){
-
- },
-
- render : function render(parent){
- this.remove();
-
- var loc = this.loc;
- this.shape = new Circle(this.width/2)
- .position(loc.x, loc.y)
- .fill(this.color)
- .appendTo( parent );
-
- return this;
}
+
})
;
var Y = require('Y').Y
-, tank = require('tanks/thing/tank')
, bullet = require('tanks/thing/bullet')
+, component = require('tanks/thing/component')
, item = require('tanks/thing/item')
-, accessory = require('tanks/thing/accessory')
, player = require('tanks/thing/player')
+, shield = require('tanks/thing/shield')
+, tank = require('tanks/thing/tank')
, thing = require('tanks/thing/thing')
;
Y.core.extend(exports, {
- 'Tank' : tank.Tank,
- 'Bullet' : bullet.Bullet,
- 'Item' : item.Item,
- 'Accessory' : accessory.Accessory,
- 'Player' : player.Player,
- 'Thing' : thing.Thing
+ 'Bullet' : bullet.Bullet,
+ 'Component' : component.Component,
+ 'Item' : item.Item,
+ 'Player' : player.Player,
+ 'Shield' : shield.Shield,
+ 'Tank' : tank.Tank,
+ 'Thing' : thing.Thing
});
, Tank = require('tanks/thing/tank').Tank
, Inventory = require('tanks/inventory/inventory').Inventory
, Inventoried = require('tanks/mixins/inventoried').Inventoried
+, Shield = require('tanks/thing/shield').Shield
,
stats: {
hp : 1, // health
move : 0.90, // move speed (squares/sec)
- rotate : HALF_PI, // rotation speed (radians/sec)
+ rotate : 1.0, // rotation speed (rotations/sec)
power : 1, // attack power
speed : 0.5, // attack cool (sec)
shots : 5 // max projectiles in the air at once
/// Instance ///
align : null,
- replayMode : false,
- init : function init(align, replay){
+ init : function init(align){
Tank.init.call(this, align);
this.gameLog = [];
this.activeKeys = new Y.YArray();
this.inventory = new Inventory(this);
- if (this.replayMode) {
- this.replay = replay
- this.nextMove = replay.shift();
-
- } else {
- $(document)
- .bind('keydown', this.keydown)
- .bind('keyup', this.keyup)
- .bind('mousemove', this.mousemove);
- $('#viewport')
- .bind('mousedown', this.mousedown)
- .bind('mouseup', this.mouseup);
- }
+ $(document)
+ .bind('keydown', this.keydown)
+ .bind('keyup', this.keyup)
+ .bind('mousemove', this.mousemove);
+ $('#viewport')
+ .bind('mousedown', this.mousedown)
+ .bind('mouseup', this.mouseup);
+
+ var self = this;
+ this.game.on('ready', function(){
+ for (var i=0; i<1; i += 0.25) {
+ self.components.push( Shield.create('shield', self, i * 2*Math.PI) );
+ }
+ });
},
destroy : function destroy(){
}
}
- if ( !action )
+ if ( !action ) {
+ this.components.invoke('act', elapsed, now);
return this;
+ }
var data = action.data;
switch (action.type) {
break;
}
+ this.components.invoke('act', elapsed, now);
return this;
},
--- /dev/null
+var Y = require('Y').Y
+, Circle = require('ezl/shape/circle').Circle
+
+, constants = require('tanks/constants')
+, BoundsType = constants.BoundsType
+, Thing = require('tanks/thing/thing').Thing
+, Component = require('tanks/thing/component').Component
+, Traversal = require('tanks/map/pathing/traversal').Traversal
+, CircularTrajectory = require('tanks/map/pathing/circular-trajectory').CircularTrajectory
+
+, SQRT_TWO = Math.sqrt(2)
+, TWO_PI = 2 * Math.PI
+,
+
+Shield =
+exports['Shield'] =
+Component.subclass('Shield', {
+ // __bind__ : [ 'onCollide' ],
+
+ // Instance
+ blocking : BoundsType.IRREGULAR, // Need to allow shields etc to passthrough like-aligned units
+
+ isComponent : true,
+ isShield : true,
+
+ active : false, // Owner will notify us to ensure we go at the right time
+ isRenderable : true, // Agent will present itself for rendering when ready // FIXME: stupid hack
+ isReflective : false, // Projectiles bounce off agent rather than explode?
+ hasInventory : false, // Agent can acquire items?
+
+ orbit : 9,
+ width : 9,
+ height : 9,
+
+ color : '#0A9CFF',
+
+ stats : {}, // radial speed in revolutions/sec
+
+ // state
+ radius : 0,
+ radsPerTick : 0,
+ radialPosition : 0,
+
+
+
+ init : function initShield(owner, radialPosition){
+ Component.init.call(this, owner);
+
+ var obb = owner.bbox, oloc = owner.loc;
+ this.radialPosition = radialPosition || 0;
+ this.radius = this.orbit + SQRT_TWO * Math.max(obb.width, obb.height) / 2;
+ this.radsPerTick = TWO_PI * this.stats.move.val / 1000 * MS_PER_FRAME;
+
+ this.trajectory = new CircularTrajectory(this, oloc.x,oloc.y, this.radius, this.radsPerTick, this.radialPosition);
+ this.act(0);
+ },
+
+ testCollide : function testCollide(agent, bbox, to, traversal){
+ return agent.isProjectile && (agent.align !== this.align);
+ },
+
+ act : function act(elapsed, now){
+ var oloc = this.owner.loc
+ , tr = this.trajectory;
+ tr.x = oloc.x; tr.y = oloc.y;
+
+ var tvsl = new Traversal(this)
+ , to = tvsl.traverse(this.radsPerTick);
+
+ this.game.moveThingTo(this, to.x,to.y);
+
+ // var oloc = this.owner.loc
+ // , t = (this.radialPosition += this.radsPerTick)
+ // , r = this.radius
+ // , x = oloc.x + r*Math.cos(t)
+ // , y = oloc.y + r*Math.sin(t)
+ // ;
+ // this.game.moveThingTo(this, x,y);
+ return this;
+ },
+
+ render : function render(parent){
+ this.remove();
+
+ var loc = this.loc;
+ this.shape = new Circle(this.width/2)
+ .position(loc.x, loc.y)
+ .fill(this.color)
+ .appendTo( parent );
+
+ return this;
+ }
+})
+;
, constants = require('tanks/constants')
, BoundsType = constants.BoundsType
, DensityType = constants.DensityType
-, Trajectory = require('tanks/map/pathing/trajectory').Trajectory
+, LinearTrajectory = require('tanks/map/pathing/linear-trajectory').LinearTrajectory
, Traversal = require('tanks/map/pathing/traversal').Traversal
, Thing = require('tanks/thing/thing').Thing
, Bullet = require('tanks/thing/bullet').Bullet
// Nothing to shoot at? Move toward something
this.continueMove();
+ this.components.invoke('act', elapsed, now);
return this;
};
if (x instanceof Array) { y=x[_Y]; x=x[_X]; }
var loc = this.loc;
- this.trajectory = new Trajectory(this, loc.x,loc.y, x,y, this.movePerMs);
+ 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) ;
// Attributes
stats: {
- // rotate : HALF_PI, // rotation speed (radians/sec) [UNUSED]
hp : 1, // health
move : 1.0, // move speed (squares/sec)
power : 1, // attack power
// AI "Cooldowns" (max frequency of each action per sec)
ai : {}, // see Tank
+ components : [],
+
// *** Bookkeeping *** //
isWall : false,
isProjectile : false,
isAccessory : false,
+ isComponent : false,
active : true, // Agent takes actions?
isRenderable : false, // Agent will present itself for rendering when ready // FIXME: stupid hack
// Location
loc : null,
bbox : null,
-
- // subclasses with BoundsType.{IRREGULAR,COMPLEX} should override:
- testCollision : function testCollide(agent, to, bbox, traversal){ return false; },
+ ownBbox : null,
// Rotation (rads)
rotation : 0,
init : function init(align){
this.align = align || this.align;
+ this.components = new Y.YArray();
this.createBoundingBox();
this.createStats();
this.createCooldowns();
this.bbox = new BoundingBox(0,0, this.width,this.height, this.originX,this.originY);
},
+ // subclasses with BoundsType.{IRREGULAR,COMPLEX} should override but probably delegate on false
+ testCollision : function testCollide(agent, bbox, to, traversal){ return true; },
+
position : function position(x,y){
if (x === undefined && y === undefined)
return this.loc;
overlay = $('#overlay');
updateOverlay( config.get('ui.overlayOnPause') );
- config.on('set:ui.overlayOnPause', function(evt){ updateOverlay(evt.newval); });
- config.on('set:debug.showFpsGraph', function(evt){ updateUI('#info', evt.newval); });
- config.on('set:debug.showGridCoords', function(evt){ $('body')[(evt.newval ? 'add' : 'remove' )+'Class']('showGridCoords'); });
-
- config.set('debug.showGridCoords', config.get('debug.showGridCoords'));
+ Y.forEach({
+ 'ui.overlayOnPause' : function(evt){ updateOverlay(evt.newval); },
+ 'debug.showFpsGraph' : function(evt){ updateUI('#info', evt.newval); },
+ 'debug.showGridCoords' : function(evt){ $('body')[(evt.newval ? 'add' : 'remove' )+'Class']('showGridCoords'); },
+ 'debug.allowViewportScroll' : function(evt){ $('body')[(evt.newval ? 'add' : 'remove' )+'Class']('allowViewportScroll'); }
+ }, function(fn, key){
+ config.on('set:'+key, fn);
+ config.set(key, config.get(key));
+ });
/// Debug ///
if (qkv.debug || config.get('debug.showFpsGraph'))
#viewport .layer.grid { outline:1px solid rgba(255,255,255, 0.1); }
#viewport .ezl.layer.map { }
#viewport .ezl.layer.pathmap { z-index:50; }
-
+.allowViewportScroll #viewport { overflow:scroll; }
.item-container { position:absolute; }
<div id="scripts">
<!--# include file="build/versioned-build.html" -->
-<!--# include file="build/versioned-deps.html" -->
+<!--# include file="build/versioned-app.html" -->
<!--# include file="ga.html" -->
</div>