"src/portal/layer.js",
"src/portal/shape.js",
+
+ "src/portal/math/math.js",
+ "src/portal/math/vec.js",
+ "src/portal/math/line.js",
+
"src/portal/util/quadtree.js",
"src/portal/util/rbtree.js",
"src/portal/util/eventloop.js",
// Generic Collection Functions
-function notSelfOrWrapped(fn){
+function notWrapped(fn){
var self = arguments.callee.caller;
return fn && fn !== self && fn.__wraps__ !== self;
}
return acc;
// fn = Function.toFunction(fn);
- if ( notSelfOrWrapped(o.reduce) )
+ if ( notWrapped(o.reduce) )
return o.reduce.apply(o, [fn, acc, cxt]);
cxt = cxt || o;
return acc;
}
-function set(o, key, value, def){
- if ( o && notSelfOrWrapped(o.set) )
- return o.set.apply(o, slice.call(arguments,1));
+function set(o, key, value, def){
if ( o && key !== undefined )
o[key] = (value !== undefined ? value : def);
-
return o;
}
-function attr(o, key, value, def){
- if ( o && notSelfOrWrapped(o.attr) )
- return o.attr.apply(o, slice.call(arguments,1));
-
+function dset(o, key, value, def){
+ if ( o && notWrapped(o.set) )
+ return o.set.apply(o, slice.call(arguments,1));
+ else
+ return set(o, key, value, def);
+}
+
+function attr(o,key,value,def){
if ( !o || key === undefined ) return o;
- if ( isPlainObject(key) )
+ if ( Y.isPlainObject(key) )
return extend(o, key);
if ( value !== undefined || def !== undefined ){
- return set(o, key, value, def);
+ return dset(o, key, value, def);
} else
return o[key];
}
+function dattr(o, key, value, def){
+ if ( o && notWrapped(o.attr) )
+ return o.attr.apply(o, slice.call(arguments,1));
+ else
+ return attr(o, key, value, def);
+}
+
function extend( A, B ){
return slice.call(arguments,1).reduce(extend._extendall, A);
}
return reduce(donor, extend._set, A);
};
extend._set = function _set(o, v, k){
- return attr(o, k, v, o[k]);
+ return dattr(o, k, v, o[k]);
};
Y.reduce = reduce;
-Y.set = set;
-Y.attr = attr;
+Y.set = dset;
+Y.attr = dattr;
Y.extend = extend;
Y.isFunction = isFunction;
zrshift: function(x,y){ return x >>> y; },
// values
- nop: function(){},
+ nop: function(x){},
I: function(x){ return x; },
K: function(k){ return function(){ return k; }; },
val: function(def,o){ return o !== undefined ? o : def; },
ok: function(o){ return o !== undefined && o !== null; },
- // values & accessors
- has: function(k,o){ return k in o; },
- get: function(k,o){ return o[k] },
- getdef: function(def,k,o){ return (k in o ? o[k] : def); },
- set: function(o,k,v){ if (o && k !== undefined) o[k] = v; return o; },
+ // reduce-ordered values & accessors
+ khas: function(k,o){ return k in o; },
+ kget: function(k,o){ return o[k] },
+ defkget: function(def,k,o){ return (k in o ? o[k] : def); },
+ vkset: function(o,v,k){ if (o && k !== undefined) o[k] = v; return o; },
+
+ // curry-ordered values & accessors
+ has: function(o,k){ return k in o; },
+ get: function(o,k){ return o[k] },
+ getdef: function(o,k,def){ return (k in o ? o[k] : def); },
+ set: set,
+ attr: attr,
method: function(name){
var args = Y(arguments,1);
return function(obj){
(function($, undefined){
+var CONTEXT_ATTRS = Y([
+ 'globalAlpha', 'globalCompositeOperation',
+ 'strokeStyle', 'fillStyle',
+ 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit',
+ 'shadowOffsetX', 'shadowOffsetY', 'shadowBlur', 'shadowColor'
+]);
+
+
+
Layer = new Y.Class('Layer', {
_cssClasses : 'portal layer',
/// Attributes ///
+
+ attr : function attr(key, value, def){
+ if (!key) return this;
+
+ if ( Y.isPlainObject(key) ) {
+ for (var k in key)
+ this.attr(k, key[k]);
+ return this;
+
+ // } else if ( CONTEXT_ATTRS.has(key) ) {
+ // var r = Y.attr(this.ctx, key, value, def);
+ //
+ // if (r === this.ctx) {
+ // // This implies we set a property
+ // this.dirty = true;
+ // return this;
+ // } else
+ // return r;
+ //
+ } else
+ return Y.op.attr(this, key, value, def);
+ },
+
/**
* Changes the layer's width and then updates the canvas.
*/
/// Drawing Functions ///
- // for debugging
- point : function point(x,y, color){
- var ctx = this.ctx;
- this._openPath(ctx);
-
- var r = 2;
- ctx.arc(x+r,y+r, r, 0, Math.PI*2, false);
- ctx.fillStyle = color || '#FFFFFF';
- ctx.fill();
-
- this._closePath(ctx);
- return this;
- },
/**
* @param {CanvasDrawingContext2D} [ctx=this.ctx] Forces context to use rather than the layer's own.
* @param {Boolean} [force=false] Forces redraw.
},
_openPath : function _openPath(ctx){
- var w = this.canvasWidth
+ var self = this
+ , w = this.canvasWidth
, h = this.canvasHeight
, neg = this.negBleed
;
// ctx.scale(this.absScaleX, this.absScaleY);
+ // Set context attributes
+ CONTEXT_ATTRS.forEach(function(name){
+ if (self[name] === undefined)
+ delete ctx[name];
+ else
+ ctx[name] = self[name];
+ });
+
return this;
},
return this;
},
+ // for debugging
+ point : function point(x,y, color){
+ var ctx = this.ctx;
+ // this._openPath(ctx);
+
+ var r = 2;
+ ctx.beginPath();
+ ctx.arc(x,y, r, 0, Math.PI*2, false);
+ ctx.fillStyle = color || '#FFFFFF';
+ ctx.fill();
+ ctx.closePath();
+
+ // this._closePath(ctx);
+ return this;
+ },
+
$('<style />')
.text([
'.portal.layer { position:absolute; z-index:1; top:0; left:0; line-height:0; }',
+ // '.portal.layer { outline:1px solid #000000; }',
'.portal.layer canvas { z-index:0; }'
].join('\n'))
.appendTo('head');
+(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 init(x1,y1, x2,y2, t){
+ 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);
, xi = this.xint = -y1/m + x1
;
math.Vec.init.call(this, xdelta, ydelta);
- this.setT(t);
+
+ 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);
},
- setT : function setT(t){
- this.t = 1/(t || 1);
- this.pa = this.t*this.x;
- this.pb = this.t*this.y;
+ 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;
},
pcalc : function parametric(t){
- return new math.Vec( this.x1 + this.pa*t ,
- this.y1 + this.pb*t );
+ return new math.Vec( this.x1 + t*this.pa ,
+ this.y1 + t*this.pb );
+ },
+
+ pointX : function pointX(x){
+ return new math.Vec(x, this.calcY(x));
+ },
+
+ pointY : function pointY(y){
+ return new math.Vec(this.calcX(y), y);
},
calcY : function calcY(x){
},
base : function base(){
- return new math.Line(0,0, this.x,this.y);
+ if (!this._base)
+ this._base = new math.Line(0,0, this.x,this.y);
+ return this._base;
+ },
+
+ tangent : function tangent(at){
+ var _theta = Math.PI/2 + this.theta
+ , x = (at.x !== this.x1 ? this.x1 : this.x2) - at.x
+ , y = (at.y !== this.y1 ? this.y1 : this.y2) - at.y
+ , _x = at.x + y
+ , _y = at.y - x
+ return new math.Line(at.x,at.y, _x,_y, this.tdist);
},
toString : function toString(){
- return 'Line('+this.x1+','+this.y1+', '+this.x2+','+this.y2+', slope='+this.slope+')';
+ return 'Line('+this.x1.toFixed(2)+','+this.y1.toFixed(2)+', '+
+ this.x2.toFixed(2)+','+this.y2.toFixed(2)+', '+
+ 'slope='+this.slope.toFixed(3)+')';
}
-});
\ No newline at end of file
+});
+
+})();
},
toString : function toString(){
- return 'Vec('+this.x+','+this.y+')';
+ return 'Vec('+this.x.toFixed(3)+','+this.y.toFixed(3)+')';
}
});
-CONTEXT_ATTRS = Y([
- 'globalAlpha', 'globalCompositeOperation', 'strokeStyle', 'fillStyle',
- 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit', 'shadowOffsetX',
- 'shadowOffsetY', 'shadowBlur', 'shadowColor'
-]);
-
-
Shape = new Y.Class('Shape', Layer, {
_cssClasses : 'portal layer shape',
- attr : function attr(key, value, def){
- if (!key) return this;
-
- if ( Y.isPlainObject(key) ) {
- for (var k in key)
- this.attr(k, key[k]);
- return this;
-
- } else if ( CONTEXT_ATTRS.has(key) ) {
- var r = Y.attr(this.ctx, key, value, def);
-
- if (r === this.ctx) {
- // This implies we set a property
- this.dirty = true;
- return this;
- } else
- return r;
-
- } else
- return Y.attr(this, key, value, def);
- },
-
_calcDimension : function _calcDimension(which, values){
values.unshift(0);
var self = this
Rect = new Y.Class('Rect', Shape, {
_cssClasses : 'portal layer shape rect',
- init : function init(w, h){
+ init : function initRect(w, h){
Layer.init.call(this);
this.width(w)
- .height(h)
- .origin(w/2, h/2);
+ .height(h);
+ // .origin(w/2, h/2);
},
drawShape : function drawShape(ctx){
Circle = new Y.Class('Circle', Shape, {
_cssClasses : 'portal layer shape circle',
- init : function init(radius){
+ init : function initCircle(radius){
Layer.init.call(this);
var d = radius * 2;
- this.radius = radius;
- this.width(d).height(d)
- .origin(radius,radius);
+ this.radius = this.negBleed.x = this.negBleed.y = radius;
+ this.width(d).height(d);
+ // .origin(radius,radius);
},
drawShape : function drawShape(ctx){
var r = this.radius;
- ctx.arc(r,r, r, 0, Math.PI*2, false);
+ ctx.arc(0,0, r, 0, Math.PI*2, false);
ctx.fill();
}
* together to make the numbered coordinates.
* x0 and y0 will always be 0.
*/
- init : function init(xs, ys){
+ init : function initPolygon(xs, ys){
Layer.init.call(this);
var xs = this._calcDimension('x', xs)
this.points = Y(xs).zip(ys).map(Loc.instantiate, Loc);
this.width(w)
- .height(h)
- .origin(w/2, h/2);
+ .height(h);
+ // .origin(w/2, h/2);
},
drawShape : function drawShape(ctx){
});
// Er, this won't do. It's only a line-segment.
-Line = new Y.Class('Line', Polygon, {
+Line = new Y.Class('Line', Shape, {
+ _cssClasses : 'portal layer shape line',
+
+ init : function initLine(x,y){
+ Layer.init.call(this);
+
+ this.sublayer = jQuery('<div style="overflow:hidden" />')
+ .append(this.canvas)
+ .appendTo(this.layer);
+
+ this.x2 = x; this.y2 = y;
+ this.position(0,0);
+ },
+
+ position : function position(left, top){
+ if (top === undefined && left === undefined)
+ return this.line.p1;
+
+ if (top && Y.isPlainObject(top))
+ var pos = top;
+ else
+ var pos = { 'top': top, 'left':left };
+
+ this.x1 = pos.left; this.x2 += this.x1;
+ this.y1 = pos.top; this.y2 += this.y1;
+ this.line = new math.Line(this.x1,this.y1, this.x2,this.y2);
+
+ return this;
+ },
- init : function init(x,y){
- Polygon.init.call(this, [x], [y]);
+ appendTo : function appendTo(parent){
+ var r = Layer.prototype.appendTo.call(this, parent);
+ this.fixSize();
+ return r;
+ },
+
+ fixSize : function fixSize(){
+ var p = this.parent
+ , w = this.canvasWidth, h = this.canvasHeight
+ , pw = p.canvasWidth, ph = p.canvasHeight ;
+
+ if (w !== pw) {
+ this.width(pw);
+ this.sublayer.width(pw);
+ }
+ if (h !== ph) {
+ this.height(ph);
+ this.sublayer.height(ph);
+ }
+ return this;
+ },
+
+ drawShape : function drawShape(ctx){
+ this.fixSize();
+ var x1,y1, x2,y2
+ , line = this.line, p1 = line.p1, p2 = line.p2
+ , w = this.canvasWidth, h = this.canvasHeight;
+
+ x1 = 0; y1 = line.calcY(x1);
+ if (y1 < 0) {
+ y1 = 0; x1 = line.calcX(y1);
+ }
+
+ x2 = w; y2 = line.calcY(x2);
+ if (y2 > h) {
+ y2 = h; x2 = line.calcX(y2);
+ }
+
+ ctx.moveTo(x1,y1);
+ ctx.lineTo(x2,y2);
+ ctx.stroke();
+ ctx.closePath();
+
+ // Show definition points
+ this.point(p1.x,p1.y, '#4596FF');
+ this.point(p2.x,p2.y, '#4596FF');
+ },
+
+
+ toString : function toString(){
+ return this.className+'['+this.x1+','+this.y1+', '+this.x2+','+this.y2+']';
}
+
});
Line.fromPoints = function fromPoints(x1,y1, x2,y2){
return new Line(x2-x1, y2-y1).position(x1,y1);
Triangle = new Y.Class('Triangle', Polygon, {
_cssClasses : 'portal layer shape polygon triangle',
- init : function init(x1,y1, x2,y2){
+ init : function initTriangle(x1,y1, x2,y2){
Polygon.init.call(this, [x1,x2], [y1,y2]);
},
Quad = new Y.Class('Quad', Polygon, {
_cssClasses : 'portal layer shape polygon quad',
- init : function init(x1,y1, x2,y2, x3,y3){
+ init : function initQuad(x1,y1, x2,y2, x3,y3){
Polygon.init.call(this, [x1,x2,x3], [y1,y2,y3]);
}
this.timer = setTimeout(this.tick, tickInt);
},
- tick : function tick(lastTick){
- lastTick = lastTick || this.now;
+ tick : function tick(){
+ var lastTick = this.now;
this.now = new Date().getTime();
this.elapsed = this.now - lastTick;
this.maxBuffer = Math.floor(w / 3);
},
- tickTime : function tickTime(lastTick){
+ tickTime : function tickTime(){
var loop = this.loop
, buf = this.buffer
;
- this.loopTick.call(loop, lastTick);
+ this.loopTick.call(loop);
this.ticks++;
this.tickSum += loop.tFrame;
addUnit : function addUnit(unit, col,row){
unit.game = this;
- // Center unit in square
- var sqX = (col || 0) * REF_SIZE
- , sqY = (row || 0) * REF_SIZE
- , x = sqX + (REF_SIZE-unit.width)/2
- , y = sqY + (REF_SIZE-unit.height)/2 ;
-
- unit.setLocation(x,y);
- unit.render( this.level );
+ if (col !== undefined) {
+ // Center unit in square
+ var sqX = (col || 0) * REF_SIZE
+ , sqY = (row || 0) * REF_SIZE
+ , x = sqX + (REF_SIZE-unit.width) /2
+ , y = sqY + (REF_SIZE-unit.height)/2 ;
+
+ unit.setLocation(x,y);
+ unit.render( this.level );
+ }
this.addBlocker(unit);
var r = TWO_PI * (TICKS % 30)/30;
// console.log('tank.shape.rotate(', r, ')');
- t.shape.rotate(r);
+ // t.shape.rotate(r);
},
act_ : function act_(){
LBT = new Game();
T = new Tank(0);
-LBT.addUnit(T, 1,1);
+LBT.addUnit(T, 1,2);
+
+B = new Bullet(T, 3*REF_SIZE,3*REF_SIZE);
+LBT.addUnit(B);
+B.render( LBT.level );
+
P = new Player(LBT, T);
-// L = new Layer(v)
-// .width(v.width())
-// .height(v.height())
-// .append(
-// new Rect(250,250)
-// .position(150,50)
-// .attr({
-// fillStyle : '#E2EEF5'
-// }),
-// new Triangle(25,-25, 50,0)
-// .position(150,300)
-// .attr('fillStyle', '#E73075'),
-// new Quad(10,50, 50,50, 60,0)
-// .position(50,50)
-// .attr('fillStyle', '#E73075'),
-// new Circle(30)
-// .position(30,330)
-// .attr('fillStyle', '#8DCDA1')
-// ).appendTo(v)
-// .draw()
-// ;
+ctx = LBT.level.ctx;
+tr = B.trajectory;
+
+
});
\ No newline at end of file
Bullet = new Y.Class('Bullet', Thing, {
- /*
- t = time from creation
- current_t = now - creation_time
- */
/**
* @param {tanks.Unit} owner
* @param {math.Line} trajectory
*/
- init : function initBullet(owner, trajectory){
- Thing.init.call(this, owner.game, owner.align);
+ init : function initBullet(owner, x,y){
+ this.owner = owner;
- this.owner = owner;
- this.trajectory = trajectory;
- this.creationTime = NOW;
+ var loc = owner.loc
+ , trj = this.trajectory = new math.Line(loc.x,loc.y, x,y);
+ Thing.init.call(this, owner.game, owner.align);
- this.setLocation(trajectory.x1, trajectory.y1);
- // this.trajectory.setT(this.stats.move*SQUARETH);
+ this.setLocation(trj.x1, trj.y1);
+ trj.setTScale(this.stats.move * REF_SIZE/1000);
},
blocking : false,
- creationTime : 0,
+ elapsed : 0,
+ width : 5,
+ height : 5,
stats : {
move : 2.0, // move speed (squares/sec)
fillStats : function(){
this.stats = Y({},
Thing.fillStats(this.owner.stats),
- Thing.fillStats(this.stats) ).end();
+ Thing.fillStats(this.stats) );
},
createCooldowns : Y.op.nop,
act : function act(){
+ this.elapsed += ELAPSED;
if (!this.dead)
this.move();
return this;
},
move : function move(){
- var to = this.trajectory.pcalc( (NOW-this.creationTime) * REF_SIZE/1000 );
+ var p, wall, p2 = this.trajectory.p2
+ , level = this.game.grid, walls = level.walls
+ , w = level.layerWidth, h = level.layerHeight
+ , trj = this.trajectory
+ , to = this.trajectory.pcalc(this.elapsed);
+
+ // 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);
+ }
+
+ p = math.reflect(p2, wall.tangent(to));
+
+ // Are we pointed the wrong direction? Rotate 180 degrees around the bullet
+ if ( (p.x <= 0 && to.x <= 0) || (p.y <= 0 && to.y <= 0)
+ || (p.x >= w && to.x >= w) || (p.y >= h && to.y >= h)
+ ){
+ var x = to.x - (p.x - to.x)
+ , y = to.y - (p.y - to.y);
+ p = new math.Vec(x,y);
+ }
+
+ this.trajectory = new math.Line(
+ math.clamp(to.x, 0.1, w-0.1), math.clamp(to.y, 0.1, h-0.1),
+ p.x,p.y,
+ this.stats.move * REF_SIZE/1000 );
+
+ // console.log('p2='+p2+' reflected in '+wall.tangent(to)+' --> '+this.trajectory);
+
+ this.render(this.game.level);
+ this.elapsed = 0;
+ this.dirty = true;
+ return this.move();
+ }
+
this.game.moveAgentTo(this, to.x, to.y);
return this;
+ },
+
+ render : function render(parent){
+ if (this.tline) this.tline.remove();
+ if (this.shape) this.shape.remove();
+
+ var t = this.trajectory;
+ this.tline = Line.fromPoints(t.x1,t.y1, t.x2,t.y2)
+ .attr('strokeStyle', 'rgba(255,246,174, 0.5)')
+ .appendTo( parent );
+
+ this.shape = new Circle(2.5)
+ .position(this.loc.x, this.loc.y)
+ .attr('fillStyle', '#FFF6AE')
+ .appendTo( parent );
+
+ return this;
+ },
+
+ toString : function toString(){
+
+ return this.className+'(loc='+this.loc+', traj='+this.trajectory+', owner='+this.owner+')';
}
});
-Y(Bullet).extend({
-
- fireAt : function fireAt(ProjectileType, owner, target){
- var oloc = owner.loc
- , x1 = oloc.x, y1 = oloc.y
- , x2 = target.x, y2 = target.y
- ;
- return new ProjectileType(owner, new math.Line(x1,y1, x2,y2));
- }
-
-});
\ No newline at end of file
this.fireProjectile(target);
},
- fireProjectile : function fireProjectile(target){
- var p = Bullet.fireAt(this.projectile, this, target);
+ fireProjectile : function fireProjectile(x,y){
+ var ProjectileType = this.projectile
+ , p = new ProjectileType(this, x,y);
this.bullets.push(p);
- this.game.addAgent(p);
+ this.game.addUnit(p);
return p;
},
spark = new FpsSparkline(LBT.loop, '.fps-sparkline', 0,0);
// Tick once to draw grid, initial units
- LBT.start();
- LBT.stop();
- LBT.loop.elapsedAtStop = 0;
+ // LBT.start();
+ // LBT.stop();
+ // LBT.loop.elapsedAtStop = 1;
+
+ LBT.root.draw();
+
setInterval(updateInfo, 1000);
updateInfo();
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){
drawLine(w2,-h, w2,h, '#CCCCCC', 2.0);
-
P = new Layer()
.width(w).height(h)
.appendTo(grid);
ctx.scale(PPU, PPU);
points = Y([]);
-line = mkLine(5,8, 4,7);
+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)');
+
dragging = false;
P.layer.bind('click', function(evt){
if (!dragging) {
color = color || 'rgba(231,48,117, 0.5)';
var pts = points.clone();
clear();
- drawLine(-W/2, line.calcY(-W2), line.calcX(H2), H2, color);
+ drawLine(-W, line.calcY(-W), W, line.calcY(W), color);
P.append(p1, p2);
pts.forEach(addPoint);
}
color = color || 'rgba(231,48,117, 0.5)';
pcolor = pcolor || 'rgba(69,150,255, 1)';
- var line = new math.Line(x1,y1, x2,y2, 10);
- drawLine(-W/2, line.calcY(-W2), line.calcX(H2), H2, color);
+ var line = new math.Line(x1,y1, x2,y2);
+ drawLine(-W, line.calcY(-W), W, line.calcY(W), color);
p1 = drawPoint(line.x1, line.y1, pcolor);
p1.layer.bind('mousedown', function(){
}
function drawLine(x1,y1, x2,y2, color, width){
- if ([x1,y1, x2,y2].some(isNaN)) {
- throw new Error('Value is NaN!'+'('+x1+','+y1+') ('+x2+','+y2+')');
- }
try {
ctx.beginPath();
ctx.lineWidth = width || PX;
return c;
}
+function drawAngle(theta, radius){
+ radius = radius || 3;
+ ctx.beginPath();
+ ctx.fillStyle = 'rgba(36,71,146, 0.25)';
+ ctx.moveTo(0,0);
+ ctx.lineTo(radius,0);
+ // ctx.arc(0,0, radius, 0, -(Math.PI/2-theta), true);
+ ctx.arc(0,0, radius, 0, -theta, true);
+ ctx.lineTo(0,0);
+ ctx.fill();
+ ctx.closePath();
+}