From: dsc Date: Tue, 9 Nov 2010 23:32:32 +0000 (-0800) Subject: Ah ha. Finally found the bug in the math test page's UI. X-Git-Url: http://git.less.ly:3516/?a=commitdiff_plain;h=7baadfca431bf2bf0f763389286c227d2f680772;p=tanks.git Ah ha. Finally found the bug in the math test page's UI. --- diff --git a/bin/deploy.sh b/bin/deploy.sh index 4a6a94f..5251783 100755 --- a/bin/deploy.sh +++ b/bin/deploy.sh @@ -4,31 +4,19 @@ function halp () { cat >&2 <<-HALP The Littlest Deployer of Battletanks -Usage: $( basename $0 ) [options] - -Deploys Simoon files. - -Options: - -h Displays this help. +Usage: $( basename $0 ) [exclude...] HALP } SHIFT=0 function incshift () { SHIFT=$(( $SHIFT + ${1:-1} )); } -function join () { seps="$IFS"; IFS="$1"; shift; echo "$*"; IFS="$seps"; } function fail () { echo "PREDICTABLE FAILURE. $1" >&2; exit 1; } for opt in $*; do - egrep -xq -e '--?h(e(lp?)?)?' && { halp; exit 0; } + echo $opt | egrep -xq -e '--?h(e(lp?)?)?' && { halp; exit 0; } done -# while getopts "b:" opt; do -# case $opt in -# b ) B=$OPTARG; incshift 2 ;; -# esac -# done -# shift $SHIFT - -rsync -Cavz --delete --exclude=tmp ./* less.ly:lessly/hacking/tanks/ - +EXCLUDE="--exclude=$(join ' --exclude=' 'tmp' $*)" +echo "rsync -Cavz --delete $EXCLUDE ./* less.ly:lessly/hacking/tanks/" +rsync -Cavz --delete $EXCLUDE ./* less.ly:lessly/hacking/tanks/ diff --git a/index.php b/index.php index 2a76380..330dc95 100644 --- a/index.php +++ b/index.php @@ -48,18 +48,20 @@ $scripts = array( "src/portal/math/vec.js", "src/portal/math/line.js", + "src/portal/util/loc.js", "src/portal/util/quadtree.js", "src/portal/util/rbtree.js", + "src/portal/util/eventloop.js", "src/portal/util/fps.js", "src/portal/util/cooldown.js", - "src/portal/util/loc.js", "src/tanks/globals.js", "src/tanks/util/calc.js", "src/tanks/util/grid.js", "src/tanks/util/pathmap.js", + "src/tanks/game/level.js", "src/tanks/game/game.js", "src/tanks/game/map.js", diff --git a/src/Y/y-array.js b/src/Y/y-array.js index de7a26c..7e9b140 100644 --- a/src/Y/y-array.js +++ b/src/Y/y-array.js @@ -27,8 +27,10 @@ function array_remove(v){ YArray.prototype.unique = array_unique; function array_unique(){ - // Executes in the context of the new array return this.filter(function(v, i){ + // Executes in the context of the new array, so + // `this.indexOf` is checking what we've already + // collected. return (this.indexOf(v) === -1); }); } diff --git a/src/portal/layer.js b/src/portal/layer.js index db019dd..b3a2f7f 100644 --- a/src/portal/layer.js +++ b/src/portal/layer.js @@ -321,6 +321,53 @@ Layer = new Y.Class('Layer', { + + + + + /// Iterators /// + + invoke : function invoke(name){ + var args = Y(arguments,1); + + this[name].apply(this, args); + this.children.invoke.apply(this.children, ['invoke', name].concat(args)); + return this; + }, + + setAll : function setAll(k,v){ + this[k] = v; + this.children.invoke('setAll', k,v); + return this; + }, + + /** + * Reduce "up", across this and parents, inner to outer: + * acc = fn.call(context || node, acc, node) + */ + reduceup : function reduceup(acc, fn, context){ + // if ( Y.isFunction(fn) ) + // acc = fn.call(context || this, acc, this); + // else + // acc = this[fn].call(context || this, acc, this); + acc = fn.call(context || this, acc, this); + return ( this.parent ? this.parent.reduceup(acc, fn, context) : acc ); + }, + + /** + * Reduce "down", across this and children, depth-first: + * acc = fn.call(context || node, acc, node) + */ + reduce : function reduce(acc, fn, context){ + acc = fn.call(context || this, acc, this); + return this.children.reduce(acc, fn, context); + }, + + + + + + /// Drawing Functions /// /** @@ -352,25 +399,23 @@ Layer = new Y.Class('Layer', { ctx.clearRect(-w,-h, 2*w,2*h); ctx.translate(neg.x, neg.y); - // ctx.rotate(this.absRotation); - // ctx.translate(-this.originX, -this.originY); - - // ctx.scale(this.absScaleX, this.absScaleY); - // Set context attributes + var alwaysClear = !!this.alwaysClear; CONTEXT_ATTRS.forEach(function(name){ - if (self[name] === undefined) - delete ctx[name]; - else + if (self[name] !== undefined) ctx[name] = self[name]; + else if (alwaysClear) + delete ctx[name]; }); + // ctx.rotate(this.absRotation); + // ctx.translate(-this.originX, -this.originY); + // ctx.scale(this.absScaleX, this.absScaleY); + return this; }, - /** - * To be implemented by subclasses. - */ + /** To be implemented by subclasses. */ drawShape : function drawShape(ctx){ return this; }, _closePath : function _closePath(ctx){ @@ -411,60 +456,13 @@ Layer = new Y.Class('Layer', { - - - - /// Iterators /// - - invoke : function invoke(name){ - var args = Y(arguments,1); - - this[name].apply(this, args); - this.children.invoke.apply(this.children, ['invoke', name].concat(args)); - return this; - }, - - setAll : function setAll(k,v){ - this[k] = v; - this.children.invoke('setAll', k,v); - return this; - }, - - /** - * Reduce "up", across this and parents, inner to outer: - * acc = fn.call(context || node, acc, node) - */ - reduceup : function reduceup(acc, fn, context){ - // if ( Y.isFunction(fn) ) - // acc = fn.call(context || this, acc, this); - // else - // acc = this[fn].call(context || this, acc, this); - acc = fn.call(context || this, acc, this); - return ( this.parent ? this.parent.reduceup(acc, fn, context) : acc ); - }, - - /** - * Reduce "down", across this and children, depth-first: - * acc = fn.call(context || node, acc, node) - */ - reduce : function reduce(acc, fn, context){ - acc = fn.call(context || this, acc, this); - return this.children.reduce(acc, fn, context); - }, - - - /// Misc /// - toString : function toString(){ var pos = (this.layer ? this.position() : {top:NaN, left:NaN}); return this.className+'['+pos.left+','+pos.top+']( children='+this.children.size()+' )'; } }); - -// Helpers for building the class - function makeDelegate(name, dirties, prop){ prop = prop || 'layer'; return function(){ @@ -489,8 +487,4 @@ $(function(){ .appendTo('head'); }); - - - - })(jQuery); diff --git a/src/portal/math/line.js b/src/portal/math/line.js index b774a96..abe1250 100644 --- a/src/portal/math/line.js +++ b/src/portal/math/line.js @@ -12,8 +12,8 @@ COS_HALF_PI = Math.cos(HALF_PI); math.Line = new Y.Class('Line', math.Vec, { init : function init(x1,y1, x2,y2, tdist){ - this.x1 = x1; this.y1 = y1; this.p1 = new math.Vec(x1,y1); - this.x2 = x2; this.y2 = y2; this.p2 = new math.Vec(x2,y2); + this.x1 = x1; this.y1 = y1; + this.x2 = x2; this.y2 = y2; var xdelta = x2-x1, ydelta = y2-y1 , m = this.slope = ydelta/xdelta @@ -22,9 +22,13 @@ math.Line = new Y.Class('Line', math.Vec, { ; 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); }, diff --git a/src/portal/math/math.js b/src/portal/math/math.js index 99b71fd..bb8a8a1 100644 --- a/src/portal/math/math.js +++ b/src/portal/math/math.js @@ -10,7 +10,7 @@ math = { reflect : function reflect(v, line){ var dot = math.Vec.dot , basev = math.Vec.difference(v, line.p1); - return line.clone() + return new math.Vec(line.x, line.y) .scale(2 * dot(basev,line) / dot(line,line)) .subtract(basev) .add(line.p1); diff --git a/src/portal/math/vec.js b/src/portal/math/vec.js index 995f1c1..33cf4f2 100644 --- a/src/portal/math/vec.js +++ b/src/portal/math/vec.js @@ -1,7 +1,7 @@ /** * A 2-dimensional vector. */ -math.Vec = new Y.Class('Vec', { +math.Vec = new Y.Class('Vec', [], { init : function init(x, y){ if ( Array.isArray(x) ) { @@ -9,8 +9,9 @@ math.Vec = new Y.Class('Vec', { x = x[0]; } - this.x = x; - this.y = y; + this.length = 2; + this.x = this[0] = x; + this.y = this[1] = y; }, equals : function equals(b){ @@ -62,7 +63,7 @@ math.Vec = new Y.Class('Vec', { }, toString : function toString(){ - return 'Vec('+this.x.toFixed(3)+','+this.y.toFixed(3)+')'; + return '['+this.x.toFixed(3)+', '+this.y.toFixed(3)+']'; } }); diff --git a/src/portal/shape.js b/src/portal/shape.js index 1f1b109..a31817b 100644 --- a/src/portal/shape.js +++ b/src/portal/shape.js @@ -1,5 +1,8 @@ Shape = new Y.Class('Shape', Layer, { _cssClasses : 'portal layer shape', + fillStyle : 'rgba(231,48,117, 1)', + strokeStyle : 'transparent', + lineWidth : 0, _calcDimension : function _calcDimension(which, values){ values.unshift(0); @@ -52,6 +55,7 @@ Circle = new Y.Class('Circle', Shape, { var r = this.radius; ctx.arc(0,0, r, 0, Math.PI*2, false); ctx.fill(); + ctx.stroke(); } }); @@ -125,9 +129,10 @@ Line = new Y.Class('Line', Shape, { }, fixSize : function fixSize(){ - var p = this.parent - , w = this.canvasWidth, h = this.canvasHeight - , pw = p.canvasWidth, ph = p.canvasHeight ; + var p = this.parent + , pw = p.canvasWidth, ph = p.canvasHeight + , w = this.canvasWidth, h = this.canvasHeight + ; if (w !== pw) { this.width(pw); @@ -144,7 +149,8 @@ Line = new Y.Class('Line', Shape, { this.fixSize(); var x1,y1, x2,y2 , line = this.line, p1 = line.p1, p2 = line.p2 - , w = this.canvasWidth, h = this.canvasHeight; + , w = this.canvasWidth, h = this.canvasHeight + ; x1 = 0; y1 = line.calcY(x1); if (y1 < 0) { @@ -162,8 +168,8 @@ Line = new Y.Class('Line', Shape, { ctx.closePath(); // Show definition points - this.point(p1.x,p1.y, '#4596FF'); - this.point(p2.x,p2.y, '#4596FF'); + this.point(p1.x,p1.y, 'rgba(69,150,255,0.4)'); + this.point(p2.x,p2.y, 'rgba(69,150,255,0.4)'); }, diff --git a/src/portal/util/loc.js b/src/portal/util/loc.js index d170dc8..659a6d8 100644 --- a/src/portal/util/loc.js +++ b/src/portal/util/loc.js @@ -1,5 +1,5 @@ // [x,y] -Loc = new Y.Class('Loc', [], { +Loc = new Y.Class('Loc', math.Vec, { init : function init(x, y){ if ( Array.isArray(x) ) { @@ -26,10 +26,6 @@ Loc = new Y.Class('Loc', [], { }, attr : Y.attr.methodize(), - equals : function equals(loc){ - return (this.x === loc.x) && (this.y === loc.y); - }, - clone : function clone(){ return new Loc(this.x, this.y); }, @@ -67,8 +63,8 @@ Loc = new Y.Class('Loc', [], { toString : function toString(){ var x = this.x, y = this.y; - x = Y.isNumber(x) ? Math.round(x,2) : x; - y = Y.isNumber(y) ? Math.round(y,2) : y; + x = Y.isNumber(x) ? x.toFixed(2) : x; + y = Y.isNumber(y) ? y.toFixed(2) : y; return '('+x+','+y+')'; } @@ -106,23 +102,25 @@ Y(Loc).extend({ Loc.Rect = new Y.Class('Rect', [], { init : function init(x1,y1, x2,y2){ if (x1 instanceof Loc && y1 instanceof Loc) { - var top = x1, - bottom = y1; - } else { - var top = new Loc(x1,y1), - bottom = new Loc(x2,y2); + y2 = y1.y; x2 = y1.x; + y1 = x1.y; x1 = x1.x; } - this.left = this.top = top; - this.right = this.bottom = bottom; this.length = 4; - x1 = this.x1 = this[0] = this.x = top.x; - y1 = this.y1 = this[1] = this.y = top.y; - x2 = this.x2 = this[2] = bottom.x; - y2 = this.y2 = this[3] = bottom.y; + this.x1 = this[0] = this.x = x1; + this.y1 = this[1] = this.y = y1; + this.x2 = this[2] = x2; + this.y2 = this[3] = y2; this.width = x2 - x1; this.height = y2 - y1; + + this.sides = { + top : new math.Line(x1,y1, x2,y1), + bottom : new math.Line(x1,y2, x2,y2), + left : new math.Line(x1,y1, x1,y2), + right : new math.Line(x2,y1, x2,y2) + }; }, set : function set(k, v, def){ @@ -141,31 +139,6 @@ Loc.Rect = new Y.Class('Rect', [], { attr : Y.attr.methodize(), - top : function top(x1,y1){ - if ( x1 !== undefined && y1 !== undefined ) - return new Loc(this.x1, this.y1); - else - return this.attr({ 'x1':x1, 'y1': y1 }); - }, - bottom : function bottom(x2,y2){ - if ( x2 !== undefined && y2 !== undefined ) - return new Loc(this.x2, this.y2); - else - return this.attr({ 'x2':x2, 'y2': y2 }); - }, - left : function left(x1,y1){ - if ( x1 !== undefined && y1 !== undefined ) - return new Loc(this.x1, this.y1); - else - return this.attr({ 'x1':x1, 'y1': y1 }); - }, - right : function right(x2,y2){ - if ( x2 !== undefined && y2 !== undefined ) - return new Loc(this.x2, this.y2); - else - return this.attr({ 'x2':x2, 'y2': y2 }); - }, - moveTo : function moveTo(x,y){ return new Loc.Rect(x,y, x+this.width,y+this.height); }, diff --git a/src/tanks/game/level.js b/src/tanks/game/level.js new file mode 100644 index 0000000..0105e5c --- /dev/null +++ b/src/tanks/game/level.js @@ -0,0 +1,35 @@ +Wall = new Y.Class('Wall', Rect, { + fillStyle : 'rgba(255,255,255, 0.25)', + blocking : true, + + init : function init(x,y, w,h){ + Rect.init.call(this, w,h); + + 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); + }, + + drawShape : Y.op.nop + +}); \ No newline at end of file diff --git a/src/tanks/game/map.js b/src/tanks/game/map.js index 3abf13c..a6dc4f7 100644 --- a/src/tanks/game/map.js +++ b/src/tanks/game/map.js @@ -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 = + var root = + this.root = + this.grid = new Grid(COLUMNS,ROWS, CELL_SIZE) .appendTo(this.viewport); this.level = - new Layer() - .width( root.layerWidth ) - .height( root.layerHeight ) + new Level(this, root.layerWidth, root.layerHeight ) .appendTo(this.root); - this.byId = {}; - this.units = new Y.YArray(); - this.bullets = new Y.YArray(); - this.blockers = new Y.YArray(); - // Agent.addEventListener('create', function(evt){ // self.addAgent(evt.instance); // }); @@ -156,5 +156,3 @@ Y(Game.prototype).extend({ } }); - - diff --git a/src/tanks/lttl.js b/src/tanks/lttl.js index 6cf21de..2ce4ee3 100644 --- a/src/tanks/lttl.js +++ b/src/tanks/lttl.js @@ -3,10 +3,24 @@ jQuery(function($){ v = $('#viewport'); LBT = new Game(); +var sq = REF_SIZE +, wall = new Wall(6*sq,1*sq, 1*sq,4*sq); +LBT.level.append(wall); + + 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 ); + +B = new Bullet(T, 25,25); +LBT.addUnit(B); +B.render( LBT.level ); -B = new Bullet(T, 3*REF_SIZE,3*REF_SIZE); +B = new Bullet(T, 1*REF_SIZE,3*REF_SIZE); LBT.addUnit(B); B.render( LBT.level ); diff --git a/src/tanks/thing/bullet.js b/src/tanks/thing/bullet.js index 4855582..af51a27 100644 --- a/src/tanks/thing/bullet.js +++ b/src/tanks/thing/bullet.js @@ -41,29 +41,34 @@ Bullet = new Y.Class('Bullet', Thing, { move : function move(){ var p, wall, p2 = this.trajectory.p2 - , level = this.game.grid, walls = level.walls + , level = this.game.level, walls = level.walls , w = level.layerWidth, h = level.layerHeight , trj = this.trajectory - , to = this.trajectory.pcalc(this.elapsed); + , to = this.trajectory.pcalc(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); - } + // 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); + // } + if (!test.ok) { + to = test.to; + wall = test.line; p = math.reflect(p2, wall.tangent(to)); @@ -99,12 +104,16 @@ 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.5)') + .attr('strokeStyle', 'rgba(255,246,174, 0.05)') .appendTo( parent ); - this.shape = new Circle(2.5) + this.shape = new Circle(3) .position(this.loc.x, this.loc.y) - .attr('fillStyle', '#FFF6AE') + .attr({ + 'fillStyle' : '#EC5B38', + 'strokeStyle' : 'transparent', + 'lineWidth' : 0 + }) .appendTo( parent ); return this; diff --git a/src/tanks/util/grid.js b/src/tanks/util/grid.js index c3b6862..22cf5c1 100644 --- a/src/tanks/util/grid.js +++ b/src/tanks/util/grid.js @@ -9,15 +9,6 @@ Grid = new Y.Class('Grid', Rect, { this.rows = rows; this.size = size; Rect.init.call(this, cols*size, rows*size); - - var w = this.canvasWidth - , h = this.canvasHeight; - 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) - }; }, drawShape : function drawShape(ctx){ diff --git a/src/tanks/util/pathmap.js b/src/tanks/util/pathmap.js index 9e3726f..5f5f8df 100644 --- a/src/tanks/util/pathmap.js +++ b/src/tanks/util/pathmap.js @@ -1,5 +1,72 @@ PathMap = new Y.Class('PathMap', QuadTree, { + init : function init(game, x1,y1, x2,y2, capacity) { + QuadTree.init.call(this, x1,y1, x2,y2, capacity); + + 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) + }; + + }, + + + attemptMove : function attemptMove(obj, trj, to){ + var line, bb = obj.boundingBox + , 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); + } + } + + var blocker = this.get(x1,y1, x2,y2).remove(obj).shift(); + if ( blocker ) { + 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); + } + } + + return { 'ok':!line, 'to':to, 'line':line }; + }, + + + + overlay : function overlay(gridEl){ var w = this.width *SCALE , h = this.height *SCALE diff --git a/test/math/index.php b/test/math/index.php index 3fc9c2e..da6937a 100644 --- a/test/math/index.php +++ b/test/math/index.php @@ -2,8 +2,10 @@ math - - +document.write(''); +?> + @@ -33,26 +36,25 @@ $scripts = array( // "http://static.ukijs.org/pkg/0.3.8/uki-more.js", "src/lessly/future.js", - "src/Y/y.js.php", "src/Y/modules/y.event.js", "src/evt/evt.class.js", + "src/portal/math/math.js", + "src/portal/math/vec.js", + "src/portal/math/line.js", + "src/portal/util/loc.js", "src/portal/layer.js", "src/portal/shape.js", "src/tanks/util/grid.js", - "src/portal/math/math.js", - "src/portal/math/vec.js", - "src/portal/math/line.js", - "test/math/math.test.js" ); function js($src) { - echo " \n"; + echo " \n"; } foreach ($scripts as $s) js($s); diff --git a/test/math/math.test.js b/test/math/math.test.js index 0fbf015..5fb18eb 100644 --- a/test/math/math.test.js +++ b/test/math/math.test.js @@ -7,10 +7,10 @@ plot = $('#plot'); w = plot.width(); w2 = w/2; h = plot.height(); h2 = h/2; -W = w/PPU; W2 = W/2; -H = h/PPU; H2 = H/2; +COLS = w/PPU; COLS2 = COLS/2; +ROWS = h/PPU; H2 = ROWS/2; -grid = new Grid( W, H, PPU ).appendTo(plot); +grid = new Grid( COLS, ROWS, PPU ).appendTo(plot); grid.lineWidth = 1.0; grid.strokeStyle = '#E0E0E0'; //'#EEEEEE'; // grid.draw(); @@ -20,7 +20,6 @@ ctx = grid.ctx; drawLine(-w,-h2, w,-h2, '#CCCCCC', 2.0); drawLine(w2,-h, w2,h, '#CCCCCC', 2.0); - P = new Layer() .width(w).height(h) .appendTo(grid); @@ -31,12 +30,7 @@ ctx.scale(PPU, PPU); points = Y([]); line = mkLine(0,0, 2.3125,1); -addPoint(-5,2); - -drawAngle(line.theta); - -tanLine = line.tangent(line.p2); -drawLine(-W, tanLine.calcY(-W), W, tanLine.calcY(W), 'rgba(226,127,8, 0.5)'); +rv = addPoint(-5,2); dragging = false; P.layer.bind('click', function(evt){ @@ -69,15 +63,21 @@ function mvLine(pn, x,y){ , y2 = (pn === 2 ? y : line.y2) ; mkLine(x1,y1, x2,y2); - redraw(); } function redraw(color){ color = color || 'rgba(231,48,117, 0.5)'; var pts = points.clone(); clear(); - drawLine(-W, line.calcY(-W), W, line.calcY(W), color); + + // drawAngle(line.theta); + drawLine(-COLS, line.calcY(-COLS), COLS, line.calcY(COLS), color); + drawLine(-COLS, tanLine.calcY(-COLS), COLS, tanLine.calcY(COLS), 'rgba(226,127,8, 0.5)'); + P.append(p1, p2); + bindPoint(p1, 1); + bindPoint(p2, 2); + pts.forEach(addPoint); } @@ -100,6 +100,7 @@ function addPoint(x,y){ var rv = math.reflect(c.vec,line) , rc = c.reflected = drawPoint(rv, null, '#F25522'); points.push(c); + return rv; } function mkLine(x1,y1, x2,y2, color, pcolor){ @@ -108,19 +109,25 @@ function mkLine(x1,y1, x2,y2, color, pcolor){ color = color || 'rgba(231,48,117, 0.5)'; pcolor = pcolor || 'rgba(69,150,255, 1)'; - var line = new math.Line(x1,y1, x2,y2); - drawLine(-W, line.calcY(-W), W, line.calcY(W), color); + + line = new math.Line(x1,y1, x2,y2); + tanLine = line.tangent(line.p2); + + // drawLine(-COLS, line.calcY(-COLS), COLS, line.calcY(COLS), color); p1 = drawPoint(line.x1, line.y1, pcolor); - p1.layer.bind('mousedown', function(){ + p2 = drawPoint(line.x2, line.y2, pcolor); + redraw(); + + return line; +} + +function bindPoint(pt, pn){ + pt.layer.bind('mousedown', function(){ dragging = true; function onMove(evt){ var r = 3.75, v = convertLoc(evt); - mvLine(1, v.x,v.y); - - // _p1.appendTo(P); - // p1.position(w2-r + v.x*PPU, h2-r - v.y*PPU) - + mvLine(pn, v.x,v.y); return false; } P.layer.bind('mousemove', onMove); @@ -128,18 +135,15 @@ function mkLine(x1,y1, x2,y2, color, pcolor){ dragging = false; P.layer.unbind('mousemove', onMove); P.layer.unbind('mouseup', arguments.callee); - // _p1.remove(); return false; }); return false; }); - - p2 = drawPoint(line.x2, line.y2, pcolor); - return (window.line = line); + return pt; } function drawLine(x1,y1, x2,y2, color, width){ - try { + // try { ctx.beginPath(); ctx.lineWidth = width || PX; ctx.strokeStyle = color || '#000000'; @@ -147,9 +151,9 @@ function drawLine(x1,y1, x2,y2, color, width){ ctx.lineTo(x2, -y2); ctx.stroke(); ctx.closePath(); - } catch (e) { - console.log('drawLine error:', e, '(',x1,y1,')', '(',x2,y2,')'); - } + // } catch (e) { + // console.log('drawLine error:', e, '(',x1,y1,')', '(',x2,y2,')'); + // } } function drawPoint(x,y, color, r){ @@ -162,10 +166,14 @@ function drawPoint(x,y, color, r){ var v = new math.Vec(x,y); var c = new Circle(r) - .position(w2-r + x*PPU, h2-r - y*PPU) - .attr({ 'fillStyle': color || 'rgba(0,0,0,0.5)' }) + .position(w2 + x*PPU, h2 - y*PPU) + .attr({ + 'strokeStyle' : '', + 'fillStyle' : color || 'rgba(0,0,0,0.5)' + }) .appendTo(P) .draw(); + c.vec = v; c.layer.attr('title', '('+x+','+y+')'); return c; @@ -174,6 +182,7 @@ function drawPoint(x,y, color, r){ function drawAngle(theta, radius){ radius = radius || 3; ctx.beginPath(); + ctx.strokeStyle = ''; ctx.fillStyle = 'rgba(36,71,146, 0.25)'; ctx.moveTo(0,0); ctx.lineTo(radius,0);