From: dsc Date: Wed, 17 Nov 2010 07:41:13 +0000 (-0800) Subject: Moves pathmap test back. Adds collisions to player tank. X-Git-Url: http://git.less.ly:3516/?a=commitdiff_plain;h=c6d196f6d19f2952970db9dac2cae56072a027d1;p=tanks.git Moves pathmap test back. Adds collisions to player tank. --- diff --git a/notes.md b/notes.md index 4961760..26c0f5a 100644 --- a/notes.md +++ b/notes.md @@ -1,10 +1,4 @@ -- use unit vectors for trajectories ---> use matrix math for reflections -- incremental calls to move -- collision object for recalculating pathing - # Bugs -- Have move() do incremental calls (consuming elapsed time? distance?) if a push results in a move of x or y larger than the bounding box. # TODOs - Move game objects into namespace `tanks` @@ -15,3 +9,6 @@ # Notes - TODO Replace *2 and /2 with shifts at compile-time - Clipping will suck (masking is easy -- overflow:hidden) +- Should use unit vectors for trajectories? +--> matrix math for reflections? + diff --git a/src/portal/layer.js b/src/portal/layer.js index ebf2f50..bc8bf6c 100644 --- a/src/portal/layer.js +++ b/src/portal/layer.js @@ -221,7 +221,7 @@ 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.boundingBox = this.boundingBox.add(pos.left,pos.top); this.loc = this.boundingBox.p1; this.css(pos); return this; diff --git a/src/portal/math/oldline.js b/src/portal/math/oldline.js deleted file mode 100644 index b13b4bf..0000000 --- a/src/portal/math/oldline.js +++ /dev/null @@ -1,134 +0,0 @@ -(function(){ - -var -HALF_PI = Math.PI/2, -SIN_HALF_PI = Math.sin(HALF_PI), -COS_HALF_PI = Math.cos(HALF_PI); - - -/** - * A line in the cartesian plane. - */ -math.Line = new Y.Class('Line', math.Vec, { - - init : function initLine(x1,y1, x2,y2, tdist){ - this.x1 = x1; this.y1 = y1; - this.x2 = x2; this.y2 = y2; - - var xdelta = x2-x1, ydelta = y2-y1 - , m = this.slope = ydelta/xdelta - , yi = this.yint = -x1*m + y1 - , xi = this.xint = -y1/m + x1 - ; - math.Vec.init.call(this, xdelta, ydelta); - - this.p1 = new math.Vec(x1,y1); - this.p2 = new math.Vec(x2,y2); - - this.theta = Math.atan2(ydelta, xdelta); - this._cos = Math.cos(this.theta); - this._sin = Math.sin(this.theta); - - this.setTScale(tdist); - }, - - clone : function clone(){ - return new math.Line(this.x1,this.y1, this.x2,this.y2, this.tdist); - }, - - equals : function equals(line){ - return ( this.slope === line.slope - && this.x1 === line.x1 && this.y1 === line.y1 - && this.x2 === line.x2 && this.y2 === line.y2 ); - }, - - intersects : function intersects(x,y){ - var o = x; - if (o instanceof math.Line) - return this.slope !== o.slope || this.equals(o); - - if (o instanceof math.Vec) { - x = o.x; - y = o.y; - } - 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; - this.pa = tdist * this._cos; - this.pb = tdist * this._sin; - } else { - this.tdist = this.y / this._sin; - this.pa = this.x; - this.pb = this.y; - } - return this; - }, - - parametric : function parametric(t){ - return new math.Vec( this.x1 + t*this.pa , - this.y1 + t*this.pb ); - }, - - pointAtX : function pointAtX(x){ - return new math.Vec(x, this.calcY(x)); - }, - - 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.xint ? 0 : x*this.slope + this.yint); - }, - - calcX : function calcX(y){ - return (y === this.yint ? 0 : y/this.slope + this.xint); - }, - - base : function base(){ - if (!this._base) - this._base = new math.Line(0,0, this.x,this.y); - return this._base; - }, - - tangent : function tangent(at){ - var slope = this.slope; - - if ( slope === 0 ) - return new math.Line(at.x,at.y, at.x,at.y+1, this.tdist); - - if ( !isFinite(slope) ) - return new math.Line(at.x,at.y, at.x+1,at.y, this.tdist); - - var x1 = at.x, y1 = at.y - , x2 = at.x - at.y + (at.y !== this.y1 ? this.y1 : this.y2) - , y2 = at.y + at.x - (at.x !== this.x1 ? this.x1 : this.x2) ; - return new math.Line(x1,y1, x2,y2, this.tdist); - }, - - toString : function toString(){ - return '['+this.p1+', '+this.p2+', slope='+this.slope.toFixed(3)+']'; - } - -}); - -})(); \ No newline at end of file diff --git a/src/tanks/config.js b/src/tanks/config.js index 7092331..97513b4 100644 --- a/src/tanks/config.js +++ b/src/tanks/config.js @@ -5,6 +5,6 @@ tanks.config = { traceTrajectories : true }, debug : { - projectiles : 1 + projectiles : 2 } }; \ No newline at end of file diff --git a/src/tanks/main.js b/src/tanks/main.js index 3d3035b..6764658 100644 --- a/src/tanks/main.js +++ b/src/tanks/main.js @@ -1,10 +1,7 @@ var btank = null , bullets = new Y.YArray() ; - - (function(){ - jQuery(main); @@ -27,8 +24,8 @@ function main(){ new Player(LBT, T); setupUI(); - B = bullets.attr(0); - T = B.trajectory; + // B = bullets.attr(0); + // T = B.trajectory; } diff --git a/src/tanks/map/collision.js b/src/tanks/map/collision.js index b1694f2..ee4ea47 100644 --- a/src/tanks/map/collision.js +++ b/src/tanks/map/collision.js @@ -1,5 +1,7 @@ Collision = new Y.Class('Collision', { - + init : function initCollision(line, to){ + + }, }); \ No newline at end of file diff --git a/src/tanks/map/loc.js b/src/tanks/map/loc.js index edc840a..4178962 100644 --- a/src/tanks/map/loc.js +++ b/src/tanks/map/loc.js @@ -186,7 +186,7 @@ Loc.BoundingBox = new Y.Class('BoundingBox', Loc.Rect, { attr : Y.attr.methodize(), - moveTo : function moveTo(x,y){ + add : function add(x,y){ return new Loc.BoundingBox(x,y, x+this.width,y+this.height); }, diff --git a/src/tanks/map/pathmap.js b/src/tanks/map/pathmap.js index 9aeb818..6d43b88 100644 --- a/src/tanks/map/pathmap.js +++ b/src/tanks/map/pathmap.js @@ -38,84 +38,60 @@ PathMap = new Y.Class('PathMap', QuadTree, { return obj; }, - attemptMove : function attemptMove(obj, trj, to){ - var wall, blocker, what - , clamp = math.clamp - , bb = obj.boundingBox - , minW = 2, minH = 2 - , maxW = this.width-2, maxH = this.height-2 - , bw = bb.width, bh = bb.height - , x1 = to.x, y1 = to.y - , x2 = x1+bw, y2 = y1+bh + moveBlocked : function moveBlocked(agent, trj, to){ + var blockers, blocker, msg + , side = null + + , bb = agent.boundingBox + , bw = bb.width, bh = bb.height + , offX = agent.offsetX, offY = agent.offsetY + + , x1 = to.x+offX, y1 = to.y+offY + , x2 = x1+bw, y2 = y1+bh ; - // Check for collision with the walls to prevent teleporting units - // if (x1 < minW || x2 > maxW || y1 < minH || y2 > maxH){ - // blocker = this.game.level; - // what = 'LevelWall on the '; - // - // if (x1 < minW) { - // what = 'left'; - // wall = this.walls.left; - // to = trj.pointAtX(minW); - // - // } else if (x2 > maxW) { - // what = 'right'; - // wall = this.walls.right; - // to = trj.pointAtX(maxW-bw); - // - // } else if (y1 < minH) { - // what = 'top'; - // wall = this.walls.top; - // to = trj.pointAtY(minH); - // - // } else if (y2 > maxH) { - // what = 'bottom'; - // wall = this.walls.bottom; - // to = trj.pointAtY(maxH-bh); - // } - // - // what += ' at '+wall; - // return { 'ok':!wall, 'to':to, 'wall':wall, 'blocker':blocker, 'what':what }; - // } + blockers = this.get(x1,y1, x2,y2).remove(agent).end(); + blocker = blockers[0]; - // Check for pathmap collisions - var blockers = this.get(x1,y1, x2,y2).remove(obj); - if (blockers.size() > 1){ - console.log('multiple blockers! '+blockers._o.slice(0)); - return { 'ok':false, 'corner':true }; - } + // Not blocked + if (!blocker) return false; - blocker = blockers.shift(); - if ( blocker ) { - what = blocker+' on the '; + // Literal corner case :P + // XXX: needs better detection of corner + if (blockers.length > 1) { + msg = 'corner of '+blockers.slice(0); + to = trj.p1; + + // Normal reflection against one line + } else { + msg = blocker+' on the '; var B = blocker.boundingBox; if (bb.x2 <= B.x1 && x2 > B.x1) { - what += 'left'; - wall = B.sides.left; - to = trj.pointAtX(B.x1-bw); + msg += 'left'; + side = B.sides.left; + to = trj.pointAtX(B.x1-bw-offX-1); + } else if (bb.x1 >= B.x2 && x1 < B.x2) { - what += 'right'; - wall = B.sides.right; - to = trj.pointAtX(B.x2); + msg += 'right'; + side = B.sides.right; + to = trj.pointAtX(B.x2-offX+1); + } else if (bb.y2 <= B.y1 && y2 > B.y1) { - what += 'top'; - wall = B.sides.top; - to = trj.pointAtY(B.y1-bh); + msg += 'top'; + side = B.sides.top; + to = trj.pointAtY(B.y1-bh-offY-1); + } else if (bb.y1 >= B.y2 && y1 < B.y2) { - what += 'bottom'; - wall = B.sides.bottom; - to = trj.pointAtY(B.y2); + msg += 'bottom'; + side = B.sides.bottom; + to = trj.pointAtY(B.y2-offY+1); } + + msg += ' side'; } - // to.setXY( - // clamp(to.x, 2,maxW-2), - // clamp(to.y, 2,maxH-2) ); - - what += ' at '+wall; - return { 'ok':!wall, 'to':to, 'wall':wall, 'blocker':blocker, 'what':what }; + return { 'msg':msg, 'blockers':blockers, 'side':side, 'to':to }; }, diff --git a/src/tanks/map/trajectory.js b/src/tanks/map/trajectory.js index fae22dd..546354b 100644 --- a/src/tanks/map/trajectory.js +++ b/src/tanks/map/trajectory.js @@ -51,61 +51,30 @@ Trajectory = new Y.Class('Trajectory', math.Line, { ; do { - var t, to, ng, x1,y1, x2,y2, bs, blocker, blockers, what, wall; + var t, to, _to, ng + , test, blockers, side + ; t = Math.min(this.tBound, dt); dt -= t; this.elapsed += t; - var _to = to = this.parametric(this.elapsed); - x1 = to.x+offX; y1 = to.y+offY; - x2 = x1+bw; y2 = y1+bh; + _to = to = this.parametric(this.elapsed); + test = this.pathmap.moveBlocked(o, this, to); - bs = this.pathmap.get(x1,y1, x2,y2).remove(o).end(); - blocker = bs[0]; - - // Literal corner case :P - if (bs.length > 1) { - console.log('multiple blockers! '+bs.slice(0)); - what = 'corner of '+bs.slice(0); - to = loc; - ng = this.p1; // XXX: recalculate? - - // Normal reflection against one line - } else if ( blocker ) { - what = blocker+' on the '; + // Blocked! Reflect trajectory + if ( test ) { + to = test.to; + side = test.side; + blockers = test.blockers; - var B = blocker.boundingBox; - if (bb.x2 <= B.x1 && x2 > B.x1) { - what += 'left'; - wall = B.sides.left; - to = this.pointAtX(B.x1-bw-offX-1); - - } else if (bb.x1 >= B.x2 && x1 < B.x2) { - what += 'right'; - wall = B.sides.right; - to = this.pointAtX(B.x2-offX+1); - - } else if (bb.y2 <= B.y1 && y2 > B.y1) { - what += 'top'; - wall = B.sides.top; - to = this.pointAtY(B.y1-bh-offY-1); - - } else if (bb.y1 >= B.y2 && y1 < B.y2) { - what += 'bottom'; - wall = B.sides.bottom; - to = this.pointAtY(B.y2-offY+1); + if ( blockers.length > 1 ) { + to = loc; + ng = this.p1; // XXX: recalculate? + } else { + ng = math.reflect(this.p2, side); } - ng = math.reflect(this.p2, wall); - } - - // No collision: don't change trajectory - if (!ng) { - this.depth = 0; - - // New goal-point: change trajectory - } else { var og = this.p2; this.reset(to.x,to.y, ng.x,ng.y); @@ -113,7 +82,7 @@ Trajectory = new Y.Class('Trajectory', math.Line, { console.log([ '['+TICKS+':'+_dt+' ('+this.depth+')] '+this.owner+' reflected!', ' wanted: '+_to+' x ('+(_to.x+bw)+','+(_to.y+bh)+')', - ' blocker: '+what, + ' blocker: '+test.msg, ' old:', ' loc: '+bb.p1, ' goal: '+og, @@ -128,7 +97,6 @@ Trajectory = new Y.Class('Trajectory', math.Line, { ng = null; this.owner.render(this.game.level); - // this.owner.render(this.game.level).draw(); if (this.depth++ < 5) { // dt += t; // do this step over again @@ -139,6 +107,11 @@ Trajectory = new Y.Class('Trajectory', math.Line, { LBT.stop(); throw new Error('Reflection limit reached!'); } + + + // No collision: don't change trajectory + } else { + this.depth = 0; } } while (dt > 0); diff --git a/src/tanks/ui/player.js b/src/tanks/ui/player.js index 1f1d4f4..06c412f 100644 --- a/src/tanks/ui/player.js +++ b/src/tanks/ui/player.js @@ -4,7 +4,7 @@ Action = { moveDirFromKey : { 37: "left", 38: "up", 39: "right", 40: "down", - 65: "left", 87: "up", 83: "right", 68: "down" + 65: "left", 87: "up", 68: "right", 83: "down" } }; @@ -22,8 +22,9 @@ Player = new Y.Class('Player', { this.activeKeys = new Y.YArray(); - this.game = game; this.tank = tank; + this.game = game; + this.pathmap = game.pathmap; tank.act = this.act; // Override tank actions with player control tank.move = this.move; @@ -51,7 +52,9 @@ Player = new Y.Class('Player', { }, keydown : function keydown(evt){ - this.activeKeys.push(evt.which+''); + var k = evt.which+''; + if ( !this.activeKeys.has(k) ) + this.activeKeys.push(k); this.updateMeta(evt); }, @@ -93,8 +96,16 @@ Player = new Y.Class('Player', { move : function move(dir){ var tank = this.tank - , toLoc = tank.loc.moveByDir(dir, (tank.stats.move * SQUARETH)); - this.game.moveAgentTo(tank, toLoc.x, toLoc.y); + , toLoc = tank.loc.moveByDir(dir, (tank.stats.move * SQUARETH)) + + , x = toLoc.x, y = toLoc.y + , bb = tank.boundingBox.add(x,y) + + , blockers = this.pathmap.get(bb.x1,bb.y1, bb.x2,bb.y2).remove(tank) + ; + + if ( !blockers.size() ) + this.game.moveAgentTo(tank, x,y); } }); \ No newline at end of file