From: dsc Date: Thu, 4 Nov 2010 05:46:26 +0000 (-0700) Subject: Starts work on transform stack. X-Git-Url: http://git.less.ly:3516/?a=commitdiff_plain;h=004cc02dd1f9889a5a3b0b4de207c5982a102103;p=tanks.git Starts work on transform stack. --- diff --git a/css/lttl.css b/css/lttl.css index 0bd2596..5b26d43 100644 --- a/css/lttl.css +++ b/css/lttl.css @@ -6,8 +6,8 @@ ul, ol, li { list-style: none ! important; margin:0; padding:0; } .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; */ } +#viewport { position:relative; top:1em; width:500px; height:500px; margin:0 auto; overflow:hidden; + /* outline:1px solid #aaa; */ } #howto { position:fixed; top:3em; right:1em; color:#BFBFBF; } diff --git a/index.php b/index.php index e2b5d7a..f22a776 100644 --- a/index.php +++ b/index.php @@ -50,17 +50,15 @@ $scripts = array( "src/portal/util/cooldown.js", "src/portal/util/loc.js", + "src/tanks/globals.js", + "src/tanks/util/calc.js", "src/tanks/util/pathmap.js", "src/tanks/util/grid.js", - "src/tanks/game/game.js", "src/tanks/game/map.js", - "src/tanks/unit/thing.js", "src/tanks/unit/tank.js", - "src/tanks/game/player.js", - "src/tanks/lttl.js", "src/tanks/ui.js" diff --git a/notes.md b/notes.md index 1d5c4a2..dc5d10b 100644 --- a/notes.md +++ b/notes.md @@ -1 +1,2 @@ -- Clipping is going to suck \ No newline at end of file +- Clipping is going to suck +- TODO Replace *2 and /2 with shifts at compile-time \ No newline at end of file diff --git a/src/Y/core.js b/src/Y/core.js index bc22ed7..4536fb6 100644 --- a/src/Y/core.js +++ b/src/Y/core.js @@ -20,6 +20,16 @@ function reduce(o, fn, acc, cxt){ return acc; } +function set(o, key, value, def){ + if ( o && notSelfOrWrapped(o.set) ) + return o.set.apply(o, slice.call(arguments,1)); + + 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)); @@ -30,8 +40,7 @@ function attr(o, key, value, def){ return extend(o, key); if ( value !== undefined || def !== undefined ){ - o[key] = (value !== undefined ? value : def); - return o; + return set(o, key, value, def); } else return o[key]; } diff --git a/src/Y/modules/y.control.js b/src/Y/modules/y.control.js new file mode 100644 index 0000000..84631ef --- /dev/null +++ b/src/Y/modules/y.control.js @@ -0,0 +1,48 @@ +(function(Y, undefined){ if (!Y) return; + +/* Functional Control "Statements" */ +Y.extend(Y.op, { + + // flow + either: function( test, t, f ){ return function(v){ return test(v) ? t : f; }; }, + dowhile: function( test, action ){ + return function(v){ + var acc = v; + while( test(acc) ){ acc = action(acc); } + return acc; + }; + }, + dountil: function( test, action ){ + return Y.ops.dowhile( function(v){ return !test(v); }, action ); + }, + forloop: function( test, action, pretest, posttest ){ + pretest = pretest || Y.ops.I; + posttest = posttest || Y.ops.I; + return function(v){ + for(var acc = pretest(v); test(acc); acc = posttest(acc) ){ + acc = action(acc); + } + return acc; + }; + }, + repeat: function( action, n ){ + return function(v){ + for( var acc = v, i = 0; i < n; ++i ){ acc = action(acc); } + return acc; + }; + }, + maybe: function( pitcher, catcher ){ + return function(){ + var args = Y(arguments); + try { + return pitcher.apply( this, args ); + } catch(e) { + args.unshift(e); + return catcher.apply( this, args ); + } + }; + } +}); + + +})(this.Y); diff --git a/src/Y/modules/y.event.js b/src/Y/modules/y.event.js index 8b8cdce..7e085cf 100644 --- a/src/Y/modules/y.event.js +++ b/src/Y/modules/y.event.js @@ -11,7 +11,7 @@ ns = Y.event = {} */ , YEvent = ns.YEvent = Y.YObject.subclass('YEvent', { - init : function( type, target, trigger, data ){ + init : function init( type, target, trigger, data ){ data = data || {}; for (var k in data) this[k] = data[k]; this.data = this._o = data; @@ -28,23 +28,23 @@ Y.YObject.subclass('YEvent', { * A simple multicaster. */ , methods = { - getQueue : function(evt){ + getQueue : function getQueue(evt){ var Qs = this.queues; if ( !Qs[evt] ) Qs[evt] = Y([]); return Qs[evt]; }, - addEventListener : function(evt, fn){ + addEventListener : function addEventListener(evt, fn){ this.getQueue(evt).push(fn); return this.target; }, - removeEventListener : function(evt, fn){ + removeEventListener : function removeEventListener(evt, fn){ this.getQueue(evt).remove(fn); }, - fire : function(evtname, trigger, data, async){ + fire : function fire(evtname, trigger, data, async){ var evt = new YEvent(evtname, this.target, trigger, data); if (async) setTimeout(this.dispatchEvent.bind(this, evt), 10); @@ -54,7 +54,7 @@ Y.YObject.subclass('YEvent', { }, // XXX: does not handle degenerate or recursive event dispatch - dispatchEvent : function(evt){ + dispatchEvent : function dispatchEvent(evt){ this.getQueue(evt.type).invoke('call', evt.target, evt); if (this.parent) this.parent.fire(evt.type, evt.trigger, evt.data); return evt; @@ -63,7 +63,7 @@ Y.YObject.subclass('YEvent', { /** * Decorates object with bound methods to act as a delegate of this hub. */ - decorate : function(delegate){ + decorate : function decorate(delegate){ if (!delegate) return; for (var k in methods) delegate[k] = methods[k].bind(this); diff --git a/src/Y/modules/y.op.js b/src/Y/modules/y.op.js deleted file mode 100644 index d8260a4..0000000 --- a/src/Y/modules/y.op.js +++ /dev/null @@ -1,101 +0,0 @@ -(function(Y, undefined){ if (!Y) return; - -/* Functional Operators (Taste Great with Curry!) */ -Y.op = { - - // comparison - cmp: function(x,y){ return x == y ? 0 : (x > y ? 1 : -1); }, - eq: function(x,y){ return x == y; }, - ne: function(x,y){ return x != y; }, - gt: function(x,y){ return x > y; }, - ge: function(x,y){ return x >= y; }, - lt: function(x,y){ return x < y; }, - le: function(x,y){ return x <= y; }, - - // math - add: function(x,y){ return x + y; }, - sub: function(x,y){ return x - y; }, - mul: function(x,y){ return x * y; }, - div: function(x,y){ return x / y; }, - flrdiv: function(x,y){ return Math.floor(x / y); }, - mod: function(x,y){ return x % y; }, - - // logic - and: function(x,y){ return x && y; }, - or: function(x,y){ return x || y; }, - xor: function(x,y){ return x != y; }, - not: function(x){ return !x; }, - neg: function(x){ return -x; }, - - // bitwise - bitnot: function(x){ return ~x; }, - bitand: function(x,y){ return x & y; }, - bitor: function(x,y){ return x | y; }, - bitxor: function(x,y){ return x ^ y; }, - lshift: function(x,y){ return x << y; }, - rshift: function(x,y){ return x >> y; }, - zrshift: function(x,y){ return x >>> y; }, - - // typecast - bool: function(x){ return !!x; }, - number: function(x){ return Number(x); }, - int: function(x){ return parseInt(x); }, - float: function(x){ return parseFloat(x); }, - str: function(x){ return String(x); }, - - // functional - I: function(x){ return x; }, - K: function(k){ return function(){ return k; }; }, - nop: function(){}, - - // accessors - isset: function(o,def){ return o !== undefined ? o : def; }, - has: function(x,y){ return y in x; }, - getkey: function(k,o){ return o[k] }, - getdef: function(o,k,def){ return (k in o ? o[k] : def); }, - set: function(o,k,v){ if (o) o[k] = v; return o; }, - - - // flow - either: function( test, t, f ){ return function(v){ return test(v) ? t : f; }; }, - dowhile: function( test, action ){ - return function(v){ - var acc = v; - while( test(acc) ){ acc = action(acc); } - return acc; - }; - }, - dountil: function( test, action ){ - return Y.ops.dowhile( function(v){ return !test(v); }, action ); - }, - forloop: function( test, action, pretest, posttest ){ - pretest = pretest || Y.ops.I; - posttest = posttest || Y.ops.I; - return function(v){ - for(var acc = pretest(v); test(acc); acc = posttest(acc) ){ - acc = action(acc); - } - return acc; - }; - }, - repeat: function( action, n ){ - return function(v){ - for( var acc = v, i = 0; i < n; ++i ){ acc = action(acc); } - return acc; - }; - }, - maybe: function( pitcher, catcher ){ - return function(){ - var args = Y(arguments); - try { - return pitcher.apply( this, args ); - } catch(e) { - args.unshift(e); - return catcher.apply( this, args ); - } - }; - } -}; - - -})(this.Y); diff --git a/src/Y/y-class.js b/src/Y/y-class.js index d297e05..ee07b8c 100644 --- a/src/Y/y-class.js +++ b/src/Y/y-class.js @@ -118,9 +118,10 @@ Y.subclass = Class; Class.instantiate = function(){ var instance = this.fabricate(); - if ( instance.init ) - return instance.init.apply(instance, arguments); - else + if ( instance.init ) { + var r = instance.init.apply(instance, arguments); + return (r !== undefined ? r : instance); + } else return instance; }; diff --git a/src/Y/y-core.js b/src/Y/y-core.js index 10a9b26..995751b 100644 --- a/src/Y/y-core.js +++ b/src/Y/y-core.js @@ -1,5 +1,6 @@ Y.reduce = reduce; +Y.set = set; Y.attr = attr; Y.extend = extend; diff --git a/src/Y/y-function.js b/src/Y/y-function.js index ef502f9..01edb5a 100644 --- a/src/Y/y-function.js +++ b/src/Y/y-function.js @@ -18,7 +18,7 @@ Y.extend(YFunction.prototype, { init : YFunction, reduce : methodize(Y.reduce), extend : methodize(Y.extend), - end : function(){ return this; } + end : function end(){ return this; } }); YFunction.prototype.attr = methodize(Y.attr); // YFunction.prototype.extend = methodize(Y.extend); @@ -185,28 +185,40 @@ function genericize( fn ) { // XXX: hashCode() Y.memoize = memoize; YFunction.prototype.memoize = methodize(memoize); -function memoize(fn){ + +/** + * @param {Function} fn Function to memorize. + * @param {Array -> String} [keyfn] Serializes an array of arguments to a string. By default, joins with three nulls. + * @param {Object} [cacher] Object on which to store the memorization cache for lookups. Useful for meta-caches. Defaults to the memorized function. + * @param {String} [cacheName="cache"] Property this cache will be stored under. + */ +function memoize(fn, keyfn, cacher, cacheName){ if (fn.__memoized__) return fn.__memoized__; - var cache; - fn.__memoized__ = memorizer; - function memorizer(){ - // I'd like to use toJSON here, but that won't work cross-browser. - var key = Y(arguments).join('\0'); - if ( !(key in cache) ) - cache[key] = fn.apply(this, arguments); - return cache[key]; - } + var m = + fn.__memoized__ = + function memorizer(){ + var key = keyfn(Y(arguments)) + , cache = cacher[cacheName] ; + if ( !(key in cache) ) + cache[key] = fn.apply(this, arguments); + return cache[key]; + }; - memorizer.purge = purge; - function purge(){ - memorizer.cache = cache = {}; - } + // toJSON would be a better alternative, but that won't work cross-browser + keyfn = keyfn || function keyfn(args){ return args.join('\0\0\0'); }; + cacher = cacher || m; + cacheName = cacheName || 'cache'; - purge(); - memorizer.__wraps__ = fn; + m.__wraps__ = fn; + m.purge = function purge(){ + var cache = cacher[cacheName]; + cacher[cacheName] = {}; + return cache; + }; - return memorizer; + m.purge(); + return m; } // Memorized to reduce eval costs @@ -214,28 +226,52 @@ var _ofArityWrapper = YFunction._ofArityWrapper = memoize(function(n, limit){ - return eval('(function(fn){ '+ + return eval('(function '+(limit ? 'limited' : 'artized')+'(fn){ '+ 'return function('+Y.range(n).map( Y.op.add('$') ).join(',')+'){ '+ 'return fn.apply(this,' + (limit ? 'Y(arguments).slice(0,'+n+')' : 'arguments')+ '); }; })'); }); -YFunction.prototype.aritize = function(n){ - return _ofArityWrapper(n, false)(this); +YFunction.prototype.aritize = +function aritize(n){ + var fn = this + , cache = fn.__aritized__ ; + + if (fn.length === n) + return fn; + + if ( !cache ) + cache = fn.__aritized__ = {}; + else if ( cache[n] ) + return cache[n]; + + return ( cache[n] = _ofArityWrapper(n, false)(fn) ); }; -YFunction.prototype.limit = function(n){ - return _ofArityWrapper(n, true)(this); +YFunction.prototype.limit = +function limit(fn, n){ + var fn = this + , cache = fn.__limited__ ; + + if (fn.length === n) + return fn; + + if ( !cache ) + cache = fn.__limited__ = {}; + else if ( cache[n] ) + return cache[n]; + + return ( cache[n] = _ofArityWrapper(n, true)(fn) ); }; /** * Filter the arguments passed to the wrapper function */ -YFunction.prototype.mask = mask; -function mask(){ - -} +// YFunction.prototype.mask = mask; +// function mask(){ +// +// } @@ -270,6 +306,7 @@ function mixinNames(o, Donor, names, override, yWrap){ YFunction(Y); Y(Y.reduce); +Y(Y.set); Y(Y.attr); Y(Y.extend); Y.reduce(YFunction.prototype, function(_,fn,name){ diff --git a/src/Y/y-number.js b/src/Y/y-number.js index c390bb5..dba6137 100644 --- a/src/Y/y-number.js +++ b/src/Y/y-number.js @@ -8,13 +8,13 @@ YCollection.subclass('YNumber', { YCollection.init.call(this, o); }, - compare : function(n){ + compare : function compare(n){ var m = this._o; return (m > n ? 1 : (m < n ? -1 : 0 )); }, - toString : function(){ + toString : function toString(){ return this.end()+''; } }); diff --git a/src/Y/y-string.js b/src/Y/y-string.js index 57d2ddc..572d443 100644 --- a/src/Y/y-string.js +++ b/src/Y/y-string.js @@ -40,7 +40,7 @@ var YString = Y.YString = YCollection.subclass('YString', { - init : function(o){ + init : function init(o){ if (!o) o = ""; this._o = o; YCollection.init.call(this, o); @@ -52,7 +52,7 @@ YCollection.subclass('YString', { startsWith: startsWith, endsWith: endsWith, - compare : function(n){ + compare : function compare(n){ var m = this._o; return (m > n ? 1 : (m < n ? -1 : 0 )); diff --git a/src/lessly/bitgrid.js b/src/lessly/bitgrid.js index 37efb7b..815b3b5 100644 --- a/src/lessly/bitgrid.js +++ b/src/lessly/bitgrid.js @@ -21,7 +21,7 @@ function toY(y){ return Math.floor(y/CELL_Y); } * TODO: Optimize set operations */ BitGrid = new Y.Class('BitGrid', { - init : function(w, h){ + init : function init(w, h){ this.width = w; this.height = h; @@ -37,7 +37,7 @@ BitGrid = new Y.Class('BitGrid', { // } }, - _getCol : function(x){ + _getCol : function _getCol(x){ var xi = toX(x) , cells = this.cells , xcell = cells[xi] @@ -45,7 +45,7 @@ BitGrid = new Y.Class('BitGrid', { return xcell || (cells[xi] = []); }, - _getCell : function(x,y){ + _getCell : function _getCell(x,y){ var xi = toX(x) , cells = this.cells , xcell = cells[xi] @@ -53,7 +53,7 @@ BitGrid = new Y.Class('BitGrid', { return (xcell ? xcell[ toY(y) ] || 0 : 0); }, - _setCell : function(x,y, b){ + _setCell : function _setCell(x,y, b){ this._getCol(x)[ toY(y) ] = b; }, @@ -64,7 +64,7 @@ BitGrid = new Y.Class('BitGrid', { * function iter(acc, cell, x, y) -> new acc * Returns the final accumulated value. */ - reduce : function(iter, acc, context){ + reduce : function reduce(iter, acc, context){ context = context || this; var cells = this.cells , xi_max = toX(this.width) @@ -85,7 +85,7 @@ BitGrid = new Y.Class('BitGrid', { * iter has sig: * function iter(cell, x, y) -> new value */ - map : function(iter, context){ + map : function map(iter, context){ context = context || this; var col, cell , cells = this.cells @@ -109,7 +109,7 @@ BitGrid = new Y.Class('BitGrid', { * iter has sig: * function iter(cell, x, y) -> void */ - each : function(iter, context){ + each : function each(iter, context){ context = context || this; var col , cells = this.cells @@ -125,18 +125,18 @@ BitGrid = new Y.Class('BitGrid', { return this; }, - isSet : function(x,y){ + isSet : function isSet(x,y){ return this._getCell(x,y) & toBits(x,y); }, - addPoint : function(x,y){ + addPoint : function addPoint(x,y){ // if (x < 0 || x > this.width || y < 0 || y > this.height) // return undefined; this._getCol(x)[ toY(y) ] |= toBits(x,y); return this; }, - addRect : function(x1,y1, x2,y2){ + addRect : function addRect(x1,y1, x2,y2){ var cells = this.cells , x_min = toX(x1), x_max = toX(x2) , y_min = toY(y1), y_max = toY(y2) @@ -168,7 +168,7 @@ BitGrid = new Y.Class('BitGrid', { return this; }, - addGrid : function(other){ + addGrid : function addGrid(other){ var cells = this.cells , o_cells = other.cells , x_len = o_cells.length @@ -188,7 +188,7 @@ BitGrid = new Y.Class('BitGrid', { return this; }, - add : function(x1,y1, x2,y2){ + add : function add(x1,y1, x2,y2){ var L = arguments.length; if (L == 4) { this.addRect(x1,y1, x2,y2); @@ -202,11 +202,11 @@ BitGrid = new Y.Class('BitGrid', { return this; }, - subtractPoint : function(x,y){ + subtractPoint : function subtractPoint(x,y){ this._getCol(x)[ toY(y) ] &= CELL_MASK ^ toBits(x,y); }, - subtractRect : function(x1,y1, x2,y2){ + subtractRect : function subtractRect(x1,y1, x2,y2){ var cells = this.cells , x_min = toX(x1), x_max = toX(x2) , y_min = toY(y1), y_max = toY(y2) @@ -238,7 +238,7 @@ BitGrid = new Y.Class('BitGrid', { return this; }, - subtractGrid : function(other){ + subtractGrid : function subtractGrid(other){ var cells = this.cells , o_cells = other.cells , x_len = o_cells.length @@ -260,7 +260,7 @@ BitGrid = new Y.Class('BitGrid', { return this; }, - subtract : function(x1,y1, x2,y2){ + subtract : function subtract(x1,y1, x2,y2){ var L = arguments.length; if (L == 4) { this.subtractRect(x1,y1, x2,y2); @@ -274,32 +274,32 @@ BitGrid = new Y.Class('BitGrid', { return this; }, - intersection : function(other){ + intersection : function intersection(other){ return this.reduce(function(g, cell, x, y){ g._setCell(x,y, cell & other._getCell(x,y)); return g; }, new Grid(this.width, this.height)); }, - union : function(other){ + union : function union(other){ return this.reduce(function(g, cell, x, y){ g._setCell(x,y, cell | other._getCell(x,y)); return g; }, new Grid(this.width, this.height)); }, - difference : function(other){ + difference : function difference(other){ return this.reduce(function(g, cell, x, y){ g._setCell(x,y, cell & (CELL_MASK ^ other._getCell(x,y))); return g; }, new Grid(this.width, this.height)); }, - symmetricDifference : function(grid){ + symmetricDifference : function symmetricDifference(grid){ return this.difference(grid).addGrid( grid.difference(this) ); }, - toDiagram : function(label, selector){ + toDiagram : function toDiagram(label, selector){ var self = this, el = $('
'), @@ -371,7 +371,7 @@ BitGrid = new Y.Class('BitGrid', { }); }, - toString : function(){ + toString : function toString(){ return 'Grid['+this.width+','+this.height+']()'; } }); diff --git a/src/lessly/draw.js b/src/lessly/draw.js index b23b5b0..2024499 100644 --- a/src/lessly/draw.js +++ b/src/lessly/draw.js @@ -31,7 +31,7 @@ function YProcessing(P){ } var methods = { init : YProcessing, - rectXY : function(x1,y1, x2,y2){ + rectXY : function rectXY(x1,y1, x2,y2){ return this.rect( x1,y2, x2-x1,y2-y1 ); } diff --git a/src/lessly/log.js b/src/lessly/log.js index 7125be6..b1d85bb 100644 --- a/src/lessly/log.js +++ b/src/lessly/log.js @@ -5,7 +5,7 @@ Log = new Y.Class('Log', { prefix : '' }, - init : function(el, options){ + init : function init(el, options){ this.el = el; var o = Y({}, this.DEFAULT_OPTIONS, options || {}); this.options = o.end(); @@ -25,7 +25,7 @@ Log = new Y.Class('Log', { return Logger; }, - ready : function(evt){ + ready : function ready(evt){ var self = this , el = self.el = $(self.el) , n = this.id @@ -52,13 +52,13 @@ Log = new Y.Class('Log', { }); }, - log : function(){ + log : function log(){ var msgs = this.msgs; msgs.append('
'+this.prefix+Y(arguments).join(' ')+'
'); if (this.options.autoScroll) msgs.scrollTop(msgs.attr('scrollHeight')); }, - clear : function(){ + clear : function clear(){ this.msgs.empty().append(this.meta_spacer); } }); diff --git a/src/lessly/viewport.js b/src/lessly/viewport.js index 9a82530..b6de63e 100644 --- a/src/lessly/viewport.js +++ b/src/lessly/viewport.js @@ -13,7 +13,7 @@ Y.subclass(Viewport, Y.event.Emitter, { * Creates Processing instance and begins dispatch. * Clients must listen for `setup` prior to init(). */ - init : function(){ + init : function init(){ var self = this; self.processing = new Processing( self.canvas, @@ -34,7 +34,7 @@ Y.subclass(Viewport, Y.event.Emitter, { }); }, - dispatchEvent : function(evt){ + dispatchEvent : function dispatchEvent(evt){ // log.debug('dispatchEvent('+evt.type+')', this); this.getQueue(evt.type).each(function(fn){ fn.call(evt.target, evt, evt.data.api, evt.data.constants); diff --git a/src/portal/layer.js b/src/portal/layer.js index 31ac03d..244a684 100644 --- a/src/portal/layer.js +++ b/src/portal/layer.js @@ -1,28 +1,5 @@ (function($, undefined){ -// Install CSS styles -$(function(){ - $('