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/
"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",
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);
});
}
+
+
+
+
+ /// 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 ///
/**
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){
-
-
-
- /// 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(){
.appendTo('head');
});
-
-
-
-
})(jQuery);
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
;
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);
},
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);
/**
* 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) ) {
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){
},
toString : function toString(){
- return 'Vec('+this.x.toFixed(3)+','+this.y.toFixed(3)+')';
+ return '['+this.x.toFixed(3)+', '+this.y.toFixed(3)+']';
}
});
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);
var r = this.radius;
ctx.arc(0,0, r, 0, Math.PI*2, false);
ctx.fill();
+ ctx.stroke();
}
});
},
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);
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) {
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)');
},
// [x,y]
-Loc = new Y.Class('Loc', [], {
+Loc = new Y.Class('Loc', math.Vec, {
init : function init(x, y){
if ( Array.isArray(x) ) {
},
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);
},
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+')';
}
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){
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);
},
--- /dev/null
+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
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);
// });
}
});
-
-
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 );
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));
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;