Movement and pathing sorta work again! AI tanks are a bit off though.
authordsc <david.schoonover@gmail.com>
Tue, 21 Dec 2010 00:49:46 +0000 (16:49 -0800)
committerdsc <david.schoonover@gmail.com>
Tue, 21 Dec 2010 00:49:46 +0000 (16:49 -0800)
src/ezl/loop/eventloop.cjs
src/ezl/math/rect.cjs
src/tanks/map/level.cjs
src/tanks/map/pathmap.cjs
src/tanks/map/traversal.cjs
src/tanks/thing/bullet.cjs
src/tanks/thing/player.cjs
src/tanks/thing/tank.cjs

index c93e2e5..6d2895f 100644 (file)
@@ -96,7 +96,7 @@ Emitter.subclass('EventLoop', {
         var lastTick = this.now;
         this.now     = new Date().getTime();
         this.elapsed = this.now - lastTick;
-        this.perceived = this.elapsed/this.dilation;
+        this.perceived = this.elapsed/this.timeDilation;
         
         clearTimeout(this.timer);
         this.timer = null;
index 7cf09e0..0d665e4 100644 (file)
@@ -1,5 +1,7 @@
-var Y = require('Y').Y
-,   Vec = require('ezl/math/vec').Vec
+var Y    = require('Y').Y
+,   Vec  = require('ezl/math/vec').Vec
+,   Line = require('ezl/math/line').Line
+
 ,   X1 = 0, Y1 = 1
 ,   X2 = 2, Y2 = 3
 ,
index a3cc320..3da05b1 100644 (file)
@@ -42,8 +42,8 @@ Rect.subclass('Level', {
         // game.addThing(new Tank(1).colors('#4596FF', '#182B53', '#F25522'), 3,9);
         
         E = 
-        game.addThing(new Tank(2), 0,1);
-        game.addThing(new Tank(2), 1,0);
+        game.addThing(new Tank(2), 0,0);
+        // game.addThing(new Tank(2), 1,0);
         // game.addThing(new Tank(2), 8,1);
         
         I = game.addThing(new Item(), 8,8);
index 14f2ad5..7c6cc28 100644 (file)
@@ -23,7 +23,7 @@ var Y          = require('Y').Y
 // Would be nice if I could make this an inner class (for once)
 Square =
 exports['Square'] =
-Vec.subclass('Square', {
+Y.subclass('Square', new Vec(0,0), {
     pathId : null, // instance of A* being run, to track when to reset
     
     // resetable:
@@ -51,7 +51,7 @@ Vec.subclass('Square', {
             return this;
         
         this.pathId = pathId;
-        this._blocked();
+        this.blocked = this._blocked();
         
         this.dist      = 0;
         this.startDist = 0;
@@ -64,7 +64,7 @@ Vec.subclass('Square', {
     },
     
     /**
-     * @private Caches this.blocked value. Should only be called by reset().
+     * @private Calculates this.blocked value. Should only be called by reset() to cache the result.
      */
     _blocked : function blocked(){
         var pm    = this.pathmap
@@ -78,15 +78,17 @@ Vec.subclass('Square', {
         ,   SIZE = pm.gridSquare
         ,   x  = Math.floor(this.x)
         ,   y  = Math.floor(this.y)
-        ,   x1 = x - left,  x2 = x + SIZE + right
-        ,   y1 = y - top,   y2 = y + SIZE + bottom
+        // ,   x1 = x - left,  x2 = x + SIZE + right
+        // ,   y1 = y - top,   y2 = y + SIZE + bottom
+        ,   x1 = x,  x2 = x + SIZE
+        ,   y1 = y,  y2 = y + SIZE
         
         ,   blockers = pm.get(x1,y1, x2,y2)
                 .remove(agent)
                 .filter(this._filterBlocked)
         ;
         
-        this.blocked = !!blockers.length;
+        return !!blockers.length;
     },
     
     /**
@@ -104,23 +106,39 @@ Vec.subclass('Square', {
         ,   SIZE  = pm.gridSquare
         
         ,   x = this.x,  y = this.y
-        ,   sq, cost, ix, iy
+        ,   sq, cost, ix, iy, x1,y1, x2,y2
         ;
         
         for (ix=-1; ix<2; ix++) {
             for (iy=-1; iy<2; iy++) {
-                // if (ix === 0 && iy === 0) // skipping diagonals
-                if ( (ix === 0 && iy === 0) || (abs(ix) === 1 && abs(iy) === 1) )
+                // if (ix === 0 && iy === 0)
+                if ( (ix === 0 && iy === 0) || (abs(ix) === 1 && abs(iy) === 1) ) // skipping diagonals
+                    continue;
+                x1 = x + ix*SIZE;  y1 = y + iy*SIZE;
+                x2 = x1+SIZE;      y2 = y1+SIZE;
+                if (    pm.x1 >= x1 || pm.y1 >= y1 ||
+                        pm.x2 <= x2 || pm.y2 <= y2 )
                     continue;
                 // TODO: handle diagonals: need to ensure we don't try to move through a corner
                 // cost = ( abs(ix) === 1 && abs(iy) === 1 ) ? SQRT_TWO : 1;
                 cost = 1;
-                sq = pm._getSquare(x + ix*SIZE, y + iy*SIZE);
-                if ( !sq.blocked ) neighbors.push([ sq, cost*SIZE ]);
+                sq = pm._getSquare(x1,y1);
+                // if ( !sq.blocked ) neighbors.push([ sq, cost*SIZE ]);
+                neighbors.push([ sq, cost*SIZE ]);
             }
         }
         
         return neighbors;
+    },
+    
+    toString : function toString(){
+        var props = [];
+        if (this.blocked) props.push('blocked');
+        if (this.visited) props.push('dist='+this.dist);
+        if (this.closed) props.push('closed');
+        props = props.join(', ');
+        if (props) props = '('+props+')';
+        return '['+this.x+' '+this.y+']'+props;
     }
     
 })
@@ -193,10 +211,12 @@ Map.subclass('PathMap', {
      */
     _getSquare : function getSquare(x,y){
         if (x instanceof Array) { y=x[1]; x=x[0]; }
-        x = Math.floor(x);  y = Math.floor(y);
-        
         var cache = this._squares
-        ,   key = x+"_"+y
+        ,   SIZE = this.gridSquare ;
+        
+        x = Math.floor(x / SIZE) * SIZE;
+        y = Math.floor(y / SIZE) * SIZE;
+        var key = x+'_'+y
         ,   sq  = cache[key] ;
         
         if (sq)
@@ -227,10 +247,13 @@ Map.subclass('PathMap', {
         ,   start = this._getSquare(agent.loc)
         ,   end   = this._getSquare(x,y)
         ,   open  = new BinaryHeap('dist') // 'dist' is the scoring key on heap objects
+        
+        ,   iterations = 0
         ;
         
         open.push(start);
         while (open.length) {
+            iterations++;
             
             // Grab the lowest f(x) to process next.  Heap keeps this sorted for us.
             var current = open.pop();
@@ -238,9 +261,10 @@ Map.subclass('PathMap', {
             // End case -- result has been found, return the traced path
             if (current === end) {
                 var path = []
+                ,   mid  = this.gridSquareMid
                 ,   node = current;
                 while( node.prev ) {
-                    path.push( node );
+                    path.push( vec.sum(node,mid) );
                     node = node.prev;
                 }
                 return path.reverse();
@@ -283,6 +307,7 @@ Map.subclass('PathMap', {
                     } else
                         open.rescore(node);
                 }
+                var _node = node;
             }
         }
         
index 29a5471..7fe1e34 100644 (file)
@@ -18,7 +18,7 @@ Y.subclass('Traversal', {
     init : function initTraversal(thing, trajectory){
         this.thing      = thing;
         this.game       = thing.game;
-        this.pathmap    = thing.pathmap;
+        this.pathmap    = thing.game.pathmap;
         this.bbox       = thing.boundingBox.clone();
         
         this.trajectory = trajectory || thing.trajectory;
@@ -36,8 +36,9 @@ Y.subclass('Traversal', {
             
             if (this.isBlocked) {
                 this.remaining = dt;
-                this.thing.fire('collide', this.blocker);
-                this.blocker.fire('collide', this.thing);
+                var data = { 'traversal':this };
+                this.thing.fire('collide', this.blocker, data);
+                this.blocker.fire('collide', this.thing, data);
                 break;
             }
             
@@ -53,6 +54,7 @@ Y.subclass('Traversal', {
      */
     stepTo : function stepTo(t, tx,ty){
         var blockers, blocker, B
+        ,   abs = Math.abs
         ,   traj = this.trajectory, thing = this.thing
         
         ,   bb = this.bbox
@@ -82,9 +84,10 @@ Y.subclass('Traversal', {
         // TODO: Either: this never happens (current belief) OR it needs better corner-detection
         // Literal corner case :P
         if (blockers.length > 1) {
-            console.error('Corner! WHO KNEW.', 'to:', to, 'blockers:', blockers);
+            console.error('Corner!', 'to:', to, 'blockers:', blockers);
+            // throw new Error('Corner! to:'+to+', blockers:'+blockers);
             this.isCorner = true;
-            // to = trj.p1; // Turn around, go back whence you came
+            // to = traj.p1; // Turn around, go back whence you came
         }
         
         // blocker = traj.closest(blockers)
@@ -93,30 +96,32 @@ Y.subclass('Traversal', {
         
         // Figure out which boundary of the blocker we crossed and calculate
         // the furthest non-overlapping point.
-        if (bb.x2 <= B.x1 && x2 >= B.x1) {
-            this.to = to = trj.pointAtX(B.x1 - 1 - bb.originRight);
+        if (x2 <= B.x1 && bb.x2 >= B.x1) {
+            this.to = to = traj.pointAtX(B.x1 - 1 - bb.originRight);
             this.side = B.leftSide;
             
-        } else if (bb.x1 >= B.x2 && x1 <= B.x2) {
-            this.to = to = trj.pointAtX(B.x2 + 1 + bb.originLeft);
+        } else if (x1 >= B.x2 && bb.x1 <= B.x2) {
+            this.to = to = traj.pointAtX(B.x2 + 1 + bb.originLeft);
             this.side = B.rightSide;
             
-        } else if (bb.y2 <= B.y1 && y2 >= B.y1) {
-            this.to = to = trj.pointAtY(B.y1 - 1 - bb.originTop);
+        } else if (y2 <= B.y1 && bb.y2 >= B.y1) {
+            this.to = to = traj.pointAtY(B.y1 - 1 - bb.originTop);
             this.side = B.topSide;
             
-        } else if (bb.y1 >= B.y2 && y1 <= B.y2) {
-            this.to = to = trj.pointAtY(B.y2 + 1 + bb.originBottom );
+        } else if (y1 >= B.y2 && bb.y1 <= B.y2) {
+            this.to = to = traj.pointAtY(B.y2 + 1 + bb.originBottom );
             this.side = B.bottomSide;
+            
         } else {
             console.error('Null reflection line!', 'to:', to, 'blockers:', blockers);
+            // throw new Error('Null reflection line! to:'+to+', blockers:'+blockers);
         }
         
         // Move bounding box to furthest non-overlapping point
         bb.relocate(to);
         
         // Return how much time consumed
-        return trj.timeToMove(to.x-o.x, to.y-o.y);
+        return traj.timeToMove(to.x-o.x, to.y-o.y);
     }
     
 })
index 08de2ac..22d1b94 100644 (file)
@@ -91,7 +91,7 @@ Thing.subclass('Bullet', {
     move : function move(elapsed, now){
         if (this.dead) return this;
         
-        var tvsl = new Traversal(this, this.trajectory)
+        var tvsl = new Traversal(this)
         ,   to = tvsl.step(elapsed)
         ;
         
@@ -110,7 +110,7 @@ Thing.subclass('Bullet', {
         if ( this.dead ) return;
         
         var ng
-        ,   tvsl = evt.target
+        ,   tvsl = evt.data.traversal
         ,   traj = this.trajectory
         ,   to   = tvsl.to
         
index 8455342..619cf4b 100644 (file)
@@ -56,6 +56,9 @@ Tank.subclass('PlayerTank', {
     
     
     act : function act(elapsed, now){
+        this.elapsed = elapsed;
+        this.now = now;
+        
         if (this.dead)
             return this;
         
@@ -86,7 +89,7 @@ Tank.subclass('PlayerTank', {
         if (!dir) return;
         
         // @see Tank.move()
-        this.move(this.loc.moveByDir(dir, this.stats.move * SQUARETH));
+        this.move( this.loc.moveByDir(dir, this.stats.move * SQUARETH) );
     },
     
     // _move : function _move(){
index 40238a5..fbbb7fd 100644 (file)
@@ -80,6 +80,9 @@ Thing.subclass('Tank', function(Tank){
     
     this['act'] =
     function act(elapsed, now){
+        this.elapsed = elapsed;
+        this.now = now;
+        
         var ai = this.ai;
         
         // Check to see if we should obey our last decision, and not recalc
@@ -293,11 +296,11 @@ Thing.subclass('Tank', function(Tank){
         ,   cur = this.currentMove
         ;
         
-        if (cur.x !== x || cur.y !== y)
+        if ( !(this.trajectory && cur && cur.x === x && cur.y === y) )
             this.trajectory = new Trajectory(this, loc.x,loc.y, x,y, this.movePerMs);
         
-        var tvsl = new Traversal(this, this.trajectory)
-        ,   to = tvsl.step(elapsed, x,y)
+        var tvsl = new Traversal(this)
+        ,   to = tvsl.step(this.elapsed, x,y)
         ;
         
         this.game.moveThingTo(this, to.x,to.y);
@@ -308,35 +311,35 @@ Thing.subclass('Tank', function(Tank){
      * @protected
      * This method does not update this.trajectory -- call this.move(x,y) instead.
      */
-    this['moveByAngle'] =
-    function moveByAngle(theta, targetX,targetY){
-        var abs = Math.abs
-        ,   bb  = this.boundingBox
-        ,   loc = this.loc
-        ,   to  = loc.moveByAngle(theta, this.stats.move * SQUARETH)
-        ,   x = to.x, y = to.y
-        ;
-        
-        // Don't overshoot the target
-        if ( targetX !== undefined && abs(loc.x-x) > abs(loc.x-targetX) )
-            x = targetX;
-        
-        if ( targetY !== undefined && abs(loc.y-y) > abs(loc.y-targetY) )
-            y = targetY;
-        
-        var nbb = bb.relocated(x,y)
-        ,   blockers = this.game.pathmap.get(nbb.x1,nbb.y1, nbb.x2,nbb.y2).remove(this);
-        
-        if ( !blockers.size() )
-            this.game.moveThingTo(this, x,y);
-        
-        return this;
-    };
+    // this['moveByAngle'] =
+    // function moveByAngle(theta, targetX,targetY){
+    //     var abs = Math.abs
+    //     ,   bb  = this.boundingBox
+    //     ,   loc = this.loc
+    //     ,   to  = loc.moveByAngle(theta, this.stats.move * SQUARETH)
+    //     ,   x = to.x, y = to.y
+    //     ;
+    //     
+    //     // Don't overshoot the target
+    //     if ( targetX !== undefined && abs(loc.x-x) > abs(loc.x-targetX) )
+    //         x = targetX;
+    //     
+    //     if ( targetY !== undefined && abs(loc.y-y) > abs(loc.y-targetY) )
+    //         y = targetY;
+    //     
+    //     var nbb = bb.relocated(x,y)
+    //     ,   blockers = this.game.pathmap.get(nbb.x1,nbb.y1, nbb.x2,nbb.y2).remove(this);
+    //     
+    //     if ( !blockers.size() )
+    //         this.game.moveThingTo(this, x,y);
+    //     
+    //     return this;
+    // };
     
     
     this['continueMove'] =
     function continueMove(){
-        if ( !this.currentMove || this.currentMoveLimit <= NOW ){
+        if ( !this.currentMove || this.ai.path.ready ){
             var target = this.findNearEnemies(10000).shift();
             if (target) this.calculatePath(target.loc);
         }
@@ -344,8 +347,8 @@ Thing.subclass('Tank', function(Tank){
         var to = this.currentMove;
         if (!to) return;
         
-        this.move(to.x, to.y);
-        if ( this.midpoint.equals(to) ) {
+        this.move(to);
+        if ( this.loc.equals(to) ) {
             this.forceCurrentMove = false;
             this.currentMoveLimit = -1;
             this.currentMove = (this.lastPath ? this.lastPath.shift() : null);