transform : null, // Object
useCanvasScaling : false, // default to CSS3 scaling
+ /// Defaults ///
+
+ originX : 0,
+ originY : 0,
+
+
/// Setup ///
this.negBleed = new Loc(0,0);
this.posBleed = new Loc(0,0);
- this.boundingBox = new BoundingBox(0,0, 0,0);
+ this.boundingBox = new BoundingBox(0,0, 0,0, this.originX,this.originY);
this._origin = this.boundingBox.origin;
this.transform = {
attr : Y.attr.methodize(),
+ size : function size(w,h){
+ if (w === undefined && h === undefined)
+ return new Vec(this.layerWidth,this.layerHeight);
+
+ this.layerWidth = w;
+ this.layerHeight = h;
+
+ var bb = this.boundingBox.resize(w,h)
+ , nb = this.negBleed, pb = this.posBleed
+
+ // HTMLCanvas.{width,height} is a long
+ , cw = this.canvasWidth = Math.ceil(w + nb.x + pb.x)
+ , ch = this.canvasHeight = Math.ceil(h + nb.y + pb.y)
+ ;
+
+ this.layer.css({
+ 'width' : w, 'height' : h,
+ 'left' : bb.x1, 'top' : bb.y1
+ });
+ this.canvas.css({
+ 'width' : cw, 'height' : ch,
+ 'margin-left' : -nb.x, 'top' : -nb.y
+ });
+ var el = this.canvas[0];
+ el.width = cw;
+ el.height = ch;
+
+ return this;
+ },
+
/**
* Changes the layer's width and then updates the canvas.
*/
this.layerWidth = w;
var bb = this.boundingBox.resize(w, this.layerHeight)
- , ro = bb.relOrigin
+ // , ro = bb.relOrigin
, nb = this.negBleed
, cw = this.canvasWidth = Math.ceil(w + nb.x + this.posBleed.x); // HTMLCanvas.width is a long
this.layer.css({
'width' : w,
'left' : bb.x1,
- 'margin-left' : -ro.x
+ // 'margin-left' : -ro.x
});
this.canvas.css({
this.layerHeight = h;
var bb = this.boundingBox.resize(this.layerWidth, h)
- , ro = bb.relOrigin
+ // , ro = bb.relOrigin
, nb = this.negBleed
, ch = this.canvasHeight = Math.ceil(h + nb.y + this.posBleed.y); // HTMLCanvas.height is a long
this.layer.css({
'height' : h,
'top' : bb.y1,
- 'margin-top' : -ro.y
+ // 'margin-top' : -ro.y
});
this.canvas.css({
css : makeDelegate('css'),
/** Position relative to document. */
- // offset : makeDelegate('offset'),
+ offset : makeDelegate('offset'),
return this;
},
+ animate : function animate(props, options) {
+
+ },
+
+ /// Debuggging ///
+
// for debugging
point : function point(x,y, color){
var ctx = this.ctx;
return this;
},
- animate : function animate(props, options) {
+ title : function title(val){
+ if (val === undefined)
+ return this.layer.attr('title');
+ this.layer.attr('title', val);
+ return this;
},
/// Misc ///
toString : function toString(){
- var pos = (this.layer ? this.position() : {y:NaN, x:NaN});
- return this.className+'['+pos.x+','+pos.y+']( children='+this.children.size()+' )';
+ var pos = (this.layer ? this.position() : {top:NaN, left:NaN});
+ return this.className+'['+pos.left+','+pos.top+']( children='+this.children.size()+' )';
}
});
* Use relocate() to change the position by moving the origin.
*/
set originX(v){ this._origin.x = v; return v; },
- get originX(){ return this._origin.absolute(this.width,this.height, this.x1,this.x2).x; },
+ get originX(){ return this._origin.absolute(this.width,this.height, this.x1,this.y1).x; },
set originY(v){ this._origin.y = v; return v; },
- get originY(){ return this._origin.absolute(this.width,this.height, this.x1,this.x2).y; },
+ get originY(){ return this._origin.absolute(this.width,this.height, this.x1,this.y1).y; },
/**
* Accessor for the realized numeric origin.
*/
- get absOrigin() { return this._origin.absolute(this.width,this.height, this.x1,this.x2); },
+ get absOrigin() { return this._origin.absolute(this.width,this.height, this.x1,this.y1); },
get relOrigin() { return this._origin.absolute(this.width,this.height); },
get origin(){ return this._origin; },
var _x1 = this[X1], _y1 = this[Y1]
, _x2 = this[X2], _y2 = this[Y2]
- , abs = this._origin.absolute(_x1-_x1, _y2-_y1, _x1,_y1)
+ , abs = this._origin.absolute(_x2-_x1, _y2-_y1, _x1,_y1)
, dx1 = _x1 - abs.x, dy1 = _y1 - abs.y
, dx2 = _x2 - abs.x, dy2 = _y2 - abs.y
return this.set4(x1,y1, x2,y2);
},
+ relocated : function relocated(x,y){
+ var bb = this.clone();
+ return bb.relocate(x,y);
+ },
+
resize : function resize(w,h){
var x1 = this[X1], y1 = this[Y1]
, x2 = this[X2], y2 = this[Y2]
, xp = o.xPercentage, yp = o.yPercentage
;
if ( xp !== null ) {
- diff = w - wOld;
+ // diff = w - wOld;
abs = x1 + xp*wOld;
- x1 = abs - xp*diff;
- x2 = abs + (1-xp)*diff;
+ x1 = abs - xp*w;
+ x2 = abs + (1-xp)*w;
} else
x2 = x1 + w;
if ( yp !== null ) {
- diff = h - hOld;
+ // diff = h - hOld;
abs = y1 + yp*hOld;
- y1 = abs - yp*diff;
- y2 = abs + (1-yp)*diff;
+ y1 = abs - yp*h;
+ y2 = abs + (1-yp)*h;
} else
y2 = y1 + h;
return this.set4(x1,y1, x2,y2);
},
+ resized : function resized(w,h){
+ var bb = this.clone();
+ return bb.resize(w,h);
+ },
+
clone : function clone(){
var o = this._origin;
return new BoundingBox(this[X1],this[Y1], this[X2],this[Y2], o[X1], o[Y1]);
return this.setXY(x*cos - y*sin, x*sin + y*cos);
},
+ clone : function clone(){
+ return new this.__class__(this[_X],this[_Y]);
+ },
+
toString : function toString(){
var p = 2, x = this[_X], y = this[_Y];
x = ((x % 1 !== 0) ? x.toFixed(p) : x);
exports['Circle'] =
Shape.subclass('Circle', {
_cssClasses : 'ezl layer shape circle',
+ originX : '50%',
+ originY : '50%',
init : function initCircle(radius){
Shape.init.call(this);
var d = r * 2;
this.dirty = true;
this._radius = r;
- this.width(d).height(d);
+ this.size(d,d);
return this;
},
drawShape : function drawShape(ctx){
- ctx.arc(0,0, this._radius, 0, Math.PI*2, false);
+ var r = this._radius;
+ ctx.arc(r,r, r, 0, Math.PI*2, false);
ctx.fill();
ctx.stroke();
}
exports['Rect'] =
Shape.subclass('Rect', {
_cssClasses : 'ezl layer shape rect',
+ originX : 0,
+ originY : 0,
init : function initRect(w,h){
Shape.init.call(this);
- this.origin(0,0)
- .width(w)
- .height(h);
+ this.size(w,h);
},
drawShape : function drawShape(ctx){
exports['defaults'] = {
ui : {
showGridCoords : false,
- showCountdown : true
+ showCountdown : false
},
pathing : {
overlayAIPaths : false,
// 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 ;
+ , x = sqX + REF_SIZE/2
+ , y = sqY + REF_SIZE/2 ;
unit.position(x,y);
unit.render( this.level );
// -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
var Y = require('Y').Y
-, Vec = require('ezl/math/vec').Vec
+, math = require('ezl/math')
+, Vec = math.Vec
+, Line = math.Line
, QuadTree = require('ezl/util/tree/quadtree').QuadTree
, Bullet = require('tanks/thing/bullet').Bullet
, astar = require('ezl/util/astar')
bb = bb || agent.boundingBox;
var blockers, blocker, msg
, side = null
-
- , bw = bb.width, bh = bb.height
+ , tobb = bb.relocated(to.x,to.y)
+ , x1 = tobb.x1, y1 = tobb.y1
+ , x2 = tobb.x2, y2 = tobb.y2
, ro = bb.relOrigin
- , offX = ro.x, offY = ro.y
+ , bw = bb.width, bh = bb.height
+ , offX = bw - ro.x, offY = bh = ro.y
- , x1 = to.x+offX, y1 = to.y+offY
- , x2 = x1+bw, y2 = y1+bh
+ // , x1 = to.x+offX, y1 = to.y+offY
+ // , x2 = x1+bw, y2 = y1+bh
;
blockers = this.get(x1,y1, x2,y2).remove(agent).end();
if (bb.x2 <= B.x1 && x2 >= B.x1) {
msg += 'left';
side = new Line(B.x1,B.y1, B.x1,B.y2);
- to = trj.pointAtX(B.x1-bw-offX-1);
+ to = trj.pointAtX(B.x1-offX-1);
} else if (bb.x1 >= B.x2 && x1 <= B.x2) {
msg += 'right';
side = new Line(B.x2,B.y1, B.x2,B.y2);
- to = trj.pointAtX(B.x2-offX+1);
+ to = trj.pointAtX(B.x2+ro.x+1);
} else if (bb.y2 <= B.y1 && y2 >= B.y1) {
msg += 'top';
side = new Line(B.x1,B.y1, B.x2,B.y1);
- to = trj.pointAtY(B.y1-bh-offY-1);
+ to = trj.pointAtY(B.y1-offY-1);
} else if (bb.y1 >= B.y2 && y1 <= B.y2) {
msg += 'bottom';
side = new Line(B.x1,B.y2, B.x2,B.y2);
- to = trj.pointAtY(B.y2-offY+1);
+ to = trj.pointAtY(B.y2+ro.y+1);
}
msg += ' side';
, Vec = math.Vec
, Line = math.Line
, Rect = math.Rect
+, BoundingBox = require('ezl/loc').BoundingBox
, Thing = require('tanks/thing/thing').Thing
,
to = this.stepTo(t, bb);
if (this.halt) break;
- // FIXME: bb.add?
- bb = new Rect(to.x,to.y, to.x+bw,to.y+bh);
+ bb = new BoundingBox(to.x,to.y, to.x+bw,to.y+bh);
} while (dt > 0);
var toLoc = this.loc.moveByDir(dir, (this.stats.move * SQUARETH))
, x = toLoc.x, y = toLoc.y
- , bb = this.boundingBox.reloacte(x,y)
+ , bb = this.boundingBox.relocate(x,y)
, blockers = this.game.pathmap.get(bb.x1,bb.y1, bb.x2,bb.y2).remove(this)
;
turretColor : '#1C625B',
barrelColor : '#D43B24',
-
// Bounding box size
width : REF_SIZE*0.55,
height : REF_SIZE*0.55,
function moveByAngle(theta, targetX,targetY){
var abs = Math.abs
, bb = this.boundingBox, w2 = bb.width/2, h2 = bb.height/2
- , loc = this.loc, mid = bb.midpoint()
+ , loc = this.loc, mid = bb.midpoint
, to = loc.moveByAngle(theta, this.stats.move * SQUARETH)
;
if ( targetY !== undefined && abs(loc.y-to.y) > abs(loc.y-targetY) )
to.setXY(to.x, targetY);
- var nbb = bb.add(to.x,to.y)
+ var nbb = bb.relocated(to.x,to.y)
, blockers = this.game.pathmap.get(nbb.x1,nbb.y1, nbb.x2,nbb.y2).remove(this)
;
, path = this.lastPath = pm.path(start, end, this.id)
, to = this.currentMove = path.shift()
;
-
- // VVV We only really need this code if we're going to recalculate before we reach the currentMove
-
- // we may need to move closer to start if we occupy multiple grid-squares
- // var tosq = pm.vec2Square(to), manhattan = Vec.manhattan
- // , bb = this.boundingBox
- // , tl = pm.vec2Square(bb.x1,bb.y1), tr = pm.vec2Square(bb.x2,bb.y1)
- // , bl = pm.vec2Square(bb.x1,bb.y2), br = pm.vec2Square(bb.x2,bb.y2)
- // , straddles = [tl, tr, bl, br]
- // ;
- //
- //
- // if ( !tl.equals(br) ) {
- // tl.to = pm.vec2Square(bb.x1,bb.y1); tr.to = pm.vec2Square(mid.x,bb.y1);
- // bl.to = pm.vec2Square(bb.x1,mid.y); br.to = pm.vec2Square(mid.x,mid.y);
- // straddles.sort(function(a,b){
- // return Y.op.cmp(manhattan(a,tosq), manhattan(b,tosq));
- // });
- // to = pm.square2Vec(straddles[0].to).add(pm.gridSquareMidPt);
- // path.unshift(to);
- // }
-
- // console.log('start:', start, 'straddles:', straddles.map(pm.square2Vec.bind(pm)), 'end:', end, 'next:', to);
};
this['getTurretLoc'] =
function getTurretLoc(){
- var loc = this.loc, mid = this.midpoint
+ var WIGGLE = 8
+ , loc = this.loc, mid = this.midpoint
, barrel = this.barrel
, theta = barrel.transform.rotate
, sin = Math.sin(theta), cos = Math.cos(theta)
- , len = barrel.boundingBox.width
+ , len = barrel.boundingBox.width + WIGGLE
, x = mid.x + len*cos
, y = mid.y + len*sin
;
- // console.log('getTurretLoc()', 'loc:', loc, 'bbb.(x2,y2):', [bbb.x2,bbb.y2], '(x,y):', [x,y]);
+ // console.log('getTurretLoc()', 'loc:', loc, '(x,y):', [x,y]);
return new Vec(x,y);
};
this.shape =
new Rect(w,h)
+ .origin(this.originX,this.originY)
.position(this.loc.x, this.loc.y)
.fill(this.bodyColor)
.appendTo( parent ) ;
exports['Thing'] =
new evt.Class('Thing', {
- init : function init(align){
- this.id = Thing.THING_ID++;
- this.align = align || 0;
- this.boundingBox = new BoundingBox(0,0, this.width,this.height, this.originX,this.originY);
-
- this.fillStats();
- this.createCooldowns();
- },
-
// Attributes
stats: {
hp : 1, // health
width : REF_SIZE,
height : REF_SIZE,
- set : Y.op.set.methodize(),
- attr : Y.op.attr.methodize(),
-
- dealDamage : function dealDamage(d, source){
- this.stats.hp -= d;
-
- if (this.stats.hp <= 0)
- this.destroy();
+ init : function init(align){
+ this.id = Thing.THING_ID++;
+ this.align = align || 0;
+ this.boundingBox = new BoundingBox(0,0, this.width,this.height, this.originX,this.originY);
- return this;
+ this.fillStats();
+ this.createCooldowns();
},
+ set : Y.op.set.methodize(),
+ attr : Y.op.attr.methodize(),
+
+
position : function position(x,y){
- var bb = this.boundingBox.relocate(x,y);
- this.loc = bb.absOrigin;
+ if (x === undefined && y === undefined)
+ return this.loc;
+
+ var bb = this.boundingBox.relocate(x,y)
+ , loc = this.loc = bb.absOrigin;
this.midpoint = bb.midpoint;
- if (this.shape) this.shape.position(x,y);
+ if (this.shape) this.shape.position(loc.x,loc.y);
return this;
},
return this;
},
+ dealDamage : function dealDamage(d, source){
+ this.stats.hp -= d;
+
+ if (this.stats.hp <= 0)
+ this.destroy();
+
+ return this;
+ },
+
+
/**
* Calculates the location of the bullet-spawning point on this Thing.
*/
createCanvasGrid : true,
- init : function init(cols,rows, size){
+ init : function init(cols,rows, side){
this.cols = cols;
this.rows = rows;
- this.size = size;
- Rect.init.call(this, cols*size, rows*size);
+ this.side = side;
+ Rect.init.call(this, cols*side, rows*side);
},
drawShape : function drawShape(ctx){
// if (this.canvas) this.canvas.remove();
var cols = this.cols, rows = this.rows
- , size = this.size
+ , side = this.side
, w = this.canvasWidth
, h = this.canvasHeight
;
var row = $('<tr class="row row'+y+'" />').appendTo(tbody);
Y(0, cols).forEach(function(x){
$('<td class="cell cell'+x+'_'+y+' col'+x+'">'+x+','+y+'</td>')
- .width(size).height(size)
+ .width(side).height(side)
.appendTo(row);
}, this);
}, this);
ctx.lineWidth = this.lineWidth;
ctx.strokeStyle = this.strokeStyle;
- for (var row=0, y=0; row<=rows; y = (++row) * size){
+ for (var row=0, y=0; row<=rows; y = (++row) * side){
ctx.moveTo(0, y);
ctx.lineTo(w, y);
}
- for (var col=0, x=0; col<=cols; x = (++col) * size){
+ for (var col=0, x=0; col<=cols; x = (++col) * side){
ctx.moveTo(x, 0);
ctx.lineTo(x, h);
}
setupGame();
setupUI();
+
+ // $('#welcome').hide();
+ // $('#overlay').hide();
}
function gameExists(){ return !!tanks.currentGame; }
Y = require('Y').Y;
ezl = require('ezl');
+math = require('ezl/math');
+loc = require('ezl/loc');
shape = require('ezl/shape');
+
Grid = require('tanks/ui/grid').Grid;
grid.createTableGrid = false;
grid.lineWidth = 1.0;
grid.strokeStyle = '#E0E0E0'; //'#EEEEEE'; //
- grid.draw();
// Draw axes
shape.Line // X Axis
.width(w).height(h)
.appendTo(grid);
+ R = shape.Rect
+ .fromPoints(100,100, 150,150)
+ .fill('#E73075')
+ .appendTo(plot);
+ R.title(R.boundingBox+'');
+ C = new shape.Circle(25)
+ .position(150,150)
+ .fill('#2E62C9')
+ .appendTo(plot);
+ C.title(C.boundingBox+'');
+ grid.draw();
});