.rounded { border-radius:1em; -moz-border-radius:1em; -webkit-border-radius:1em; }
#viewport { position:relative; top:1em; width:500px; height:500px; margin:0 auto;
- outline:1px solid #ccc; }
+ /* outline:1px solid #ccc; */ }
#howto { position:fixed; top:3em; right:1em; color:#BFBFBF; }
#info { position:fixed; bottom:10px; right:10px; padding:0.5em; background-color:rgba(0,0,0, 0.1); color:#787878; }
#info label { display:block; float:left; width:3em; margin-right:0.5em; color:#787878; }
#info input { border:0; background-color:transparent; min-width:5em; width:5em; color:#5c5c5c; }
-
-#log { position:fixed; top:auto; bottom:0; left:0; width:100%; height:30%; border-top:1px solid #bbb; }
+ #info .sep { opacity:0.1; background-color:#999; margin:5px 0; height:1px; }
<li id="state"></li>
<li><label for="fps">fps</label> <input id="fps" name="fps" value="" type="text"></li>
<li><label for="frame">frame</label> <input id="frame" name="frame" value="" type="text"></li>
- <li><label for="agents">agents</label> <input id="agents" name="agents" value="" type="text"></li>
+ <li><div class="sep"></div></li>
+ <li><label for="objects">objects</label> <input id="objects" name="objects" value="" type="text"></li>
<li><label for="units">units</label> <input id="units" name="units" value="" type="text"></li>
<li><label for="bullets">bullets</label> <input id="bullets" name="bullets" value="" type="text"></li>
</ul>
-<div id="log" style="display:none"></div>
-
<div id="scripts">
<!--[if IE]><script type="text/javascript" src="lib/excanvas.min.js"></script><![endif]-->
<?php
"src/portal/layer.js",
"src/portal/shape.js",
+ "src/portal/util/quadtree.js",
+ "src/portal/util/rbtree.js",
+ "src/portal/util/eventloop.js",
+ "src/portal/util/cooldown.js",
+ "src/portal/util/loc.js",
+
+ "src/tanks/util/pathmap.js",
+ "src/tanks/util/grid.js",
+
+ "src/tanks/game/game.js",
+ "src/tanks/game/map.js",
+
+ "src/tanks/unit/tank.js",
- // "src/portal/util/quadtree.js",
- // "src/portal/util/rbtree.js",
- // "src/portal/util/eventloop.js",
- // "src/portal/util/cooldown.js",
- // "src/portal/util/loc.js",
+ "src/tanks/game/player.js",
- "src/tanks/map.js",
- "src/tanks/tank.js",
- "src/tanks/game.js",
- "src/tanks/ui.js",
+ "src/tanks/lttl.js",
+ "src/tanks/ui.js"
- "src/tanks/lttl.js"
);
function js($src) {
if ( !o )
return acc;
+ fn = Function.toFunction(fn);
if ( notSelfOrWrapped(o.reduce) )
return o.reduce.apply(o, slice.call(arguments,1));
if (fn.__curried__)
return fn.apply(this, Y(arguments,1));
+ fn = Function.toFunction(fn);
var args = Y(arguments, 1)
, L = unwrap(fn).length;
YFunction.prototype.compose = methodize(compose);
function _composer(x,fn){ return fn.call(this, x); }
function compose(f,g){
- var fns = Y(arguments);
+ var fns = Y(arguments).map(Function.toFunction);
return function(){
return fns.reduce(_composer, Y(arguments), this);
};
Y.chain = chain;
YFunction.prototype.chain = methodize(chain);
function chain(f,g){
- var fns = Y(arguments);
+ var fns = Y(arguments).map(Function.toFunction);
if ( g.__sequence__ )
fns = g.__sequence__.concat( fns.slice(1) );
}
$y_files = array(
+ 'to-function',
'alias',
'type',
'core',
+++ /dev/null
-(function(){
-
-var undefined,
-globals = this,
-_toString = _Object.prototype.toString,
-_hasOwn = _Object.prototype.hasOwnProperty,
-_isArray = _Array.isArray;
+++ /dev/null
-
-globals.reduce = reduce;
-globals.extend = extend;
-globals.attr = attr;
-
-})();
+++ /dev/null
-// Generic Collection Functions
-
-function notSelfOrWrapped(fn){
- var self = arguments.callee.caller;
- return fn && fn !== self && fn.__wraps !== self;
-}
-
-function reduce(o, fn, acc, cxt){
- if ( !o )
- return acc;
-
- if ( notSelfOrWrapped(o.reduce) )
- return o.reduce.apply(o, slice.call(arguments,1));
-
- cxt = cxt || o;
- for ( var name in o )
- acc = fn.call(cxt, acc, o[name], name, o);
-
- return acc;
-}
-
-function attr(o, key, value, def){
- if ( o && notSelfOrWrapped(o.attr) )
- return o.attr.apply(o, slice.call(arguments,1));
-
- if ( value !== undefined || def !== undefined ){
- o[key] = (value !== undefined ? value : def);
- return o;
- } else
- return o[key];
-}
-
-function extend( A, B ){
- return slice.call(arguments,1).reduce(function(A, donor){
- return reduce(donor, function(o, v, k){
- return attr(o, k, v, o[k]);
- }, A);
- }, A);
-}
+++ /dev/null
-var WR_P = "__wraps__";
-
-
-function unwrap(fn){
- return ( fn && isFunction(fn) ) ? unwrap(fn[WR_P]) || fn : fn;
-}
-
-Function.prototype.curry = curry;
-function curry(){
- var fn = this
- , args = Array.slice(arguments,0)
- , L = unwrap(fn).length;
-
- function curried(){
- var _args = args.concat(Array.slice(arguments,0));
- if ( _args.length >= L )
- return fn.apply(this, _args);
- else
- return curry.apply(fn, _args);
- }
- curried[WR_P] = fn;
-
- return curried;
-}
-
-Function.prototype.methodize = methodize;
-function methodize() {
- var fn = this;
- if ( fn.__methodized__ )
- return fn.__methodized__;
-
- var m = fn.__methodized__ =
- function(){
- return fn.apply(this, [this].concat(Array.slice(arguments, 0)));
- };
- m[WR_P] = fn;
- return m;
-}
-
-/** Returns the declared name of a function. */
-Function.prototype.getName = getName;
-function getName(){
- var fn = this;
- return fn.className || fn.name || (fn+'').match( /function\s*([^\(]*)\(/ )[1] || '';
-}
-
+++ /dev/null
-<?php
-function dump_file($path, $add_newline=true){
- $size = filesize($path);
- if ($size > 0) {
- $f = fopen($path, "r");
- echo fread($f, $size);
- fclose($f);
- }
- if ($add_newline) echo "\n";
-}
-
-$jsjs_files = array(
- 'type',
- 'core',
- 'function',
- 'object',
- 'array',
- 'string',
- 'number'
-);
-
-function jsjs_list($path='') {
- global $jsjs_files;
- $path = $path ? $path : dirname($_SERVER["REQUEST_URI"]);
- // echo $path;
- foreach ($jsjs_files as $f) {
- echo "<script src='$path/$f.js' type='text/javascript'></script>\n";
- }
-}
-
-function jsjs_dump($expose=false) {
- global $jsjs_files;
- if (!$expose)
- dump_file("./_intro.js");
- foreach ($jsjs_files as $f)
- dump_file("./$f.js");
- if (!$expose)
- dump_file("./_outro.js");
-}
-
-if ( basename($_SERVER["SCRIPT_FILENAME"]) == basename(__FILE__) ) {
- if ( $_REQUEST["list"] )
- jsjs_list();
- else
- jsjs_dump();
-}
\ No newline at end of file
+++ /dev/null
-// Type Utilities //
-// Much borrowed from jQuery
-
-var class2type = "Boolean Number String Function Array Date RegExp Object"
- .split(" ")
- .reduce(function(class2type, name) {
- class2type[ "[object "+name+"]" ] = name.toLowerCase();
- return class2type;
- }, {});
-
-function type_of(obj){
- return obj == null ?
- String( obj ) :
- class2type[ toString.call(obj) ] || "object";
-}
-
-function isFunction(obj) { return type_of(obj) === "function"; }
-function isString(obj) { return type_of(obj) === "string"; }
-function isNumber(obj) { return type_of(obj) === "number"; }
-
-// A crude way of determining if an object is a window
-function isWindow( obj ) {
- return obj && typeof obj === "object" && "setInterval" in obj;
-}
-
-function isPlainObject( obj ){
- // Must be an Object.
- // Because of IE, we also have to check the presence of the constructor property.
- // Make sure that DOM nodes and window objects don't pass through, as well
- if ( !obj || type_of(obj) !== "object" || obj.nodeType || isWindow(obj) )
- return false;
-
- // Not own constructor property must be Object
- if ( obj.constructor &&
- !hasOwn.call(obj, "constructor") &&
- !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") )
- return false;
-
-
- // Own properties are enumerated firstly, so to speed up,
- // if last one is own, then all properties are own.
-
- var key;
- for ( key in obj ) {}
-
- return key === undefined || hasOwn.call( obj, key );
-}
-
-
$(function(){
$('<style />')
.text([
- '.portal.layer { position:absolute; z-index:1; overflow:hidden; }',
+ '.portal.layer { position:absolute; z-index:1; overflow:hidden; top:0; left:0; }',
'.portal.layer canvas { z-index:0; }'
].join('\n'))
.appendTo('head');
return this;
var _ctx = ctx || this.ctx;
- this._openPath(_ctx)
- .drawShape(_ctx)
- ._closePath(_ctx);
+ this._openPath(_ctx);
+ this.drawShape(_ctx);
+ this._closePath(_ctx);
this.dirty = false;
this.children.invoke('draw', ctx);
drawShape : function(ctx){
ctx.rect(0,0, this._width,this._height);
ctx.fill();
- return this;
}
});
Polygon = new Y.Class('Polygon', Shape, {
+ _cssClasses : 'portal layer shape polygon',
/**
* Expects two arrays of coordinate-halfs, which could be zipped
ctx.lineTo.apply(ctx, pair);
});
ctx.fill();
- return this;
}
});
Triangle = new Y.Class('Triangle', Polygon, {
+ _cssClasses : 'portal layer shape polygon triangle',
+
init : function(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(x1,y1, x2,y2, x3,y3){
Polygon.init.call(this, [x1,x2,x3], [y1,y2,y3]);
}
});
+Circle = new Y.Class('Circle', Shape, {
+ _cssClasses : 'portal layer shape circle',
+
+ init : function(radius){
+ Layer.init.call(this);
+
+ var d = radius * 2;
+ this.width(d).height(d);
+ this.radius = radius;
+ },
+
+ drawShape : function(ctx){
+ var r = this.radius;
+ ctx.arc(r,r, r, 0, Math.PI*2, false);
+ ctx.fill();
+ }
+
+});
\ No newline at end of file
this.y = Math.max(y,0);
},
+ moveBy : function(dir, amount){
+ var mod = 1;
+ switch (dir) {
+ case Loc.LEFT: mod = -1;
+ case Loc.RIGHT:
+ return new Loc(this.x+amount*mod, this.y);
+
+ case Loc.UP: mod = -1;
+ case Loc.DOWN:
+ return new Loc(this.x, this.y+amount*mod);
+ }
+ },
+
clone : function(){
return new Loc(this.x, this.y);
},
toSquare : function(){
- return Square.fromLoc(this.x, this.y);
+ return Loc.Square.fromLoc(this.x, this.y);
},
toString : function(){
});
Y(Loc).extend({
+ UP : 'up', DOWN : 'down',
+ RIGHT : 'right', LEFT : 'left',
fromSquare : function(col, row){
return new Loc(
});
-Rect = new Y.Class('Rect', {
+Loc.Rect = new Y.Class('Rect', {
init : function(x1,y1, x2,y2){
if (x1 instanceof Loc && y1 instanceof Loc) {
var top = x1,
},
clone : function(){
- return new Rect(
+ return new Loc.Rect(
this.top.clone(),
this.bottom.clone() );
},
});
-Square = new Y.Class('Square', Rect, {
+Loc.Square = new Y.Class('Square', Rect, {
init : function(col, row){
col = this.col = Math.max(col,0);
row = this.row = Math.max(row,0);
, x2 = x1 + REF_SIZE
, y2 = y1 + REF_SIZE;
- Rect.init.call(this, x1,y1, x2,y2);
+ Loc.Rect.init.call(this, x1,y1, x2,y2);
},
clone : function(){
}
});
-Square.fromLoc = function(x, y){
- return new Square(
+Loc.Square.fromLoc = function(x, y){
+ return new Loc.Square(
Math.floor(x / REF_SIZE),
Math.floor(y / REF_SIZE) );
};
}
});
-this['QuadTree'] = QuadTree;
QuadTree['Region'] = Region;
+this['QuadTree'] = QuadTree;
})();
--- /dev/null
+var undefined
+, GRID_ELEMENT = '#viewport'
+
+, REF_SIZE = 50
+, CELL_SIZE = REF_SIZE
+, SCALE = CELL_SIZE / REF_SIZE
+, GRID_OFFSET = 0
+
+, COLUMNS = 10
+, ROWS = 10
+, CAPACITY = 32
+
+, FRAME_RATE = 30
+, MS_PER_FRAME = 1000 / FRAME_RATE
+
+, NOW = new Date().getTime() // Current tick's timestamp (ms)
+, ELAPSED = MS_PER_FRAME // Time (ms) since previous tick
+, FRAMETH = ELAPSED / 1000 // Ratio of second completed
+, TICKS = 0 // Ticks since start of game
+
+, PI = Math.PI
+, TWO_PI = PI*2
+, HALF_PI = PI/2
+
+;
+
+
+
+Game = new Y.Class('Game', {
+
+ init : function(viewport){
+ this.loop = new EventLoop(this, FRAME_RATE);
+
+ // Seal all methods
+ // Y.bindAll(this);
+ this.resize = this.resize.bind(this);
+ this.tick = this.tick.bind(this);
+
+ this.viewport = $(viewport || GRID_ELEMENT);
+
+ this.initMap();
+
+ this.addEventListener('tick', this.tick);
+ },
+ showOverlay : false,
+
+ /**
+ * Main Event Loop.
+ */
+ tick : function(evt){
+ var d = evt.data;
+
+ NOW = d.now;
+ ELAPSED = d.elapsed;
+ TICKS = d.ticks;
+
+ this.root.draw();
+
+ this.units.invoke('act');
+ // XXX: Collect the dead
+
+ // this.grid.removeOverlay(this.el);
+ // if (this.showOverlay) this.grid.overlay(this.el);
+ }
+
+});
+
+
--- /dev/null
+
+Y(Game.prototype).extend({
+
+ initMap : function(){
+ var self = this;
+
+ this.pathmap = new PathMap(0,0, COLUMNS*REF_SIZE, ROWS*REF_SIZE, CAPACITY);
+
+ var root = this.root = this.grid =
+ new Grid(COLUMNS,ROWS, CELL_SIZE)
+ .appendTo(this.viewport);
+ this.level =
+ new Layer()
+ .width( root._width )
+ .height( root._height)
+ .appendTo(this.root);
+
+ // this.root.ctx.scale(1.0, 1.0);
+
+ 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);
+ // });
+ // Agent.addEventListener('destroy', function(evt){
+ // self.killAgent(evt.instance);
+ // });
+ },
+
+
+ // *** Path Map Management *** //
+
+ addBlocker : function(agent){
+ var bb = agent.boundingBox;
+ if (agent.blocking && bb)
+ agent.region = this.grid.set(bb.x1,bb.y1, bb.x2,bb.y2, agent);
+ return agent;
+ },
+
+ removeBlocker : function(agent){
+ if (agent.region)
+ this.grid.remove(agent.region);
+ return agent;
+ },
+
+ updateBlocker : function(agent){
+ this.removeBlocker(agent);
+ this.addBlocker(agent);
+ },
+
+
+ // *** Agent Management *** //
+
+ addUnit : function(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 );
+