Starts work on transform stack.
authordsc <david.schoonover@gmail.com>
Thu, 4 Nov 2010 05:46:26 +0000 (22:46 -0700)
committerdsc <david.schoonover@gmail.com>
Thu, 4 Nov 2010 05:46:26 +0000 (22:46 -0700)
35 files changed:
css/lttl.css
index.php
notes.md
src/Y/core.js
src/Y/modules/y.control.js [new file with mode: 0644]
src/Y/modules/y.event.js
src/Y/modules/y.op.js [deleted file]
src/Y/y-class.js
src/Y/y-core.js
src/Y/y-function.js
src/Y/y-number.js
src/Y/y-string.js
src/lessly/bitgrid.js
src/lessly/draw.js
src/lessly/log.js
src/lessly/viewport.js
src/portal/layer.js
src/portal/shape.js
src/portal/transform.js [new file with mode: 0644]
src/portal/util/eventloop.js
src/portal/util/fps.js
src/portal/util/loc.js
src/portal/util/pointquadtree.js
src/portal/util/quadtree.js
src/portal/util/rbtree.js
src/tanks/game/game.js
src/tanks/game/map.js
src/tanks/game/player.js
src/tanks/globals.js [new file with mode: 0644]
src/tanks/ui.js
src/tanks/unit/tank.js
src/tanks/unit/thing.js
src/tanks/util/calc.js [new file with mode: 0644]
src/tanks/util/grid.js
src/tanks/util/pathmap.js

index 0bd2596..5b26d43 100644 (file)
@@ -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; }
 
index e2b5d7a..f22a776 100644 (file)
--- 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"
     
index 1d5c4a2..dc5d10b 100644 (file)
--- 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
index bc22ed7..4536fb6 100644 (file)
@@ -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 (file)
index 0000000..84631ef
--- /dev/null
@@ -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);
index 8b8cdce..7e085cf 100644 (file)
@@ -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 (file)
index d8260a4..0000000
+++ /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);
index d297e05..ee07b8c 100644 (file)
@@ -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;
     };
     
index 10a9b26..995751b 100644 (file)
@@ -1,5 +1,6 @@
 
 Y.reduce = reduce;
+Y.set    = set;
 Y.attr   = attr;
 Y.extend = extend;
 
index ef502f9..01edb5a 100644 (file)
@@ -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){
index c390bb5..dba6137 100644 (file)
@@ -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()+'';
     }
 });
index 57d2ddc..572d443 100644 (file)
@@ -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 ));
index 37efb7b..815b3b5 100644 (file)
@@ -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