From: dsc Date: Wed, 24 Nov 2010 00:03:53 +0000 (-0800) Subject: Fixes rect-line intersection. X-Git-Url: http://git.less.ly:3516/?a=commitdiff_plain;h=dc1b43126881d92e9bf292073400fbd895015bc6;p=tanks.git Fixes rect-line intersection. --- diff --git a/src/Y/y-array.js b/src/Y/y-array.js index 46fa261..7871abe 100644 --- a/src/Y/y-array.js +++ b/src/Y/y-array.js @@ -85,7 +85,7 @@ YCollection.subclass('YArray', function(YArray){ chainDelegates(YArray, 'push', 'unshift', 'sort', 'splice', 'reverse'); - mixinNames(YArray, Array, ['reduce', 'map', 'forEach', 'filter', 'slice'], true, true); + mixinNames(YArray, Array, ['reduce', 'map', 'forEach', 'filter', 'slice', 'some', 'every'], true, true); mixinNames(YArray, Array, ['indexOf', 'lastIndexOf', 'shift', 'pop', 'join'], true, false); return this; diff --git a/src/portal/math/line.js b/src/portal/math/line.js index 11734b8..237aaac 100644 --- a/src/portal/math/line.js +++ b/src/portal/math/line.js @@ -10,7 +10,7 @@ COS_HALF_PI = Math.cos(HALF_PI); /** * A line in the cartesian plane. */ -math.Line = new Y.Class('Line', math.Vec, { +math.Line = math.Vec.subclass('Line', { init : function initLine(x1,y1, x2,y2, tdist){ this.x1 = x1; this.y1 = y1; diff --git a/src/portal/shape/rect.js b/src/portal/shape/rect.js index 0d84e51..ea8ca8c 100644 --- a/src/portal/shape/rect.js +++ b/src/portal/shape/rect.js @@ -1,5 +1,5 @@ -Rect = new Y.Class('Rect', Shape, { +Rect = Shape.subclass('Rect', { _cssClasses : 'portal layer shape rect', init : function initRect(w,h){ @@ -23,3 +23,6 @@ Rect = new Y.Class('Rect', Shape, { } }); +Rect.fromPoints = function(x1,y1, x2,y2){ + return new Rect(x2-x1, y2-y1).position(x1,y1); +}; \ No newline at end of file diff --git a/src/tanks/map/loc.js b/src/tanks/map/loc.js index 43453a9..6024481 100644 --- a/src/tanks/map/loc.js +++ b/src/tanks/map/loc.js @@ -108,6 +108,13 @@ Loc.Rect = new Y.Class('Rect', [], { y2 = y1.y; x2 = y1.x; y1 = x1.y; x1 = x1.x; } + // init : function initRect(_x1,_y1, _x2,_y2){ + // if (_x1 instanceof Loc && _y1 instanceof Loc) { + // _y2 = _y1.y; _x2 = _y1.x; + // _y1 = _x1.y; _x1 = _x1.x; + // } + // var x1 = Math.min(_x1,_x2), x2 = Math.max(_x1,_x2) + // , y1 = Math.min(_y1,_y2), y2 = Math.max(_y1,_y2); this.length = 4; this.x1 = this[0] = this.x = x1; @@ -127,6 +134,16 @@ Loc.Rect = new Y.Class('Rect', [], { y >= this.y1 && y <= this.y2 ); }, + intersects : function intersects(line){ + var x1 = Math.min(this.x1,this.x2), x2 = Math.max(this.x1,this.x2) + , y1 = Math.min(this.y1,this.y2), y2 = Math.max(this.y1,this.y2) + , cx1,cy1, cx2,cy2 ; + return ( ( (cx1 = line.calcX(y1)) >= x1 && cx1 <= x2 ) + || ( (cy1 = line.calcY(x1)) >= y1 && cy1 <= y2 ) + || ( (cx2 = line.calcX(y2)) >= x1 && cx2 <= x2 ) + || ( (cy2 = line.calcY(x2)) >= y1 && cy2 <= y2 ) ); + }, + midpoint : function midpoint(){ return new Loc( this.x1 + this.width /2 , this.y1 + this.height/2 ); diff --git a/src/tanks/map/pathmap.js b/src/tanks/map/pathmap.js index 51be52e..665f2df 100644 --- a/src/tanks/map/pathmap.js +++ b/src/tanks/map/pathmap.js @@ -18,7 +18,8 @@ PathMap = QuadTree.subclass('PathMap', { }, setup : function setup(x1,y1, x2,y2){ - var w = this.width, h = this.height, level = this.level + var w = this.width, h = this.height + , level = this.level , BWs = { top : [x1,y1, w,1, true], @@ -30,6 +31,15 @@ PathMap = QuadTree.subclass('PathMap', { this.boundaryWalls = Y.map(BWs, 'this.level.addWall.apply(this.level, _)', this); }, + wallObstructs : function wallObstructs(line, w,h){ + return this.walls.some(function(wall){ + var bb = wall.boundingBox + , ss = bb.sides ; + return ( line.calcY(bb.x1) >= bb.y1 && line.calcY(bb.x2) <= bb.y2 ) + || ( line.calcX(bb.y1) >= bb.x1 && line.calcX(bb.y2) <= bb.x2 ) ; + }, this); + }, + addBlocker : function addBlocker(obj){ this.removeBlocker(obj); var bb = obj.boundingBox; diff --git a/src/tanks/map/trajectory.js b/src/tanks/map/trajectory.js index 6b35eea..0521f90 100644 --- a/src/tanks/map/trajectory.js +++ b/src/tanks/map/trajectory.js @@ -118,6 +118,24 @@ Trajectory = math.Line.subclass('Trajectory', { return to; }, + willComeWithin : function willComeWithin(pt, w,h){ + if ( !this.owner.midpoint ) + return false; + + if ( !Y.isNumber(w) ){ + h = w.height; w = w.width; + } + + var cur = this.owner.midpoint + , fx = this.calcX(pt.y), fy = this.calcY(pt.x) + , t = this.iparametric(cur.x, cur.y) + , ft = this.iparametric(fx,fy) + , dw = Math.abs(fx - pt.x), dh = Math.abs(fy - pt.y) + ; + return ( t.x <= ft.x && t.y <= ft.y + && ( dw <= w || dh <= h ) + && !this.pathmap.wallObstructs(this, w,h) ); + }, toString : function toString(){ return 'T['+this.p1+', '+this.p2+', slope='+this.slope.toFixed(3)+']'; diff --git a/src/tanks/thing/tank.js b/src/tanks/thing/tank.js index 1948e5f..1429cd2 100644 --- a/src/tanks/thing/tank.js +++ b/src/tanks/thing/tank.js @@ -89,13 +89,12 @@ Tank = Thing.subclass('Tank', { } // Try to blow up nearby tanks - var t = this.findNearEnemies(66).shift(); + var t = this.findNearEnemies(66, true).shift(); if (t) { // console.log('I gotcha!', t); this.shoot(t.loc.x, t.loc.y); return this; } - } // Nothing to shoot at? Move toward something @@ -109,12 +108,12 @@ Tank = Thing.subclass('Tank', { }, closestOf : function closestOf(agents){ - if (!agents || !agents.size()) + if ( !(agents && agents.size()) ) return null; var manhattan = math.Vec.manhattan - , bb = this.boundingBox, mid = this.midpoint - ; + , bb = this.boundingBox, mid = this.midpoint ; + agents.sort(function(a,b){ return Y.op.cmp( manhattan(a.loc,mid), @@ -208,8 +207,17 @@ Tank = Thing.subclass('Tank', { return this.game.pathmap.get(x1,y1, x2,y2).filter(fn, this); }, - findNearEnemies : function findNearEnemies(ticks){ - return this.findNearLike(ticks, 'Y.is(Tank, _) && _.align !== this.align'); + findNearEnemies : function findNearEnemies(ticks, wallObs){ + var bb = this.boundingBox + , mid = this.midpoint + , pm = this.game.pathmap ; + return this.findNearLike(ticks, function(agent){ + var am = agent.midpoint; + return agent.align !== this.align + && Y.is(Tank, agent) + && !(wallObs + && pm.wallObstructs(new Trajectory(this, mid.x,mid.y, am.x,am.y), 6,6)); + }); }, shoot : function shoot(x,y){ diff --git a/src/tanks/ui/grid.js b/src/tanks/ui/grid.js index ca98808..a055b95 100644 --- a/src/tanks/ui/grid.js +++ b/src/tanks/ui/grid.js @@ -3,6 +3,8 @@ Grid = new Y.Class('Grid', Rect, { lineWidth : 0.5, strokeStyle : '#6E6E6E', + createTableGrid : true, + createCanvasGrid : true, init : function init(cols,rows, size){ @@ -13,46 +15,52 @@ Grid = new Y.Class('Grid', Rect, { }, drawShape : function drawShape(ctx){ - var tbody = $('') - , cols = this.cols, rows = this.rows + if (this.table) this.table.remove(); + // if (this.canvas) this.canvas.remove(); + + var cols = this.cols, rows = this.rows , size = this.size , w = this.canvasWidth , h = this.canvasHeight ; - Y(0, rows).forEach(function(y){ - var row = $('').appendTo(tbody); - Y(0, cols).forEach(function(x){ - $(''+x+','+y+'') - .width(size).height(size) - .appendTo(row); + if ( this.createTableGrid ) { + var tbody = $(''); + Y(0, rows).forEach(function(y){ + var row = $('').appendTo(tbody); + Y(0, cols).forEach(function(x){ + $(''+x+','+y+'') + .width(size).height(size) + .appendTo(row); + }, this); }, this); - }, this); - - - this.table = - $('') - .width(this.layerWidth) - .height(this.layerHeight) - .append(tbody) - .prependTo( this.layer ); - - // this.canvas.remove(); + + this.table = + $('
') + .width(this.layerWidth) + .height(this.layerHeight) + .append(tbody) + .prependTo( this.layer ); + + } else + this.table = null; - ctx.lineWidth = this.lineWidth; - ctx.strokeStyle = this.strokeStyle; - - for (var row=0, y=0; row<=rows; y = (++row) * size){ - ctx.moveTo(0, y); - ctx.lineTo(w, y); - } - - for (var col=0, x=0; col<=cols; x = (++col) * size){ - ctx.moveTo(x, 0); - ctx.lineTo(x, h); + if ( this.createCanvasGrid ) { + ctx.lineWidth = this.lineWidth; + ctx.strokeStyle = this.strokeStyle; + + for (var row=0, y=0; row<=rows; y = (++row) * size){ + ctx.moveTo(0, y); + ctx.lineTo(w, y); + } + + for (var col=0, x=0; col<=cols; x = (++col) * size){ + ctx.moveTo(x, 0); + ctx.lineTo(x, h); + } + + ctx.stroke(); } - - ctx.stroke(); } }); \ No newline at end of file diff --git a/test/math/index.php b/test/math/index.php index c4ea7f5..a96d3a3 100644 --- a/test/math/index.php +++ b/test/math/index.php @@ -26,6 +26,7 @@ h1 { position:fixed; top:0; right:0; margin:0; padding:0; font-size:3em; color:# #info legend { color:#ccc; font-weight:bold; padding:0 0.5em; } #info input { width:3em; font-size:0.8em; padding:0.1em; text-align:center; background-color:rgba(0,0,0, 0.2); color:#ccc; border:0; } #info label { margin-right:1em; } +#info pre { padding:0.5em; height:5em; font:12px monospace; background-color:rgba(0,0,0, 0.2); color:#ccc; border:0; } #howto { position:relative; width:600px; margin:1em auto; background-color:#D8D8D8; } @@ -49,6 +50,7 @@ h1 { position:fixed; top:0; right:0; margin:0; padding:0; font-size:3em; color:# ( , ) +
diff --git a/test/math/math.test.js b/test/math/math.test.js index ce7c5a1..237ac71 100644 --- a/test/math/math.test.js +++ b/test/math/math.test.js @@ -11,6 +11,7 @@ COLS = w/PPU; COLS2 = COLS/2; ROWS = h/PPU; ROWS2 = ROWS/2; grid = new Grid( COLS, ROWS, PPU ).appendTo(plot); +grid.createTableGrid = false; grid.lineWidth = 1.0; grid.strokeStyle = '#E0E0E0'; //'#EEEEEE'; // grid.draw(); @@ -28,6 +29,13 @@ ctx = P.ctx; ctx.translate(w2, h2); ctx.scale(PPU, PPU); + +r = new Loc.Rect(2,6, 4,2); +R = Rect.fromPoints(r.x1*PPU,-r.y1*PPU, r.x2*PPU,-r.y2*PPU) + .fill('rgba(131,187,50, 0.5)') + .appendTo(P); +R.position(R.loc.x+w2, R.loc.y+h2); + points = Y([]); line = mkLine(0,0, 2.3125,1); addPoint(-5,2); @@ -42,6 +50,7 @@ P.layer.bind('click', function(evt){ return false; }); + $('form#line, #line input').bind('submit blur', function(evt){ var x1 = parseFloat($('#info [name=x1]').val()) , y1 = parseFloat($('#info [name=y1]').val()) @@ -58,6 +67,7 @@ $('form#line, #line input').bind('submit blur', function(evt){ return false; }); + }); function updateInfo(){ @@ -65,6 +75,7 @@ function updateInfo(){ $('#info [name=y1]').val(line.y1); $('#info [name=x2]').val(line.x2); $('#info [name=y2]').val(line.y2); + $('#info #inter').text([ 'rect:'+r, 'rect.intersects(line)? '+r.intersects(line) ].join('\n')); } function redraw(color){