Checkpoint on collision refactor to support zones.
authordsc <david.schoonover@gmail.com>
Sat, 18 Dec 2010 17:20:48 +0000 (09:20 -0800)
committerdsc <david.schoonover@gmail.com>
Sat, 18 Dec 2010 17:20:48 +0000 (09:20 -0800)
40 files changed:
src/Y/index.cjs
src/Y/modules/y.config.cjs
src/Y/modules/y.event.cjs
src/Y/modules/y.scaffold.cjs
src/Y/type.cjs
src/Y/types/function.cjs
src/Y/y.cjs
src/evt.cjs
src/ezl/layer.cjs
src/ezl/loc/boundingbox.cjs
src/ezl/loop/eventloop.cjs
src/ezl/math/line.cjs
src/ezl/shape/circle.cjs
src/ezl/shape/line.cjs
src/ezl/shape/polygon.cjs
src/ezl/shape/rect.cjs
src/ezl/util/configuration.cjs [deleted file]
src/ezl/widget/cooldown.cjs
src/tanks/abilities/buff.cjs [new file with mode: 0644]
src/tanks/abilities/index.cjs [new file with mode: 0644]
src/tanks/config.cjs
src/tanks/game.cjs
src/tanks/index.js
src/tanks/map/level.cjs
src/tanks/map/pathmap.cjs
src/tanks/map/trajectory.cjs
src/tanks/map/traversal.cjs [new file with mode: 0644]
src/tanks/map/wall.cjs
src/tanks/thing/bullet.cjs
src/tanks/thing/index.cjs
src/tanks/thing/item.cjs [new file with mode: 0644]
src/tanks/thing/player.cjs
src/tanks/thing/tank.cjs
src/tanks/thing/thing.cjs
src/tanks/ui/configui.cjs
src/tanks/ui/grid.cjs
src/tanks/ui/index.cjs
src/tanks/ui/main.cjs
src/tanks/ui/pathmapui.cjs [new file with mode: 0644]
www/deps.html

index dd9f2b5..cddbcd4 100644 (file)
@@ -50,11 +50,12 @@ addNames('Class subclass instantiate fabricate YBase', require('Y/class'));
 
 
 /// Now start assembling the normal sub-modules ///
-addNames('YCollection',      require('Y/types/collection'));
-addNames('YArray',           require('Y/types/array'));
-addNames('YObject deepcopy', require('Y/types/object'));
-addNames('YString',          require('Y/types/string'));
-addNames('YNumber range',    require('Y/types/number'));
+addNames('YCollection',   require('Y/types/collection'));
+addNames('YArray',        require('Y/types/array'));
+addNames('YObject getNested setNested deepcopy',
+                          require('Y/types/object'));
+addNames('YString',       require('Y/types/string'));
+addNames('YNumber range', require('Y/types/number'));
 
 var utils = require('Y/utils');
 Y['bindAll'] = utils.bindAll;
index 91a694c..f812fde 100644 (file)
@@ -1,5 +1,5 @@
 var Y = require('Y').Y
-,   getNested = require('Y/types/object').getNested
+,   getNested = Y.getNested
 ,   Emitter   = require('Y/modules/y.event').Emitter
 ,
 
