AH HA BOUNCING
authordsc <david.schoonover@gmail.com>
Wed, 10 Nov 2010 14:07:24 +0000 (06:07 -0800)
committerdsc <david.schoonover@gmail.com>
Wed, 10 Nov 2010 14:07:24 +0000 (06:07 -0800)
14 files changed:
src/portal/layer.js
src/portal/loop/eventloop.js
src/portal/loop/fps.js
src/portal/math/line.js
src/portal/math/vec.js
src/portal/shape/line.js
src/portal/shape/rect.js
src/tanks/game/game-map.js
src/tanks/main.js
src/tanks/map/level.js
src/tanks/map/loc.js
src/tanks/map/pathmap.js
src/tanks/thing/bullet.js
src/tanks/thing/tank.js

index 6772ea6..a3e2523 100644 (file)
@@ -157,9 +157,11 @@ Layer = new Y.Class('Layer', {
         if (w === undefined)
             return this.layerWidth;
         
+        this.layerWidth = w;
+        this.boundingBox = this.boundingBox.resize(w, this.layerHeight);
+        
         var nb = this.negBleed.x
         ,   v  = this.canvasWidth = w + nb + this.posBleed.x;
-        this.layerWidth = w;
         this.layer.width(w).css('margin-left', (-nb)+'px')
         this.canvas.width(v);
         // this.canvas.css({
@@ -168,6 +170,7 @@ Layer = new Y.Class('Layer', {
         // });
         this.canvas[0].width = v;
         
+        
         return this;
     },
     
@@ -175,9 +178,11 @@ Layer = new Y.Class('Layer', {
         if (h === undefined)
             return this.layerHeight;
         
+        this.layerHeight = h;
+        this.boundingBox = this.boundingBox.resize(this.layerWidth, h);
+        
         var nb = this.negBleed.y
         ,   v  = this.canvasHeight = h + nb + this.posBleed.y;
-        this.layerHeight = h;
         this.layer.height(h).css('margin-top', (-nb)+'px')
         this.canvas.height(v);
         // this.canvas.css({
@@ -216,6 +221,8 @@ Layer = new Y.Class('Layer', {
         // if (pos.left !== undefined)  pos.left -= this.offsetX;
         // if (pos.top  !== undefined)  pos.top  -= this.offsetY;
         
+        this.boundingBox = this.boundingBox.moveTo(pos.left,pos.top);
+        this.loc = this.boundingBox.p1;
         this.css(pos);
         return this;
     },
@@ -264,7 +271,6 @@ Layer = new Y.Class('Layer', {
         
         o.x = x;
         o.y = y;
-        // this.dirty = true;
         return this._applyTransforms();
     },
     
@@ -289,7 +295,6 @@ Layer = new Y.Class('Layer', {
         if (arguments.length === 0)
             return o.absolute(this.layerWidth, this.layerHeight);
         
-        // Record my relative scaling...
         o.x = sx;
         o.y = sy;
         this.dirty = true;
@@ -305,18 +310,12 @@ Layer = new Y.Class('Layer', {
         if (arguments.length === 0)
             return o.absolute(this.layerWidth, this.layerHeight);
         
-        // Record my relative scaling...
         o.x = x;
         o.y = y;
         this.dirty = true;
         return this;
     },
     
-    
-    // origin    : new Loc('50%','50%'),
-    // rotate    : 0,
-    // scale     : new Loc(1.0,1.0),
-    // translate : new Loc(0,0)
     _applyTransforms : function _applyTransforms(){
         var t = this.transform, tfns = [];
         
index 466e822..84b8325 100644 (file)
@@ -82,6 +82,8 @@ methods = {
     },
     
     tick : function tick(){
+        if (!this.running) return;
+        
         var lastTick = this.now;
         this.now     = new Date().getTime();
         this.elapsed = this.now - lastTick;
index 5dc506a..663afc8 100644 (file)
@@ -35,6 +35,8 @@ FpsSparkline = new Y.Class('FpsSparkline', {
     },
     
     tickTime : function tickTime(){
+        if (!this.loop.running) return;
+        
         var loop = this.loop
         ,   buf  = this.buffer
         ;
index 280fb79..e213436 100644 (file)
@@ -54,6 +54,15 @@ math.Line = new Y.Class('Line', math.Vec, {
         return this.calcY(x) === y;
     },
     
+    isWithin : function isWithin(pt, w,h){
+        if ( !Y.isNumber(w) ){
+            h = w.height; w = w.width;
+        }
+        var dw = Math.abs(this.calcX(pt.y) - pt.x)
+        ,   dh = Math.abs(this.calcY(pt.x) - pt.y) ;
+        return dw <= w || dh <= h ;
+    },
+    
     setTScale : function setTScale(tdist){
         if (tdist) {
             this.tdist = tdist;
@@ -67,25 +76,32 @@ math.Line = new Y.Class('Line', math.Vec, {
         return this;
     },
     
-    pcalc : function parametric(t){
+    parametric : function parametric(t){
         return new math.Vec( this.x1 + t*this.pa ,
                              this.y1 + t*this.pb );
     },
     
-    pointX : function pointX(x){
+    pointAtX : function pointAtX(x){
         return new math.Vec(x, this.calcY(x));
     },
     
-    pointY : function pointY(y){
+    pointAtY : function pointAtY(y){
         return new math.Vec(this.calcX(y), y);
     },
     
+    near : function near(x,y){
+        if ( !isFinite(this.slope) )
+            return this.pointAtY(y);
+        else
+            return this.pointAtX(x);
+    },
+    
     calcY : function calcY(x){
-        return x*this.slope + this.yint;
+        return (x === this.xint ? 0 : x*this.slope + this.yint);
     },
     
     calcX : function calcX(y){
-        return y/this.slope + this.xint;
+        return (y === this.yint ? 0 : y/this.slope + this.xint);
     },
     
     base : function base(){
@@ -110,7 +126,7 @@ math.Line = new Y.Class('Line', math.Vec, {
     },
     
     toString : function toString(){
-        return 'Line( '+this.p1+', '+this.p2+', slope='+this.slope.toFixed(3)+')';
+        return '['+this.p1+', '+this.p2+', slope='+this.slope.toFixed(3)+']';
     }
     
 });
index 76421f6..dbab10f 100644 (file)
@@ -59,7 +59,10 @@ math.Vec = new Y.Class('Vec', [], {
     },
     
     toString : function toString(){
-        return '('+this.x.toFixed(3)+', '+this.y.toFixed(3)+')';
+        var p = 2, x = this.x, y = this.y;
+        x = ((x % 1 !== 0) ? x.toFixed(p) : x);
+        y = ((y % 1 !== 0) ? y.toFixed(p) : y);
+        return '('+x+', '+y+')';
     }
     
 });
index fe9ddcd..9783d1b 100644 (file)
@@ -96,19 +96,19 @@ Line = new Y.Class('Line', Shape, {
             y2 = -y2;
         }
         
-        try {
+        // try {
             ctx.moveTo(x1,y1);
             ctx.lineTo(x2,y2);
             ctx.stroke();
             ctx.closePath();
-        } catch(e) {
-            if (window.console) {
-                console.error(this+'.drawShape()');
-                console.log('  points:', x1,y1, ' ', x2,y2);
-                console.log('  bounds:', minW,minH, ' ', maxW,maxH);
-                console.log('  ::', this, line);
-            }
-        }
+        // } catch(e) {
+        //     if (window.console) {
+        //         console.error(this+'.drawShape()');
+        //         console.log('  points:', x1,y1, ' ', x2,y2);
+        //         console.log('  bounds:', minW,minH, ' ', maxW,maxH);
+        //         console.log('  ::', this, line);
+        //     }
+        // }
         
         // Show definition points
         if ( this.drawDefinitionPoints ) {
index ef21d2d..4bd8c76 100644 (file)
@@ -2,7 +2,7 @@
 Rect = new Y.Class('Rect', Shape, {
     _cssClasses : 'portal layer shape rect',
     
-    init : function initRect(w, h){
+    init : function initRect(w,h){
         Layer.init.call(this);
         
         this.width(w)
index a6dc4f7..89a8884 100644 (file)
@@ -2,24 +2,24 @@
 Y(Game.prototype).extend({
     
     initMap : function initMap(){
-        // var self = this;
+        var self = this;
         
         this.byId = {};
         this.units    = new Y.YArray();
         this.bullets  = new Y.YArray();
         this.blockers = new Y.YArray();
         
-        this.pathmap = new PathMap(0,0, COLUMNS*REF_SIZE, ROWS*REF_SIZE, CAPACITY);
-        
-        var root = 
         this.root = 
         this.grid = 
             new Grid(COLUMNS,ROWS, CELL_SIZE)
                 .appendTo(this.viewport);
+        
         this.level =
-            new Level(this, root.layerWidth, root.layerHeight )
+            new Level(this, COLUMNS*REF_SIZE, ROWS*REF_SIZE)
                 .appendTo(this.root);
         
+        this.pathmap = this.level.pathmap;
+        
         // Agent.addEventListener('create', function(evt){
         //     self.addAgent(evt.instance);
         // });
@@ -29,27 +29,6 @@ Y(Game.prototype).extend({
     },
     
     
-    // *** Path Map Management *** //
-    
-    addBlocker : function addBlocker(agent){
-        var bb = agent.boundingBox;
-        if (agent.blocking && bb)
-            agent.region = this.pathmap.set(bb.x1,bb.y1, bb.x2,bb.y2, agent);
-        return agent;
-    },
-    
-    removeBlocker : function removeBlocker(agent){
-        if (agent.region)
-            this.pathmap.remove(agent.region);
-        return agent;
-    },
-    
-    updateBlocker : function updateBlocker(agent){
-        this.removeBlocker(agent);
-        this.addBlocker(agent);
-    },
-    
-    
     // *** Agent Management *** //
     
     addUnit : function addUnit(unit, col,row){
@@ -66,7 +45,7 @@ Y(Game.prototype).extend({
             unit.render( this.level );
         }
         
-        this.addBlocker(unit);
+        this.pathmap.addBlocker(unit);
         
         if ( !this.byId[unit.id] ) {
             this.byId[unit.id] = unit;
@@ -80,7 +59,7 @@ Y(Game.prototype).extend({
         agent.game = this;
         if (agent.id === undefined) return agent;
         
-        this.addBlocker(agent);
+        this.pathmap.addBlocker(agent);
         
         if ( !this.byId[agent.id] ) {
             this.byId[agent.id] = agent;
@@ -100,14 +79,14 @@ Y(Game.prototype).extend({
         else
             this.units.remove(agent);
         
-        this.removeBlocker(agent);
+        this.pathmap.removeBlocker(agent);
         return agent;
     },
     
     moveAgentTo : function moveAgentTo(agent, x,y){
-        this.removeBlocker(agent);
+        this.pathmap.removeBlocker(agent);
         agent.setLocation(x,y);
-        this.addBlocker(agent);
+        this.pathmap.addBlocker(agent);
         return agent;
     },
     
index e992043..e141c2a 100644 (file)
@@ -3,36 +3,30 @@ jQuery(main);
 function main(){
     v = $('#viewport');
     LBT = new Game();
-
+    ctx = LBT.level.ctx;
     
-    var sq = REF_SIZE
-    ,   wall = new Wall(6*sq,1*sq, 1*sq,4*sq);
-    LBT.level.append(wall);
     
+    var sq = REF_SIZE;
+    LBT.level.append(
+        new Wall(6*sq,1*sq, 1*sq,4*sq),
+        new Wall(6*sq,7*sq, 1*sq,2*sq),
+        new Wall(1*sq,7*sq, 2*sq,2*sq),
+        new Wall(3*sq,6*sq, 1*sq,1*sq)
+    );
     
     T = new Tank(0);
     LBT.addUnit(T, 1,2);
-    T.shape.hide();
     
-    B = new Bullet(T, 5*REF_SIZE,5*REF_SIZE);
-    LBT.addUnit(B);
-    B.render( LBT.level );
+    T.fireProjectile(5*sq,5*sq);
+    T.fireProjectile(1*sq,3*sq);
+    T.fireProjectile(6*sq,1.5*sq);
+    T.fireProjectile(0.5*sq,0.5*sq);
     
-    B = new Bullet(T, 25,25);
-    LBT.addUnit(B);
-    B.render( LBT.level );
-    
-    B = new Bullet(T, 1*REF_SIZE,3*REF_SIZE);
-    LBT.addUnit(B);
-    B.render( LBT.level );
+    T.shape.hide();
+    LBT.pathmap.removeBlocker(T);
     
     P = new Player(LBT, T);
     
-    
-    ctx = LBT.level.ctx;
-    tr = B.trajectory;
-    
-    
     setupUI();
 }
 
index 0105e5c..608102e 100644 (file)
@@ -1,3 +1,20 @@
+Level = new Y.Class('Level', Rect, {
+    
+    init : function init(game, w,h){
+        Rect.init.call(this, w,h);
+        this.game = game;
+        this.pathmap = new PathMap(this, 0,0, w, h, CAPACITY);
+    },
+    
+    append : function append(children){
+        Y(arguments).forEach(this.pathmap.addBlocker, this.pathmap);
+        return Rect.prototype.append.apply(this, arguments);
+    },
+    
+    drawShape : Y.op.nop
+    
+});
+
 Wall = new Y.Class('Wall', Rect, {
     fillStyle : 'rgba(255,255,255, 0.25)',
     blocking : true,
@@ -7,29 +24,18 @@ Wall = new Y.Class('Wall', Rect, {
         
         var x1 = x,   y1 = y
         ,   x2 = x+w, y2 = y+h;
-        this.boundingBox = new Loc.Rect(x1,y1, x2,y2);
         this.position(x,y);
-    }
-    
-});
-
-Level = new Y.Class('Level', Rect, {
-    
-    init : function init(game, w,h){
-        this.game = game;
-        this.pathmap = game.pathmap;
-        Rect.init.call(this, w,h);
     },
     
-    append : function append(children){
-        Y(arguments).forEach(function(child){
-            var bb = child.boundingBox;
-            if (child.blocking && bb)
-                child.region = this.pathmap.set(bb.x1,bb.y1, bb.x2,bb.y2, child);
-        }, this);
-        return Layer.prototype.append.apply(this, arguments);
+    appendTo : function appendTo(parent){
+        if (parent instanceof Level)
+            parent.pathmap.addBlocker(this);
+        return Rect.prototype.appendTo.call(this, parent);
     },
     
-    drawShape : Y.op.nop
+    toString : function(){
+        return this.className+'('+this.loc+', w='+this.layerWidth+', h='+this.layerHeight+')';
+    }
     
-});
\ No newline at end of file
+});
+
index f90f3cf..5ac58e3 100644 (file)
@@ -111,6 +111,9 @@ Loc.Rect = new Y.Class('Rect', [], {
         this.width  = x2 - x1;
         this.height = y2 - y1;
         
+        this.p1 = new Loc(x1,y1);
+        this.p2 = new Loc(x2,y2);
+        
         this.sides = {
             top    : new math.Line(x1,y1, x2,y1),
             bottom : new math.Line(x1,y2, x2,y2),
@@ -130,6 +133,29 @@ Loc.Rect = new Y.Class('Rect', [], {
             
             default: this[k] = v;
         }
+        
+        this.width  = this.x2 - this.x1;
+        this.height = this.y2 - this.y1;
+        
+        return this._updateSides();
+    },
+    
+    _updateSides : function _updateSides(){
+        var s = this.sides
+        ,   x1 = this.x1,           y1 = this.y1
+        ,   x2 = this.x2,           y2 = this.y2
+        ,   dx1 = x1 !== s.top.x1,  dy1 = y1 !== s.top.y1
+        ,   dx2 = x2 !== s.top.x2,  dy2 = y2 !== s.left.y2
+        ;
+        
+        if ( dx1 || dy1 ) this.p1 = new Loc(x1,y1);
+        if ( dx2 || dy2 ) this.p2 = new Loc(x2,y2);
+        
+        if ( dx1 || dy1 || dx2 ) s.top    = new math.Line(x1,y1, x2,y1);
+        if ( dx1 || dx2 || dy2 ) s.bottom = new math.Line(x1,y2, x2,y2);
+        if ( dx1 || dy1 || dy2 ) s.left   = new math.Line(x1,y1, x1,y2);
+        if ( dy1 || dy2 || dx2 ) s.right  = new math.Line(x2,y1, x2,y2);
+        
         return this;
     },
     
@@ -139,6 +165,11 @@ Loc.Rect = new Y.Class('Rect', [], {
         return new Loc.Rect(x,y, x+this.width,y+this.height);
     },
     
+    resize : function resize(w,h){
+        var x = this.x, y = this.y;
+        return new Loc.Rect(x,y, x+w,y+h);
+    },
+    
     midpoint : function midpoint(){
         return new Loc( this.x1 + this.width /2
                       , this.y1 + this.height/2 );
index 5f5f8df..c7b0008 100644 (file)
@@ -2,66 +2,104 @@ PathMap = new Y.Class('PathMap', QuadTree, {
     
     init : function init(game, x1,y1, x2,y2, capacity) {
         QuadTree.init.call(this, x1,y1, x2,y2, capacity);
+        this.game = game;
         
         var w = this.width, h = this.height;
-        this.game = game;
         this.walls = {
-            top    : new math.Line(0,0, w,0),
-            bottom : new math.Line(0,h, w,h),
-            left   : new math.Line(0,0, 0,h),
-            right  : new math.Line(w,0, w,h)
+            top    : new Wall(0,0, w,1),
+            bottom : new Wall(0,h, w,1),
+            left   : new Wall(0,0, 1,h),
+            right  : new Wall(w,0, 1,h)
         };
         
+        Y(this.walls).forEach(this.addBlocker, this);
+    },
+    
+    addBlocker : function addBlocker(obj){
+        var bb = obj.boundingBox;
+        if (obj.blocking && bb)
+            obj.region = this.set(bb.x1,bb.y1, bb.x2,bb.y2, obj);
+        return obj;
+    },
+    
+    removeBlocker : function removeBlocker(obj){
+        if (obj.region) {
+            this.remove(obj.region);
+            delete obj.region;
+        }
+        return obj;
+    },
+    
+    updateBlocker : function updateBlocker(obj){
+        this.removeBlocker(obj);
+        this.addBlocker(obj);
+        return obj;
     },
     
     
     attemptMove : function attemptMove(obj, trj, to){
-        var line, bb = obj.boundingBox
+        var wall, blocker, what, bb = obj.boundingBox
+        ,   maxW = this.width,  maxH = this.height
         ,   w  = bb.width,      h  = bb.height
         ,   x1 = to.x,          y1 = to.y
         ,   x2 = x1+w,          y2 = y1+h
-        ,   maxW = this.width,  maxH = this.height
         ;
         
         // Check for collision with the walls
-        if (x1 <= 0 || x2 >= maxW || y1 <= 0 || y2 >= maxH){
-            if (x1 <= 0) {
-                line = this.walls.left;
-                to = trj.pointX(w/2);
-            
-            } else if (x2 >= maxW) {
-                line = this.walls.right;
-                to = trj.pointX(maxW-w/2);
-            
-            } else if (y1 <= 0) {
-                line = this.walls.top;
-                to = trj.pointY(h/2);
-            
-            } else if (y2 >= maxH) {
-                line = this.walls.bottom;
-                to = trj.pointY(maxH-h/2);
-            }
-        }
+        // if (x1 < 0 || x2 > maxW || y1 < 0 || y2 > maxH){
+        //     blocker = this.game.level;
+        //     what = 'LevelWall on the ';
+        //     
+        //     if (x1 < 0) {
+        //         what = 'left';
+        //         wall = this.walls.left;
+        //         to = trj.pointAtX(0);
+        //     
+        //     } else if (x2 > maxW) {
+        //         what = 'right';
+        //         wall = this.walls.right;
+        //         to = trj.pointAtX(maxW-w);
+        //     
+        //     } else if (y1 < 0) {
+        //         what = 'top';
+        //         wall = this.walls.top;
+        //         to = trj.pointAtY(0);
+        //     
+        //     } else if (y2 > maxH) {
+        //         what = 'bottom';
+        //         wall = this.walls.bottom;
+        //         to = trj.pointAtY(maxH-h);
+        //     }
+        //     
+        // }
         
-        var blocker = this.get(x1,y1, x2,y2).remove(obj).shift();
+        // Check for pathmap collisions
+        blocker = this.get(x1,y1, x2,y2).remove(obj).shift();
         if ( blocker ) {
+            what = blocker+' on the ';
+            
             var B = blocker.boundingBox;
-            if (bb.x2 < B.x1 && x2 >= B.x1) {
-                line = B.sides.left;
-                to = trj.pointX(B.x1-w/2);
-            } else if (bb.x1 > B.x2 && x1 <= B.x2) {
-                line = B.sides.right;
-                to = trj.pointX(B.x2+w/2);
-            } else if (bb.y2 < B.y1 && y2 >= B.y1) {
-                line = B.sides.top;
-                to = trj.pointX(B.y1-h/2);
-            } else if (bb.y1 > B.y2 && y1 <= B.y2) {
-                line = B.sides.bottom;
-                to = trj.pointX(B.y2+h/2);
+            if (bb.x2 <= B.x1 && x2 > B.x1) {
+                what += 'left';
+                wall = B.sides.left;
+                to   = trj.pointAtX(B.x1-w);
+            } else if (bb.x1 >= B.x2 && x1 < B.x2) {
+                what += 'right';
+                wall = B.sides.right;
+                to   = trj.pointAtX(B.x2);
+            } else if (bb.y2 <= B.y1 && y2 > B.y1) {
+                what += 'top';
+                wall = B.sides.top;
+                to   = trj.pointAtY(B.y1-h);
+            } else if (bb.y1 >= B.y2 && y1 < B.y2) {
+                what += 'bottom';
+                wall = B.sides.bottom;
+                to   = trj.pointAtY(B.y2);
             }
         }
         
-        return { 'ok':!line, 'to':to, 'line':line };
+        what += ' at '+wall;
+        return { 'ok':!wall, 'to':to, 'wall':wall, 'blocker':blocker, 'what':what };
     },
     
     
index af51a27..eb1d488 100644 (file)
@@ -39,61 +39,55 @@ Bullet = new Y.Class('Bullet', Thing, {
         return this;
     },
     
+    _depth : 0,
     move : function move(){
-        var p, wall, p2 = this.trajectory.p2
-        ,   level = this.game.level, walls = level.walls
-        ,   w = level.layerWidth, h = level.layerHeight
-        ,   trj = this.trajectory
-        ,   to  = this.trajectory.pcalc(this.elapsed)
+        var trj  = this.trajectory
+        ,   to   = trj.parametric(this.elapsed)
         ,   test = this.game.pathmap.attemptMove(this, trj, to)
         ;
         
-        // Do we need to reflect because we've hit a wall?
-        // if (to.x <= 0 || to.x >= w || to.y <= 0 || to.y >= h) {
-        //     if (to.x <= 0) {
-        //         wall = walls.left;
-        //         to = trj.pointX(0);
-        //     
-        //     } else if (to.x >= w) {
-        //         wall = walls.right;
-        //         to = trj.pointX(w);
-        //     
-        //     } else if (to.y <= 0) {
-        //         wall = walls.top;
-        //         to = trj.pointY(0);
-        //     
-        //     } else if (to.y >= h) {
-        //         wall = walls.bottom;
-        //         to = trj.pointY(h);
-        //     }
+        // Something obstructs us -- time to reflect!
         if (!test.ok) {
             to = test.to;
-            wall = test.line;
-            
-            p = math.reflect(p2, wall.tangent(to));
+            var wall = test.wall, p2 = trj.p2
+            ,   bb = this.boundingBox
+            ,   goal = wall.isWithin(p2,bb) ? trj.near(p2.x+2*REF_SIZE, p2.y+2*REF_SIZE) : p2
+            ,   _ng, ng = _ng = math.reflect(goal, wall)
+            ,   x1 = bb.x1, y1 = bb.y1
+            ,   tx = to.x,  ty = to.y
+            ,   cmp = Y.op.cmp
+            ;
             
             // Are we pointed the wrong direction? Rotate 180 degrees around the bullet
-            if (   (p.x <= 0 && to.x <= 0) || (p.y <= 0 && to.y <= 0)
-                || (p.x >= w && to.x >= w) || (p.y >= h && to.y >= h)
-            ){
-                var x = to.x - (p.x - to.x)
-                ,   y = to.y - (p.y - to.y);
-                p = new math.Vec(x,y);
-            }
+            if ( cmp(tx,x1) !== cmp(goal.x,x1) || cmp(ty,y1) !== cmp(goal.y,y1) )
+                ng = new math.Vec(tx - ng.x + tx, ty - ng.y + ty);
             
             this.trajectory = new math.Line(
-                    math.clamp(to.x, 0.1, w-0.1), math.clamp(to.y, 0.1, h-0.1),
-                    p.x,p.y,
+                    to.x,to.y, ng.x,ng.y,
                     this.stats.move * REF_SIZE/1000 );
             
-            // console.log('p2='+p2+' reflected in '+wall.tangent(to)+' --> '+this.trajectory);
+            // console.log('['+this._depth+' '+TICKS+'] '+this+' reflected by', test.what);
+            // console.log('  to='+to+',  goal='+goal+(p2.equals(goal) ? '' : ' <~ '+p2));
+            // console.log('  --> new goal='+ng+(ng.equals(_ng) ? '' : ' <~ '+_ng));
+            // console.log('  --> trajectory='+this.trajectory);
+            
+            this.render(this.game.level).draw();
+            this.elapsed = ELAPSED;
+            
+            if (this._depth++ < 3)
+                return this.move();
             
-            this.render(this.game.level);
-            this.elapsed = 0;
-            this.dirty = true;
-            return this.move();
+            console.log('['+this._depth+' '+TICKS+'] '+this+' reflected by', test.what);
+            console.log('  to='+to+',  goal='+goal+(p2.equals(goal) ? '' : ' <~ '+p2));
+            console.log('  --> new goal='+ng+(ng.equals(_ng) ? '' : ' <~ '+_ng));
+            console.log('  --> trajectory='+this.trajectory);
+            throw new Error('Reflection error!');
         }
         
+        // if (this._depth > 0)
+        //     console.warn('['+this._depth+'@'+TICKS+'] ok!');
+        
+        this._depth = 0;
         this.game.moveAgentTo(this, to.x, to.y);
         return this;
     },
@@ -104,24 +98,21 @@ Bullet = new Y.Class('Bullet', Thing, {
         
         var t = this.trajectory;
         this.tline = Line.fromPoints(t.x1,t.y1, t.x2,t.y2)
-            .attr('strokeStyle', 'rgba(255,246,174, 0.05)')
+            .attr('drawDefinitionPoints', true)
+            .stroke('rgba(255,246,174, 0.05)')
             .appendTo( parent );
         
         this.shape = new Circle(3)
             .position(this.loc.x, this.loc.y)
-            .attr({
-                'fillStyle'   : '#EC5B38',
-                'strokeStyle' : 'transparent',
-                'lineWidth'   : 0
-            })
+            .fill('#EC5B38')
             .appendTo( parent );
         
         return this;
     },
     
     toString : function toString(){
-        
-        return this.className+'(loc='+this.loc+', traj='+this.trajectory+', owner='+this.owner+')';
+        // return this.className+'(loc='+this.loc+', traj='+this.trajectory+', owner='+this.owner+')';
+        return this.className+'(loc='+this.loc+')';
     }
     
 });
index 670190f..7695136 100644 (file)
@@ -39,7 +39,7 @@ Tank = new Y.Class('Tank', Thing, {
         var ProjectileType = this.projectile
         ,   p = new ProjectileType(this, x,y);
         this.bullets.push(p);
-        this.game.addUnit(p);
+        this.game.addUnit(p).render(this.game.level);
         return p;
     },