, type = require('Y/type')
;
+/*
+
+end
+clone
+
+set
+attr
+
+extend
+merge
+concat
+
+reduce
+map
+forEach
+filter
+
+indexOf
+has
+remove
+
+every
+any
+
+pluck
+invoke
+
+zip
+
+apply
+
+toString
+*/
\ No newline at end of file
},
/**
- * Determines the point and line of intersection for the specified bounding boxes
- * along the given trajectory.
+ * Determines the side of intersection for this bounding box given start-
+ * and end-points along the trajectory.
+ * @return {Line} Side of intersection or null if no collision is detected.
*/
- // collision : function collision(trj, fromBB, toBB){
- //
- // if (bb.x2 <= B.x1 && x2 >= B.x1) {
- // side = B.leftSide;
- // to = trj.pointAtX(B.x1-offX-1);
- //
- // } else if (bb.x1 >= B.x2 && x1 <= B.x2) {
- // side = B.rightSide;
- // to = trj.pointAtX(B.x2+ro.x+1);
- //
- // } else if (bb.y2 <= B.y1 && y2 >= B.y1) {
- // side = B.topSide;
- // to = trj.pointAtY(B.y1-offY-1);
- //
- // } else if (bb.y1 >= B.y2 && y1 <= B.y2) {
- // side = B.bottomSide;
- // to = trj.pointAtY(B.y2+ro.y+1);
- // }
- // },
+ collision : function collision(trj, from, to){
+ if (from.x2 <= this.x1 && to.x2 >= this.x1)
+ return this.leftSide;
+
+ if (from.x1 >= this.x2 && to.x1 <= this.x2)
+ return this.rightSide;
+
+ if (from.y2 <= this.y1 && to.y2 >= this.y1)
+ return this.topSide;
+
+ if (from.y1 >= this.y2 && to.y1 <= this.y2)
+ return this.bottomSide;
+
+ return null;
+ },
+
+ /**
+ * Determines the furthest point before intersection between this bounding box
+ * and the box on given start- and end-points along the trajectory.
+ * @return {Vec} Furthest point or null if no collision is detected.
+ */
+ furthest : function furthest(trj, from, to){
+ if (from.x2 <= this.x1 && to.x2 >= this.x1)
+ return tr.pointAtX(this.x1 - 1 - from.originRight);
+
+ if (from.x1 >= this.x2 && to.x1 <= this.x2)
+ return tr.pointAtX(this.x2 + 1 + from.originLeft);
+
+ if (from.y2 <= this.y1 && to.y2 >= this.y1)
+ return tr.pointAtY(this.y1 - 1 - from.originTop);
+
+ if (from.y1 >= this.y2 && to.y1 <= this.y2)
+ return tr.pointAtY(this.y2 + 1 + from.originBottom );
+
+ return null;
+ },
/**
* Moves absolute location of the origin and retains its relative position of the bounds.
return a[_X]*b[_X] + a[_Y]*b[_Y];
},
- lerp : function lerp(x, a, b) {
- return new Vec( lerp(a[_X], b[_X], x),
- lerp(a[_Y], b[_Y], x) );
+ lerp : function vecLerp(x, a, b) {
+ return new Vec( lerp(x, a[_X], b[_X]),
+ lerp(x, a[_Y], b[_Y]) );
},
manhattan: function manhattan(x1,y1, x2,y2) {
this.boundaryWalls = Y.map(BWs, 'this.level.addWall.apply(this.level, _)', this);
},
+ getBlockers : function getBlockers(x1,y1, x2,y2, ignore){
+ if (x1 && x1.x1 !== undefined) {
+ ignore = y1;
+ y2 = x1.y2; x2 = x1.x2;
+ y1 = x1.y1; x1 = x1.x1;
+ }
+ var bs = this.get(x1,y1, x2,y2)
+ .filter('_.blocking === 2'); // map.BLOCKING
+ if (ignore && bs.length)
+ return bs.remove.apply(bs, ignore || []);
+ else
+ return bs;
+ },
+
wallObstructs : function wallObstructs(line){
return this.walls.some(function(wall){
return wall.boundingBox.intersects(line);
// End case -- result has been found, return the traced path
if (current === end) {
- var path = []
+ var path = Y([])
, mid = this.gridSquareMid
, node = current;
while( node.prev ) {
path.push( vec.sum(node,mid) );
node = node.prev;
}
- return Y(path.reverse());
+
+ if (!path.length)
+ return path;
+
+ path = Y(path.reverse());
+
+ // Ensure we don't get stuck on a corner on our first step
+ var first = path.first()
+ , bb = agent.boundingBox.relocated( vec.lerp(0.5, agent.loc,first) )
+ , blockers = this.getBlockers(bb, [agent]);
+
+ if (blockers.length)
+ path.unshift( vec.sum(start,mid) );
+
+ return path;
}
// Normal case -- move current from open to closed, process each of its neighbors
}
// No result was found -- empty array signifies failure to find path
- return [];
+ return Y([]);
},
vec2Square : function vec2Square(x,y){
if (x instanceof Array){ y = x.y; x = x.x; }
- var floor = Math.floor, size = this.gridSquare;
- return new Vec(floor(x/size), floor(y/size));
+ var floor = Math.floor, SIZE = this.gridSquare;
+ return new Vec(floor(x/SIZE), floor(y/SIZE));
},
square2Vec : function square2Vec(x,y){
if (x instanceof Array){ y = x.y; x = x.x; }
- var floor = Math.floor, size = this.gridSquare;
- return new Vec(floor(x)*size, floor(y)*size);
+ var floor = Math.floor, SIZE = this.gridSquare;
+ return new Vec(floor(x)*SIZE, floor(y)*SIZE);
}
})
* Checks for blockers and moves traversal bounds forward as much as possible.
*/
step : function step(tx,ty){
+ this.start = this.bbox.clone();
var tr = this.trajectory
, or = this.thing.loc
, dt = Math.min(tr.tBound, this.remaining)
},
rewind : function rewind(blocker){
- var tr = this.trajectory, bb = this.bbox
+ var tr = this.trajectory
+ , bb = this.bbox, st = this.start
, B = blocker.boundingBox
, to = this.to ;
// Figure out which boundary of the blocker we crossed and calculate
// the furthest non-overlapping point.
- if (bb.x2 <= B.x1 && bb.x2 >= B.x1) {
+ if (st.x2 <= B.x1 && bb.x2 >= B.x1) {
this.side = B.leftSide;
to = tr.pointAtX(B.x1 - 1 - bb.originRight);
- } else if (bb.x1 >= B.x2 && bb.x1 <= B.x2) {
+ } else if (st.x1 >= B.x2 && bb.x1 <= B.x2) {
this.side = B.rightSide;
to = tr.pointAtX(B.x2 + 1 + bb.originLeft);
- } else if (bb.y2 <= B.y1 && bb.y2 >= B.y1) {
+ } else if (st.y2 <= B.y1 && bb.y2 >= B.y1) {
this.side = B.topSide;
to = tr.pointAtY(B.y1 - 1 - bb.originTop);
- } else if (bb.y1 >= B.y2 && bb.y1 <= B.y2) {
+ } else if (st.y1 >= B.y2 && bb.y1 <= B.y2) {
this.side = B.bottomSide;
to = tr.pointAtY(B.y2 + 1 + bb.originBottom );
this.elapsed = elapsed;
this.now = now;
- this.continueMove();
- return;
+ // this.continueMove();
+ // return;
// Check to see if we should obey our last decision, and not recalc
if (this.forceCurrentMove && this.forceCurrentMove() && this.currentMoveLimit > now) {
, path = this.currentPath = pm.path(this, end)
, to = this.currentMove = path.shift()
;
- console.log('calculatePath()', start, 'toward:', end, 'next:', this.currentMove, 'path: ['+path.invoke('toString')+']');
+ // console.log('calculatePath()', start, 'toward:', end, 'next:', this.currentMove, 'path: '+path.invoke('toString'));
};
--- /dev/null
+var Y = require('Y').Y
+, op = require('Y/op')
+, Rect = require('ezl/shape').Rect
+, Thing = require('tanks/thing/thing').Thing
+, map = require('tanks/map/map')
+,
+
+
+Wall =
+exports['Wall'] =
+Thing.subclass('Wall', {
+ blocking : map.BLOCKING,
+ active : false,
+
+ originX : 0,
+ originY : 0,
+
+ stats : {
+ hp : Infinity,
+ move : 0,
+ power : 0,
+ speed : 0,
+ shots : 0
+ },
+
+ isBoundary : false,
+
+
+
+ init : function initWall(x,y, w,h, isBoundary){
+ this.width = w;
+ this.height = h;
+ this.isBoundary = !!isBoundary;
+ Thing.init.call(this);
+ this.position(x,y);
+ },
+
+ // inactive
+ createCooldowns : op.nop,
+
+ // indestructable
+ dealDamage : op.nop,
+
+
+ render : function render(parent){
+ if (this.isBoundary)
+ return this;
+
+ if (this.shape)
+ this.shape.remove();
+
+ this.shape =
+ new Rect(this.width, this.height)
+ .position(this.loc.x, this.loc.y)
+ .fill('rgba(255,255,255, 0.25)')
+ .appendTo( parent );
+
+ return this;
+ },
+
+ toString : function(){
+ var bb = this.boundingBox
+ , x1,y1, x2,y2;
+ if (bb){
+ x1 = bb.x1; y1 = bb.y1;
+ x2 = bb.x2; y2 = bb.y2;
+ } else {
+ x1=y1=x2=y2=NaN;
+ }
+ return this.className+'['+x1+','+y1+', '+x2+','+y2+'](w='+this.width+', h='+this.height+')';
+ }
+});
+