@@ -142,7 +142,7 @@ Y.YObject.subclass('Config', function(Config){
          */
         updateOnChange : function updateOnChange(events, obj){
             if ( !Y.isArray(events) )
-                events = events.split();
+                events = events.split(/\s+/);
             events = events.map(function events(key){
                 obj[key.split('.').pop()] = this.get(key);
                 if ( !Y(key).startsWith('set:') )
index 7421fb8..64859d9 100644 (file)
@@ -37,7 +37,7 @@ Y.YObject.subclass('Event', {
     addEventListener : function addEventListener(evts, fn){
         fn = fn.toFunction();
         if ( !Y.isArray(evts) )
-            evts = evts.split();
+            evts = evts.split(/\s+/);
         evts.forEach(function addEvent(evt){
             this.getQueue(evt).push(fn);
         }, this);
@@ -57,7 +57,11 @@ Y.YObject.subclass('Event', {
         return evt;
     },
     
-    // XXX: does not handle degenerate or recursive event dispatch
+    /**
+     * Dispatches the given event to all listeners in the appropriate queue.
+     * Listeners are invoked with the event, and with context set to the target.
+     * XXX: does not handle degenerate or recursive event dispatch
+     */
     dispatchEvent : function dispatchEvent(evt){
         this.getQueue(evt.type).invoke('call', evt.target, evt);
         if (this.parent) this.parent.fire(evt.type, evt.trigger, evt.data);
index 9a499df..717b7c9 100644 (file)
@@ -37,6 +37,14 @@ type2el = {
 ,
 
 
+// addTypeSupport =
+// exports['addTypeSupport'] =
+// function addTypeSupport(type, parser, builder){
+//     var T = Y.typeName(type);
+//     type2parser[T] = parser;
+// }
+// ,
+
 
 Field =
 exports['Field'] =
@@ -52,7 +60,7 @@ Y.subclass('Field', {
         this.key   = chain.split('.').pop();
         this.label = camelToSpaces(this.key);
         
-        var T = Y(Y.type(val)).getName();
+        var T = Y.typeName(def);
         this.cast = options.cast || type2parser[T];
         this.type = options.type || type2el[T];
         
@@ -133,8 +141,12 @@ function create(config, el){
         },
         function createField(group, value, chain){
             var def = config.getDefault(chain)
-            ,   field = new Field(chain, def, value);
+            ,   T = Y.typeName(def);
+            
+            if (!type2parser[T])
+                return group;
             
+            var field = new Field(chain, def, value);
             fields[chain] = field;
             group.append(field.el);
             config.addEventListener('set:'+chain, function onConfigSet(evt){
index 18c7cb8..bed850b 100644 (file)
@@ -28,46 +28,53 @@ var class2name =
     "Boolean Number String Function Array Date RegExp Object"
         .split(" ")
         .reduce(function(class2name, name) {
-            class2name[ "[object "+name+"]" ] = name.toLowerCase();
+            class2name[ "[object "+name+"]" ] = name;
             return class2name;
         }, {});
 
-function type_of(obj){
-    return obj == null ?
-        String( obj ) :
-        class2name[ toString.call(obj) ] || "object";
+function basicTypeName(o){
+    return o == null ?
+        String(o) :
+        class2name[ toString.call(o) ] || "Object";
+}
+
+function typeName(o){
+    if (o === undefined || o === null)
+        return String(o);
+    var T = type(o);
+    return  T.className || (T !== Function ? T.name : basicTypeName(o));
 }
 
 var arrayLike = isArray.types = [];
-function isArray(obj)    { return type_of(obj) === "array" || (arrayLike.indexOf(type(obj)) !== -1); }
-function isFunction(obj) { return type_of(obj) === "function"; }
-function isString(obj)   { return type_of(obj) === "string"; }
-function isNumber(obj)   { return type_of(obj) === "number"; }
-function isWindow(obj)   { return obj && typeof obj === "object" && "setInterval" in obj; }
+function isArray(o)    { return basicTypeName(o) === "Array" || (arrayLike.indexOf(type(o)) !== -1); }
+function isFunction(o) { return basicTypeName(o) === "Function"; }
+function isString(o)   { return basicTypeName(o) === "String"; }
+function isNumber(o)   { return basicTypeName(o) === "Number"; }
+function isWindow(o)   { return o && typeof o === "object" && "setInterval" in o; }
 
-function isPlainObject( obj ){
+function isPlainObject(o){
     // Must be an Object.
     // Because of IE, we also have to check the presence of the constructor property.
     // Make sure that DOM nodes and window objects don't pass through, as well
-    if ( !obj || type_of(obj) !== "object" || obj.nodeType || isWindow(obj) )
+    if ( !o || basicTypeName(o) !== "Object" || o.nodeType || isWindow(o) )
         return false;
     
     // Not own constructor property must be Object
-    if ( obj[FN] &&
-        !hasOwn.call(obj, FN) &&
-        !hasOwn.call(obj[FN][PT], "isPrototypeOf") )
+    if ( o[FN] &&
+        !hasOwn.call(o, FN) &&
+        !hasOwn.call(o[FN][PT], "isPrototypeOf") )
             return false;
     
     
     // Own properties are enumerated firstly, so to speed up,
     // if last one is own, then all properties are own.
     var key;
-    for ( key in obj ) {}
+    for ( key in o ) {}
     
-    return key === undefined || hasOwn.call( obj, key );
+    return key === undefined || hasOwn.call( o, key );
 }
 
-function type( o ) {
+function type(o) {
     if ( o === null || o === undefined )
         return o;
     
@@ -95,7 +102,7 @@ function type( o ) {
     }
 }
 
-function is( A, B ){
+function is(A, B){
     if ( isArray(B) )
         return B.some( is.bind(this,A) );
     else {
@@ -106,7 +113,8 @@ function is( A, B ){
 
 exports['is']            = is;
 exports['type']          = type;
-exports['type_of']       = type_of;
+exports['basicTypeName'] = basicTypeName;
+exports['typeName']      = typeName;
 
 exports['isArray']       = isArray;
 exports['isFunction']    = isFunction;
@@ -115,5 +123,5 @@ exports['isNumber']      = isNumber;
 exports['isWindow']      = isWindow;
 exports['isPlainObject'] = isPlainObject;
 
-type['KNOWN_CLASSES'] = KNOWN_CLASSES;
+type['KNOWN_CLASSES']    = KNOWN_CLASSES;
 
index b332334..e11e31b 100644 (file)
@@ -284,4 +284,4 @@ function getName( fn ){
 
 // Export these last to avoid methodizing them
 exports['YFunction']  = YF(YF);
-exports._ = _;
+exports['_'] = _;
index 57bb49d..5a22487 100644 (file)
@@ -71,8 +71,7 @@ function Y(o){
     }
     
     // Do we have a type-specific wrapper?
-    var name  = type.type_of(o)
-    ,   yname = 'Y' + name.charAt(0).toUpperCase() + name.slice(1)
+    var yname = 'Y' + type.basicTypeName(o)
     ,   YType = Y[yname]
     ;
     
index 7981385..61462cf 100644 (file)
@@ -39,12 +39,19 @@ var Y       = require('Y').Y
 
 ,   objToString   = _Object[P].toString
 ,   classToString = function toString(){ return this.className+"()"; }
-;
+,
+
 
-// Private delegating constructor -- must be defined for every
-// new class to prevent shared state. All construction is
-// actually done in the init method.
-exports['ConstructorTemplate'] = ConstructorTemplate;
+/**
+ * @private
+ * Private delegating constructor. This function must be redefined for every
+ * new class to prevent shared state. All construction is actually done in
+ * the methods initialise and init.
+ * 
+ * Fires `create` event prior to initialisation if not subclassing.
+ */
+ConstructorTemplate =
+exports['ConstructorTemplate'] =
 function ConstructorTemplate() {
     var cls = arguments.callee
     ,   instance = this;
@@ -64,7 +71,39 @@ function ConstructorTemplate() {
     
     return instance;
 }
+,
 
+/**
+ * Fires `init` event after calling init(). Note that events are fired
+ * for proper instances of the class and instances of subclasses (but
+ * not for the instance created when subclassing).
+ */
+createInitialise =
+exports['createInitialise'] =
+function createInitialise(NewClass){
+    function initialise(){
+        var instance = this
+        ,   init     = NewClass.prototype.init
+        ;
+        
+        instance.__emitter__ = new Emitter(instance, NewClass);
+        
+        if (init) {
+            var result = init.apply(instance, arguments);
+            if (result) instance = result;
+        }
+        
+        instance.fire('init', instance, {
+            'instance' : instance,
+            'cls'      : NewClass,
+            'args'     : Y(arguments)
+        });
+        
+        return instance;
+    }
+    return Y(initialise);
+}
+;
 
 
 
@@ -156,28 +195,7 @@ function Class(className, Parent, members){
     NewClass.__super__    = SuperClass; // don't override NewClass.constructor -- it should be Function
     prototype.constructor = prototype.__class__ = NewClass;
     
-    NewClass.init = // XXX: This means subclasses will fire events.
-    prototype.initialise =
-        Y(function initialise(){
-            var instance = this
-            ,   init     = NewClass.prototype.init
-            ;
-            
-            instance.__emitter__ = new Emitter(instance, NewClass);
-            
-            if (init) {
-                var result = init.apply(instance, arguments);
-                if (result) instance = result;
-            }
-            
-            instance.fire('init', instance, {
-                'instance' : instance,
-                'cls'      : NewClass,
-                'args'     : Y(arguments)
-            });
-            
-            return instance;
-        });
+    NewClass.init = prototype.initialise = createInitialise(NewClass);
     
     // Add class emitter
     var ParentEmitter = (Parent.__emitter__ ? Parent : ClassFactory)
index 6857efb..21f150f 100644 (file)
@@ -21,7 +21,6 @@ Y.subclass('Layer', {
     _cssClasses : 'ezl layer',
     
     canvas     : null,
-    
     parent     : null,
     children   : null,
     
@@ -43,10 +42,14 @@ Y.subclass('Layer', {
     // Transforms
     _origin : null, // rotational origin
     transform : null, // Object
-    useCanvasScaling : false, // default to CSS3 scaling
     
     /// Defaults ///
     
+    useCanvasScaling   : false, // Default to CSS3 scaling
+    alwaysClearDrawing : true,  // Whether to clear the canvas content before redraw
+    alwaysClearAttrs   : false, // Whether to remove all canvas attributes (CONTEXT_ATTRS)
+                                // and transforms (scale, rotate, translate) and reset defaults before redraw
+    
     originX : 0,
     originY : 0,
     
@@ -129,7 +132,7 @@ Y.subclass('Layer', {
      */
     empty : function empty(ctx){
         this.children.invoke('remove');
-        this.clear();
+        this.clear(ctx);
         return this;
     },
     
@@ -469,48 +472,55 @@ Y.subclass('Layer', {
      * @param {Boolean} [force=false] Forces redraw.
      */
     draw : function draw(ctx, force){
+        var _ctx = ctx || this.ctx;
+        
         if ( this.dirty || force ){
-            var _ctx = ctx || this.ctx;
+            this.dirty = false;
             this._openPath(_ctx);
-            this.drawShape(_ctx);
+            this.render(_ctx);
             this._closePath(_ctx);
         }
         
-        this.dirty = false;
         this.children.invoke('draw', ctx, force);
         return this;
     },
     
     _openPath : function _openPath(ctx){
         var self = this
-        ,   alwaysClear = this.alwaysClear
         ,   neg = this.negBleed
         ,   t = this.transform
         ,   w = this.canvasWidth, h = this.canvasHeight ;
         
         ctx.beginPath();
-        ctx.setTransform(1,0,0,1,0,0);
-        ctx.clearRect(-w,-h, 2*w,2*h);
         
+        // TODO: only alwaysClearAttrs should reset transforms?
+        // if (this.alwaysClearAttrs)
+            ctx.setTransform(1,0,0,1,0,0);
+        
+        if (this.alwaysClearDrawing)
+            ctx.clearRect(-w,-h, 2*w,2*h);
+        
+        // if (this.alwaysClearAttrs) {
         if (this.useCanvasScaling && (t.scale.x !== 1 || t.scale.y !== 1))
             ctx.scale(t.scale.x,t.scale.y);
         
         ctx.translate(neg.x, neg.y);
         ctx.translate(t.translate.x, t.translate.y);
+        // }
         
         // Set context attributes
         CONTEXT_ATTRS.forEach(function(name){
-            if (self[name] !== undefined)
-                ctx[name] = self[name];
-            else if (alwaysClear)
+            if (this[name] !== undefined)
+                ctx[name] = this[name];
+            else if (this.alwaysClearAttrs)
                 delete ctx[name];
-        });
+        }, this);
         
         return this;
     },
     
     /** To be implemented by subclasses. */
-    drawShape : function drawShape(ctx){ return this; },
+    render : function render(ctx){ return this; },
     
     _closePath : function _closePath(ctx){
         ctx.closePath();
@@ -518,9 +528,9 @@ Y.subclass('Layer', {
     },
     
     /**
-     * Clears this layer and all children.
+     * Clears this layer and optionally all children.
      */
-    clear : function clear(ctx){
+    clear : function clear(ctx, clearChildren){
         var w = this.canvas.width()
         ,   h = this.canvas.height();
         ctx = ctx || this.ctx;
@@ -528,7 +538,8 @@ Y.subclass('Layer', {
         ctx.setTransform(1,0,0,1,0,0);
         ctx.clearRect(-w,-h, 2*w,2*h);
         ctx.closePath();
-        this.children.invoke('clear');
+        if (clearChildren)
+            this.children.invoke('clear');
         return this;
     },
     
index 5de767d..973757f 100644 (file)
@@ -41,6 +41,7 @@ Rect.subclass('BoundingBox', {
     get origin(){ return this._origin; },
     
     relocate : function relocate(x,y){
+        if (x instanceof Array) { y=x[1]; x=x[0]; }
         var _x1 = this[X1], _y1 = this[Y1]
         ,   _x2 = this[X2], _y2 = this[Y2]
         
@@ -55,11 +56,11 @@ Rect.subclass('BoundingBox', {
     },
     
     relocated : function relocated(x,y){
-        var bb = this.clone();
-        return bb.relocate(x,y);
+        return this.clone().relocate(x,y);
     },
     
     resize : function resize(w,h){
+        if (w instanceof Array) { h=w[1]; w=w[0]; }
         var x1 = this[X1], y1 = this[Y1]
         ,   x2 = this[X2], y2 = this[Y2]
         ,   wOld = x2-x1, hOld = y2-y1
@@ -87,13 +88,28 @@ Rect.subclass('BoundingBox', {
     },
     
     resized : function resized(w,h){
-        var bb = this.clone();
-        return bb.resize(w,h);
+        return this.clone().resize(w,h);
     },
     
     clone : function clone(){
         var o = this._origin;
         return new BoundingBox(this[X1],this[Y1], this[X2],this[Y2], o[X1], o[Y1]);
+    },
+    
+    
+    get topSide(){    return new Line(this[X1],this[Y1], this[X2],this[Y1]); },
+    get bottomSide(){ return new Line(this[X1],this[Y2], this[X2],this[Y2]); },
+    get leftSide(){   return new Line(this[X1],this[Y1], this[X1],this[Y2]); },
+    get rightSide(){  return new Line(this[X2],this[Y1], this[X2],this[Y2]); },
+    
+    side : function side(which){
+        switch (which) {
+            case 'top'    : return this.topSide;
+            case 'bottom' : return this.bottomSide;
+            case 'left'   : return this.leftSide;
+            case 'right'  : return this.rightSide;
+            default : throw new Error('Unknown side: '+which);
+        }
     }
     
 });
index d744531..c93e2e5 100644 (file)
@@ -11,8 +11,8 @@ var Y = require('Y').Y
 EventLoop =
 exports['EventLoop'] =
 Emitter.subclass('EventLoop', {
-    samples   : NUM_SAMPLES, // Number of frames to track for effective fps
-    dilation  : 1.0,
+    samples      : NUM_SAMPLES, // Number of frames to track for effective fps
+    timeDilation : 1.0,
     
     framerate : 0, // Target framerate
     frametime : 0, // 1000 / framerate
@@ -46,7 +46,7 @@ Emitter.subclass('EventLoop', {
         if (samples !== undefined)
             this.samples = samples;
         if (dilation !== undefined)
-            this.dilation = dilation;
+            this.timeDilation = dilation;
         
         this.reset();
     },
@@ -140,3 +140,4 @@ function decorate(delegate){
     return delegate;
 }
 
+
index bdf54ee..1daa9c8 100644 (file)
@@ -54,14 +54,34 @@ Vec.subclass('Line', {
         return this;
     },
     
+    /**
+     * @return {Vec} Delta-(x,y) on this line after given elapsed parametric time.
+     */
+    wouldMove : function wouldMove(t){
+        return new Vec( t*this.pa, t*this.pb );
+    },
+    
+    /**
+     * @return {Float} Elapsed parametric time needed to move the given delta-(x,y).
+     */
+    timeToMove : function timeToMove(dx,dy){
+        // see note at iparametric
+        return (dx/this.pa + dy/this.pb) * 0.5;
+    },
+    
     parametric : function parametric(t){
+        // return this.wouldMove(t).add(this.p1);
         return new Vec( this.x1 + t*this.pa ,
                         this.y1 + t*this.pb );
     },
     
     iparametric : function iparametric(x,y){
-        return new Vec( (x-this.x1)/this.pa ,
-                        (y-this.y1)/this.pa );
+        var tx = (x - this.x1)/this.pa
+        ,   ty = (y - this.y1)/this.pb;
+        // tx and ty should be the same number provided (x,y) is on the line
+        // we average to provide a reasonable answer when that's not true,
+        // rather than failing outright or requiring the user to deal with a Vec.
+        return (tx + ty) * 0.5;
     },
     
     pointAtX : function pointAtX(x){ return new Vec(x, this.calcY(x)); },
index e02eab7..733148a 100644 (file)
@@ -25,7 +25,7 @@ Shape.subclass('Circle', {
         return this;
     },
     
-    drawShape : function drawShape(ctx){
+    render : function render(ctx){
         var r = this._radius;
         ctx.arc(r,r, r, 0, Math.PI*2, false);
         ctx.fill();
index 34bc660..e007377 100644 (file)
@@ -80,7 +80,7 @@ Shape.subclass('Line', {
         return this;
     },
     
-    drawShape : function drawShape(ctx){
+    render : function render(ctx){
         this._fixSize();
         var x1,y1, x2,y2
         ,   line = this.line, p1 = line.p1, p2 = line.p2
@@ -112,7 +112,7 @@ Shape.subclass('Line', {
             ctx.closePath();
         // } catch(e) {
         //     if (window.console) {
-        //         console.error(this+'.drawShape()');
+        //         console.error(this+'.render()');
         //         console.log('  points:', x1,y1, ' ', x2,y2);
         //         console.log('  bounds:', minW,minH, ' ', maxW,maxH);
         //         console.log('  ::', this, line);
index b0308b8..8601c16 100644 (file)
@@ -43,7 +43,7 @@ Shape.subclass('Polygon', {
         return values.map(function(v, i){ return (self[which+i] = v); });
     },
     
-    drawShape : function drawShape(ctx){
+    render : function render(ctx){
         this.points.forEach(function(loc, i){
             ctx.lineTo(loc.x, loc.y);
         });
index 845688d..d88a45c 100644 (file)
@@ -13,9 +13,10 @@ Shape.subclass('Rect', {
         this.size(w,h);
     },
     
-    drawShape : function drawShape(ctx){
+    render : function render(ctx){
         ctx.rect(0,0, this.canvasWidth,this.canvasHeight);
         ctx.fill();
+        ctx.stroke();
     },
     
     toString : function(){
diff --git a/src/ezl/util/configuration.cjs b/src/ezl/util/configuration.cjs
deleted file mode 100644 (file)
index 539bd0a..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-var Y = require('Y').Y
-,   getNested = require('Y/types/object').getNested
-,   Emitter = require('Y/modules/y.event').Emitter
-,
-
-
-Config =
-exports['Config'] =
-Y.YObject.subclass('Config', function(Config){
-    
-    Y.core.extend(this, {
-        
-        init : function initConfig(defaults){
-            this._defaults = defaults || {};
-            this._o = Y({}, this._defaults);
-            this.__emitter__ = new Emitter(this);
-        },
-        
-        clone : function clone(){
-            var c = new Config();
-            c._defaults = this._defaults;
-            c._o = c._o.clone();
-            return c;
-        },
-        
-        set : function set(key, value, def){
-            if ( key !== undefined ){
-                var meta = this.ensure(key).getNested(key, def, true)
-                ,   old = meta.value ;
-                def   = (def   === undefined ? old : def);
-                value = (value === undefined ? def : value);
-                
-                meta.obj[meta.key] = value;
-                this._fireMutation('set', key, old, value, meta.obj);
-            }
-            return this;
-        },
-        
-        remove : function remove(key){
-            if ( key !== undefined ){
-                var sentinel = {}
-                ,   meta = this.getNested(key, sentinel, true)
-                ,   old = (meta.value === sentinel ? undefined : old);
-                
-                if ( meta.obj ) {
-                    delete meta.obj[meta.key];
-                    this._fireMutation('remove', key, old, undefined, meta.obj);
-                }
-            }
-            return this;
-        },
-        
-        /**
-         * @private
-         */
-        _fireMutation : function _fireMutation(evt, key, oldval, newval, obj){
-            if (newval !== oldval){
-                var data = {
-                    'key'    : key,
-                    'oldval' : oldval,
-                    'newval' : newval,
-                    'obj'    : obj,
-                    'root'   : this
-                };
-                this.fire(evt+':'+key, this, data);
-                this.fire(evt, this, data);
-            }
-            return this;
-        },
-        
-        /**
-         * Recursively iterates the hierarchy of the Config, depth-first.
-         */
-        reduce : function reduce(fn, acc, context){
-            context = context || this;
-            
-            var ret = Y.reduce(this._o, this._reducer, {
-                'acc'  : acc,
-                'path' : new Y.YArray(),
-                'cxt'  : context
-            }, this);
-            
-            return ret.acc;
-        },
-        
-        /**
-         * @private
-         * XXX: Not going to call the iterator on root objects. ok?
-         * XXX: Always passing the Config object as obj to iterator. ok?
-         */
-        _reducer : function _reducer(state, v, k, o){
-            var chain = state.path.push(k).join('.');
-            
-            // Nested object -- recurse
-            if ( Y.isPlainObject(v) )
-                state = Y.reduce(v, this._reducer, state, this);
-                
-            // Normal value -- invoke iterator
-            else
-                state.acc = fn.call(state.cxt, state.acc, v, chain, this);
-            
-            state.path.pop();
-            return state;
-        },
-        
-        getDefault : function getDefault(k, def){
-            return getNested(this._defaults, k, def);
-        }
-        
-    });
-    
-    this['get'] = this.getNested;
-    
-});
index dba3caa..c7f492a 100644 (file)
@@ -36,8 +36,8 @@ Layer.subclass('CooldownGauge', function setupCooldownGauge(CooldownGauge){
         return Layer.fn.draw.apply(this, arguments);
     };
     
-    this['drawShape'] =
-    function drawShape(ctx){
+    this['render'] =
+    function render(ctx){
         var cool = this.cooldown;
         
         if (cool.ready)
diff --git a/src/tanks/abilities/buff.cjs b/src/tanks/abilities/buff.cjs
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/tanks/abilities/index.cjs b/src/tanks/abilities/index.cjs
new file mode 100644 (file)
index 0000000..e69de29
index 03a5308..06ec09f 100644 (file)
@@ -1,6 +1,7 @@
 //  -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
-var Y = require('Y').Y
+var Y      = require('Y').Y
 ,   Config = require('Y/modules/y.config').Config
+,   Vec    = require('ezl/math').Vec
 ,
 
 defaults =
@@ -16,11 +17,22 @@ exports['defaults'] = {
         showAttackCooldown : false,
         showCountdown      : (document.location.host.toString() !== 'tanks.woo')
     },
-    pathing : { 
-        overlayAiPaths     : false,
-        overlayPathmap     : false,
-        traceTrajectories  : false
+    pathing : {
+        gridSquare        : REF_SIZE,
+        gridSquareMid     : new Vec(REF_SIZE/2, REF_SIZE/2),
+        overlayAiPaths    : false,
+        overlayPathmap    : false,
+        traceTrajectories : false
     }
-};
+}
+,
+
+config =
+exports['config'] = new Config(defaults)
+;
+
+config.addEventListener('set:pathing.gridSquare', function(evt){
+    var sq = evt.data.newval;
+    config.set('pathing.gridSquareMid', new Vec(sq/2, sq/2));
+});
 
-exports['values'] = new Config(defaults);
index 135f487..3c5ac9f 100644 (file)
@@ -6,10 +6,11 @@ var Y         = require('Y').Y
 ,   EventLoop = require('ezl/loop').EventLoop
 ,   Circle    = require('ezl/shape').Circle
 
-,   config = require('tanks/config').values
-,   map    = require('tanks/map')
-,   thing  = require('tanks/thing')
-,   Grid   = require('tanks/ui/grid').Grid
+,   config    = require('tanks/config').config
+,   map       = require('tanks/map')
+,   thing     = require('tanks/thing')
+,   Grid      = require('tanks/ui/grid').Grid
+,   PathMapUI = require('tanks/ui/pathmapui').PathMapUI
 
 ,   Level  = map.Level
 ,   Thing  = thing.Thing, Tank = thing.Tank, Bullet = thing.Bullet
@@ -19,11 +20,12 @@ var Y         = require('Y').Y
 Game =
 exports['Game'] = 
 Y.subclass('Game', {
-    overlayPathmap : null,
-    overlayAiPaths : null,
-    gameoverDelay  : null,
+    // Config
+    gameoverDelay : null,
+    
+    // Defaults
+    gameover : false,
     
-    gameover      :