__all__ = ('ResolutionError', 'Module', 'JSResolver',)
-import sys, re
+import sys, re, json
from itertools import chain, repeat
from collections import defaultdict
from subprocess import Popen, check_output, STDOUT, PIPE
import pystache
+AT_REQUIRE_PAT = re.compile(r'//@require\(\s*([\'"])(.*?)\1\s*\)')
LINE_COMMENT_PAT = re.compile(r'(.*?)(//.*?)(?:\n|$)')
PAIR_COMMENT_PAT = re.compile(r'(.*?)(/\*.*?\*/)')
REQUIRE_PAT = re.compile(r'\brequire\(\s*([\'"])(.*?)\1\s*\)')
+
ROOT = path(__file__).abspath().dirname().dirname()
LIB = ROOT/'lib/cjs'
CWD = path('.')
BLANK = path('')
+
MODULE_TEMPLATE = ''
+DUMMY_TEMPLATE = ''
+DEPS_TEMPLATE = ''
try:
- with (LIB/'module.js').open('rU') as f :
+ with (LIB/'module.js').open('rU') as f:
MODULE_TEMPLATE = f.read()
+ with (LIB/'dummy.js').open('rU') as f:
+ DUMMY_TEMPLATE = f.read()
+ with (LIB/'deps.js').open('rU') as f:
+ DEPS_TEMPLATE = f.read()
except Exception as ex:
print
- print 'Error reading module template file!'
+ print 'Error reading template file!'
print ' ROOT={ROOT}, LIB={LIB}, module.js={}'.format(LIB/'module.js', **locals())
raise
return str(id)
-class Repo(object):
- def __init__(self, filepath, url):
- self.path = filepath
- self.url = url
-
- def __repr__(self):
- return 'Repo({}, url={})'.format(self.path, self.url)
-
- def __str__(self):
- return repr(self)
-
-
class Module(Bunch):
DEFAULTS = {
- 'id' : '', # Canonical Module ID
- 'file' : None, # path
- 'name' : '', # Module Name
- 'uri' : '', # Module URI (TODO)
- 'text' : None, # Unmodified module text
- 'contents' : None, # Compiled module text
- '_requires' : None,
- 'outpath' : None,
+ 'id' : '', # Canonical Module ID
+ 'file' : None, # path
+ 'name' : '', # Module Name
+ 'uri' : '', # Module URI (TODO)
+ 'text' : None, # Unmodified module text
+ 'contents' : None, # Compiled module text
+ 'outpath' : None, # Build directory
+ '_requires' : None,
+ '_at_requires' : None,
}
- def __init__(self, id, file, uri='', out=None, compile=True):
+ def __init__(self, id, file, uri=BLANK, out=None, compile=True):
self.update(Module.DEFAULTS)
self.id = id
self.file = path(file)
- self.name = self.id.split('/').pop().capitalize()
+ self.name = re.subn(r'\W', '', self.id.split('/').pop().capitalize())[0]
if out:
- out = (path(out) / self.id) + '.js'
+ out = path(out)
+ outpath = (out / self.id) + '.js'
else:
- out = self.file.replace('.cjs', '.js')
- self.outpath = path(out)
- self.uri = uri
+ out = BLANK
+ outpath = self.file.replace('.cjs', '.js')
+ self.outpath = path(outpath)
+ self.uri = str(out/uri/self.id)+'.js'
- if compile: self.compile()
+ self.compile()
# print "new!", repr(self)
def compile(self):
- # if uri: self.uri = uri.format(**self) # TODO: calc uri
-
- if not self.file.endswith('.cjs'):
- return self
-
outdir = self.outpath.dirname()
if not outdir.exists():
outdir.makedirs()
with self.file.open('rU') as f:
txt = f.read()
self['text'] = txt
- self['contents'] = pystache.render(MODULE_TEMPLATE, self)
+ template = MODULE_TEMPLATE if self.file.endswith('.cjs') else DUMMY_TEMPLATE
+ self['contents'] = pystache.render(template, self)
return self[attr]
@property
def contents(self):
return self.read('contents')
+ def findDirectives(self, text):
+ for areq in AT_REQUIRE_PAT.finditer(text):
+ yield canonicalise(areq.group(2), self)
+
def findRequires(self, text):
text = LINE_COMMENT_PAT.subn(r'\1 ', text)[0]
text = PAIR_COMMENT_PAT.subn(r'\1 ', text)[0]
for mreq in REQUIRE_PAT.finditer(text):
yield canonicalise(mreq.group(2), self)
+ def calcRequires(self, attr):
+ if self._requires is None or self._at_requires is None:
+ self._at_requires = list(self.findDirectives(self.text))
+ self._requires = list(self.findRequires(self.text))
+ return getattr(self, attr)
+
+ @property
+ def atRequires(self):
+ return self.calcRequires('_at_requires')
+
+ @property
+ def nonAtRequires(self):
+ return self.calcRequires('_requires')
+
@property
def requires(self):
- if self._requires is None:
- self._requires = list(self.findRequires(self.text))
- return self._requires
+ return self.calcRequires('_at_requires') + self._requires
def __hash__(self):
return hash(self.id)
req = cjs.lookup(query, mod)
if req not in seen:
queue.append(req)
+ if cjs.deps_name:
+ cjs.genDepLoader()
return cjs
repos = []
modules = {} # id -> Module
- _graph = None # id -> set(dependants)
-
-
- def __init__(self, repos, out='build', clean=True):
- self.modules = {}
- self.repos = set( path(path(p).abspath()+'/') for p in repos)
- self.out = None if out is '' else out
+ _graph = None # id -> set(dependants)
+ _at_graph = None # id -> set(dependants)
+
+ def __init__(self, repos, out='build', deps_name=None, clean=True, **options):
+ self.modules = {}
+ self.options = options
+ self.deps_name = deps_name
+ self.repos = set( path(path(p).abspath()+'/') for p in repos)
+ self.out = None if out is '' else out
if self.out is not None and clean:
out = path(self.out)
- if out.exists(): out.rmtree()
+ for f in out.glob('*'):
+ if f.isdir():
+ f.rmtree()
+ elif f.isfile():
+ f.remove()
def register(self, id, file):
mod = self.modules[id] = Module(id=id, file=file, out=self.out)
for k, mod in self.modules.iteritems():
yield k, mod
- @property
- def graph(self):
+ def calcGraph(self, attr):
if self._graph is None:
- graph = self._graph = defaultdict(set)
+ graph = self._graph = defaultdict(set)
+ atgraph = self._at_graph = defaultdict(set)
for mod in self.modules.values():
- for req in mod.requires:
+ for req in mod.nonAtRequires:
graph[req].add(mod)
- return self._graph
+ for req in mod.atRequires:
+ atgraph[req].add(mod)
+ return getattr(self, attr)
@property
- def deplist(self):
- return '\n'.join( '%s %s' % (id, dep.id) for (id, deps) in self.graph.iteritems() for dep in deps )
+ def graph(self):
+ return self.calcGraph('_graph')
@property
- def dependencies(self):
+ def atGraph(self):
+ return self.calcGraph('_at_graph')
+
+ def tsort(self, graph):
p = Popen(['tsort'], stderr=STDOUT, stdin=PIPE, stdout=PIPE)
- p.stdin.write( self.deplist )
+ deps = '\n'.join( '%s %s' % (id, dep.id) for (id, deps) in graph.iteritems() for dep in deps )
+ p.stdin.write(deps)
p.stdin.close()
if p.wait() != 0:
raise ResolutionError('Cannot resolve dependencies! Requirements must be acyclic!')
- return p.stdout.read().strip().split('\n')
+ return p.stdout.read()
+
+ @property
+ def dependencies(self):
+ deps = (self.tsort(self.atGraph)+self.tsort(self.graph)).strip().split('\n')
+ for i, dep in reversed(list(enumerate(deps[:]))):
+ try:
+ idx = deps.index(dep, 0, i-1)
+ if i != idx:
+ del deps[idx]
+ except ValueError: pass
+ return deps
+
+ def dumpDependencies(self):
+ column = Popen(['column', '-s', '\t', '-t'], stderr=sys.stderr, stdin=PIPE, stdout=PIPE)
+ mods = self.modules.values()
+ for mod in sorted(mods, key=lambda m: len(m.requires), reverse=True):
+ column.stdin.write('%s\t->\t%r\n' % (mod, sorted(mod.requires)))
+ # print '%s\t->\t%r' % (mod, sorted(mod.requires))
+ column.stdin.close()
+ if column.wait() != 0:
+ print >> sys.stderr, 'Some sort of error has occurred!'
+ return column.stdout.read()
- def cat(self):
- for dep in self.dependencies:
- print self.modules[dep].contents
+ def genDepLoader(self):
+ with (path(self.out)/self.deps_name).open('w') as deps:
+ deps.write( pystache.render(DEPS_TEMPLATE, uris=json.dumps(self.uris)) )
+ @property
+ def uris(self):
+ return [ self.modules[d].uri for d in self.dependencies ]
+
+ @property
+ def scriptTags(self):
+ return '\n'.join( '<script src="{}" type="text/javascript"></script>'.format(uri) for uri in self.uris )
usage = 'usage: %prog [options] file[...] [-- [repo_path[...]]]',
description = 'Compiles CommonJS modules.',
version = '%prog'+" %i.%i.%i" % __version__)
- parser.add_option("-p", "--repo-paths", dest='repos', default='',
+ parser.add_option("-p", "--repo-paths", default='',
help="Comma-seperated paths to search for unqualified modules. "
"If a path contains :, the portion afterward will be taken as the repo URL. [default: .]")
parser.add_option("-o", "--out", default='build',
help="Root directory to write compiled JS files. Specify '' to write to module's dir. [default: build]")
parser.add_option("-C", "--no-clean", dest='clean', default=True, action="store_false",
help="Do not clean the out-dir of compiled files. [default: False if -o, True otherwise]")
- parser.add_option("-d", "--print-deps", default=False, action="store_true",
+ parser.add_option("--print-deps", default=False, action="store_true",
help="Prints module dependencies after compiling. [default: %default]")
+ parser.add_option("-g", "--gen-deps-script", dest='deps_name', default=None,
+ help="Generates a JS script with the given name which doc-writes tags for this set of modules.")
+ parser.add_option("-s", "--script-tags", default=False, action="store_true",
+ help="Emits script-tags for this set of modules in dependency order. [default: %default]")
(options, args) = parser.parse_args()
(files, sep, repos) = partition(sys.argv, '--')
files = filter(lambda f: f in args, files)
repos = filter(lambda f: f in args, repos)
- repos.extend( filter(None, options.repos.split(',')) )
+ repos.extend( filter(None, options.repo_paths.split(',')) )
# print 'files:', files, 'repos:', (repos or ['.'])
- js = CommonJS.discover(files=files, repos=repos or ['.'], **options.__dict__)
+ try:
+ js = CommonJS.discover(files=files, repos=repos or ['.'], **options.__dict__)
+ except ResolutionError as ex:
+ print >> sys.stderr, str(ex)
+ return 1
+
+ if options.script_tags:
+ print js.scriptTags
if options.print_deps:
- column = Popen(['column', '-s', '\t', '-t'], stderr=sys.stderr, stdin=PIPE, stdout=PIPE)
- mods = js.modules.values()
- for mod in sorted(mods, key=lambda m: len(m.requires), reverse=True):
- column.stdin.write('%s\t->\t%r\n' % (mod, sorted(mod.requires)))
- # print '%s\t->\t%r' % (mod, sorted(mod.requires))
-
- column.stdin.close()
- if column.wait() != 0: print 'Some sort of error has occurred!'
- print column.stdout.read()
+ print >> sys.stderr, 'All Dependencies:'
+ print >> sys.stderr, js.dumpDependencies()
+ print >> sys.stderr, ''
+ print >> sys.stderr, 'Resolution:'
+ print >> sys.stderr, '\n'.join(js.dependencies)
return 0
- Tanks seem to get stuck on some corners
# TODOs
-- How-to overlay
-- Restart level button
-- AI: Line-of-sight for dodging, firing
+- change @require to @ensure
+
- AI: Don't shoot if it'll kill you or your friends
- AI: Lead shots on moving targets
- Config-driven unit-types (name, stats, properties; pointers to behavior scripts, assets)
</div></div>
<div id="scripts">
-<?php require "tanks.php"; Tanks::writeTags( Tanks::ALL_SCRIPTS ); ?>
+<?php
+ /* require "tanks.php"; Tanks::writeTags( Tanks::ALL_SCRIPTS ); */
+ require "tanks.php"; Tanks::writeLoaders();
+?>
</div>
</body>
--- /dev/null
+{{{uris}}}.forEach(function(uri){
+ document.write('<scr'+'ipt src="'+uri+'" type="text/javascript"></scr'+'ipt>');
+});
--- /dev/null
+require.install(
+// Module ID
+'{{{id}}}',
+
+// Module metadata
+{
+ 'name' : '{{{name}}}',
+ 'id' : '{{{id}}}',
+ 'uri' : '{{{uri}}}'
+},
+// Dummy module: setup does nothing
+function setup{{{name}}}(require, exports, module){});
+
+{{{text}}}
require.install(
// Module ID
-'{{id}}',
+'{{{id}}}',
// Module metadata
{
- 'name' : '{{name}}',
- 'id' : '{{id}}',
- 'uri' : '{{uri}}'
+ 'name' : '{{{name}}}',
+ 'id' : '{{{id}}}',
+ 'uri' : '{{{uri}}}'
},
// Module Setup function
-function setup{{name}}(require, exports, module){
+function setup{{{name}}}(require, exports, module){
-{{text}}
+{{{text}}}
});
\ No newline at end of file
--- /dev/null
+jquery-1.4.3.min.js
\ No newline at end of file
// Inspired by John Resig's "Simple Class Inheritence" -- http://ejohn.org/blog/simple-javascript-inheritance/
-var Y = require('Y').Y
-, type = require('Y/type')
+var type = require('Y/type')
+, YFunction = require('Y/types/function').YFunction
+, core = require('Y/core')
+, slice = core.slice
+
, KNOWN_CLASSES = type.type.KNOWN_CLASSES
, classToString = function toString(){ return this.className+"()"; }
;
prototype[k] = members[k];
}
- if (prototype.init) NewClass.init = Y(prototype.init);
+ if (prototype.init) NewClass.init = YFunction(prototype.init);
KNOWN_CLASSES[className] = NewClass;
-
-/// Other Class Utilities ///
-
-function bindName(v, k){
- if ( isFunction(v) )
- this[k] = Y(v).bind(this);
-}
-// bindName = Y(bindName).curry();
-
-function bindAll(o, names){
- var names = new Y(arguments, 1);
- Y(names.size() ? names.generate(Y.op.get(o)) : o).forEach( bindName, o );
- return o;
-}
-
-// Y.chainDelegates = chainDelegates;
-function chainDelegates(type, name){
- var names = Y(arguments, 1),
- proto = type.prototype;
- names.forEach(function(name){
- proto[name] = function(){
- var o = this._o || this;
- o[name].apply(o, Y(arguments));
- return this;
- };
- });
- return type;
-}
-
-// Y.mixinNames = mixinNames;
-function mixinNames(o, Donor, names, override, yWrap){
- var target = ( isFunction(o) ? o.prototype : o)
- , proto = ( isFunction(Donor) ? Donor.prototype : Donor);
-
- // Need a closure to capture the name
- names.forEach(function(name){
- if ( isFunction(proto[name]) && (override || !target[name]) )
- target[name] = function(){
- var r = proto[name].apply(this._o || target, arguments);
- return (yWrap ? Y(r) : r);
- };
- });
-
- return o;
-}
-
exports['Class'] =
exports['subclass'] = Class;
exports['instantiate'] = Class.instantiate.bind(Class);
exports['fabricate'] = Class.fabricate.bind(Class);
-
-exports['YBase'] = YBase;
-exports['bindAll'] = bindAll;
-exports['chainDelegates'] = chainDelegates;
-exports['mixinNames'] = mixinNames;
+exports['YBase'] = YBase;
// Generic Collection Functions
+var undefined
+, globals = (function(){ return this; })()
+, _Function = globals.Function
+, _Array = globals.Array
+, PT = "prototype"
+, slice = _Array[PT].slice
+;
+
+// function slice(a){
+// return _asl.apply(a, _asl.call(arguments, 1));
+// }
function notWrapped(fn){
var self = arguments.callee.caller;
if ( !o )
return acc;
- fn = Function.toFunction(fn);
+ fn = _Function.toFunction(fn);
var cxt = arguments[3] || o;
if ( notWrapped(o.reduce) )
return o.reduce.apply(o, [fn, acc, cxt]);
if ( !o )
return o;
- fn = Function.toFunction(fn);
+ fn = _Function.toFunction(fn);
var acc = {}, cxt = arguments[2] || o;
if ( notWrapped(o.map) )
return o.map.apply(o, [fn, cxt]);
if ( !o )
return o;
- fn = Function.toFunction(fn);
+ fn = _Function.toFunction(fn);
var acc = {}, cxt = arguments[2] || o;
if ( notWrapped(o.filter) )
return o.filter.apply(o, [fn, cxt]);
exports['dset'] = dset;
exports['dattr'] = dattr;
exports['dextend'] = dextend;
+exports['slice'] = slice;
\ No newline at end of file
+// -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
/// Import our external deps first ///
-// require('lessly/future');
-// require('functional/to-function');
+//@require('lessly/future');
+//@require('functional/to-function');
/// Set up core and utilities ///
var core = require('Y/core')
// Attach core & type to Y
core.extend(Y, core, type);
+delete Y.slice; // grr
// Make top-level setters refer to the delegating versions
Y['core'] = core;
// Curry all operators
var op = require('Y/op');
core.forEach(op, YFunction);
-Y['op'] = op.extend({}, core.map(yfn.curry, op));
+Y['op'] = op['curried'] = op.extend({}, core.map(yfn.curry, op));
// Y['op'] = core.reduce(op, function(Yop, fn, k){
// Yop[k] = yfn.curry(fn);
// return Yop;
-(function(Y, undefined){ if (!Y) return;
-
var _document = document
+, Y = require('Y').Y
, enc = encodeURIComponent
, dec = decodeURIComponent
-, ns = Y.cookies = {}
;
-ns.get =
+Y['cookies'] = exports;
+
+exports['get'] =
function getCookie(k){
var cookies = Y(_document.cookie+'').fromKV('; ');
if (k !== undefined)
return cookies;
};
-ns.set =
+exports['set'] =
function setCookie(k, v, expires, path){
expires = 'expires='+(expires || "Sun, 24-Mar-2024 11:11:11 GMT");
path = 'path='+(path || "/");
};
// TODO: YCollection methods on ns over kv pairs.
-
-})(this.Y);
-(function(Y, undefined){
-
-var
-ns = Y.event = {}
+Y['event'] = exports;
/**
* A simple event.
* TODO: If DOM event, wrap with consistent API.
* TODO: use jQuery if present to wrap events.
*/
-, YEvent = ns.YEvent =
+var YEvent = exports['YEvent'] =
Y.YObject.subclass('YEvent', {
init : function init( type, target, trigger, data ){
data = data || {};
delegate[k] = methods[k].bind(this);
return delegate;
}
-}
+},
-, Emitter = ns.Emitter =
+Emitter = exports['Emitter'] =
Y.YObject.subclass('Emitter',
Y.extend({
'init' : function(target, parent){
// Global Event Hub
Emitter.global = new Emitter()
-Emitter.global.decorate(Y.event);
-
-
-})(this.Y);
+Emitter.global.decorate(exports);
-(function(Y){
+var Y = require('Y').Y;
function toJSON(o, k){
var prefix = typeof(k) === 'string' ? '"'+k+'":' : '',
}
function install(json_fn){
- var args = new Y(arguments),
- tojson = args.shift();
- args.each(function(YThing){
+ var args = Y(arguments,1);
+ args.forEach(function(YThing){
YThing.prototype.toJSON = json_fn;
});
}
// Collections
function reducer(acc, v, k, o){
- var json = toJSON(v, Y.is.array(o) ? 0 : k);
+ var json = toJSON(v, Y.isArray(o) ? 0 : k);
return json ? (acc ? acc+','+json : json) : acc;
}
// Public API
-Y.toJSON = toJSON;
+Y['toJSON'] = exports['toJSON'] = toJSON;
-install( yNoJSON, Y.YGeneric, Y.YFunction, Y.YRegExp );
-install( yToJSON, Y, Y.YBoolean, Y.YNumber );
+// install( yNoJSON, Y.YBase, Y.YFunction, Y.YRegExp );
+// install( yToJSON, Y, Y.YBoolean, Y.YNumber );
+install( yNoJSON, Y.YBase, Y.YFunction );
+install( yToJSON, Y, Y.YNumber );
install( quoteJSON, Y.YString );
-install( collectJSON.partial('{', '}'), Y.YCollection );
+install( collectJSON.partial('{', '}'), Y.YCollection, Y.YObject );
install( collectJSON.partial('[', ']'), Y.YArray );
-
-
-})(this.Y);
-(function(Y, undefined){ if (!Y) return;
-
-var enc = encodeURIComponent
+var Y = require('Y').Y
+, enc = encodeURIComponent
, dec = decodeURIComponent
;
}, {});
};
-})(this.Y);
/* A subset of the functional operators, used in Y's core */
-var Y = require('Y').Y
-, core = require('Y/core')
+var core = require('Y/core')
+, slice = core.slice
, op = { // XXX: Make these function statements?
// comparison
nop: function(x){},
I: function(x){ return x; },
K: function(k){ return function(){ return k; }; },
+ nth: function(n){ return function(){ return arguments[n]; }; },
val: function(def,o){ return o !== undefined ? o : def; },
ok: function(o){ return o !== undefined && o !== null; },
set: core.set, // set( o, key, value, def )
attr: core.attr, // attr( o, key, value, def )
method: function(name){
- var args = Y(arguments,1);
+ var args = slice.call(arguments,1);
return function(obj){
if (obj && obj[name])
- return obj[name].apply( obj, args.concat(Y(arguments)) );
+ return obj[name].apply( obj, args.concat(slice.call(arguments)) );
else
return obj;
};
-var Y = require('Y').Y;
+var YCollection = require('Y/types/collection').YCollection
+, mixin = require('Y/utils').mixin
+, slice = require('Y/core').slice
+;
exports['YArray'] =
-Y.YCollection.subclass('YArray', function(YArray){
- var yclass = require('Y/class');
+YCollection.subclass('YArray', function(YArray){
- yclass.chainDelegates(YArray, 'push', 'unshift', 'sort', 'splice', 'reverse');
- yclass.mixinNames(YArray, Array, ['reduce', 'map', 'forEach', 'filter', 'slice', 'some', 'every'], true, true);
- yclass.mixinNames(YArray, Array, ['indexOf', 'lastIndexOf', 'shift', 'pop', 'join'], true, false);
+ mixin(YArray, { donor:Array, chain:true,
+ names:'push unshift sort splice reverse'.split(' ') });
+ mixin(YArray, { donor:Array, wrap:YArray,
+ names:'map forEach filter slice'.split(' ') });
+ mixin(YArray, { donor:Array,
+ names:'reduce some every indexOf lastIndexOf shift pop join'.split(' ') });
-
-
- this.init = function(o){
- // YCollection.init.call(this, o || []);
+ this.init = function initYArray(o){
this._o = o || [];
};
this.merge =
this.concat =
function concat( donor ){
- var A = this._o;
- new Y(arguments).forEach(function( donor ){
- A = A.concat(donor instanceof YArray ? donor.end() : donor);
- });
- return Y(A);
+ return new YArray( slice.call(arguments).reduce(function(A, donor ){
+ return A.concat(donor instanceof YArray ? donor.end() : donor);
+ }, this._o) );
};
this.remove =
function remove(v){
if (arguments.length > 1)
- Y(arguments).forEach(this.remove, this);
+ slice.call(arguments).forEach(this.remove, this);
else {
var idx = this.indexOf(v);
if ( idx != -1 )
// });
};
+ // this.zip =
+ // function zip(){
+ // var sequences = new YArray(slice.call(arguments)).map( Y.limit(1) ).unshift(this);
+ // return this.map(function(_, k){
+ // return sequences.invoke('attr', k);
+ // }).invoke('end');
+ // };
+
// Like map, but produces a dict
// Y(["Foo?", "R&D"]).generate(encodeURIComponent)
// -> Y({"Foo?":"Foo%3F", "R&D":"R%26D"})
this.generate =
function generate(fn, acc){
- var args = Y(arguments),
+ var args = slice.call(arguments),
fn = args.shift(),
acc = args.shift();
return this.reduce(function(acc, v, i){
this.clone =
function clone(){
- return Y(this._o.slice(0));
+ return new YArray(this._o.slice(0));
};
this.size =
/** YCollection is the core of Y. */
-var Y = require('Y').Y
+var YBase = require('Y/class').YBase
, isFunction = require('Y/type').isFunction
-, extend = require('Y/core').extend
-, bool = require('Y/op').bool
+, core = require('Y/core')
+, op = require('Y/op')
+, slice = core.slice
+, extend = core.extend
+, attr = core.attr
+, bool = op.bool
;
function extendY(){
- extend.apply(this, [this._o].concat(Y(arguments)));
+ extend.apply(this, [this._o].concat(slice.call(arguments)));
return this;
}
exports['YCollection'] =
-Y.YBase.subclass('YCollection', {
+YBase.subclass('YCollection', {
'init' : function(o){
this._o = o || {};
},
'attr' : function attr(k, v, def){
- var r = Y.attr(this._o, k, v, def);
+ var r = attr(this._o, k, v, def);
if (r === this._o)
return this;
else
},
'clone' : function clone(){
- return Y({}).extend(this);
+ return new this.constructor().extend(this);
},
+ // 'remove' : function remove(v){
+ // var o = this._o
+ // , toRemove = new Y(arguments);
+ //
+ // for (var k in o) {
+ // var v = o[k];
+ // if ( toRemove.has(v) ) {
+ // delete o[k];
+ // toRemove.remove(v);
+ // }
+ // }
+ // return this;
+ // },
+
'remove' : function remove(v){
var o = this._o
- , toRemove = new Y(arguments);
+ , toRemove = slice.call(arguments);
for (var k in o) {
- var v = o[k];
- if ( toRemove.has(v) ) {
+ var v = o[k], idx = toRemove.indexOf(v);
+ if ( idx !== -1 ) {
delete o[k];
- toRemove.remove(v);
+ toRemove.splice(idx,1);
}
+ if (!toRemove.length)
+ break;
}
return this;
},
},
'zip' : function zip(){
- var sequences = new Y(arguments).map( Y.limit(1) ).unshift(this);
+ var sequences = slice.call(arguments);
+ sequences.unshift(this);
return this.map(function(_, k){
- return sequences.invoke('attr', k);
- }).invoke('end');
+ return sequences.map(op.curried.kget(k));
+ });
},
'pluck' : function pluck(key){
},
'invoke' : function invoke(name){
- var args = Y(arguments),
- name = args.shift();
- return this.map(function(o){
+ var args = slice.call(arguments,1);
+ return core.map(this, function(o){
return o && o[name].apply(o, args);
});
},
, WRAPS = "__wraps__"
, globals = (function(){ return this; })()
-, Y = require('Y').Y
-, core = require('Y/core')
-, type = require('Y/type')
+, core = require('Y/core')
+, type = require('Y/type')
-, isNumber = type.isNumber
, isFunction = type.isFunction
-, isArray = type.isArray
-, isPlainObject = type.isPlainObject
+, slice = core.slice
, _ = exports._ = YFunction._ = {}
, YFP = YFunction.prototype
function curry(fn){
if (fn.__curried__)
- return fn.apply(this, Y(arguments,1));
+ return fn.apply(this, slice.call(arguments,1));
fn = Function.toFunction(fn);
- var args = Y(arguments, 1)
+ var args = slice.call(arguments, 1)
, L = unwrap(fn).length;
if ( args.length >= L )
return fn.apply(this, args);
function curried(){
- var _args = args.concat( Y(arguments) );
+ var _args = args.concat( slice.call(arguments) );
if ( _args.length >= L )
return fn.apply(this, _args);
else
m = fn.__methodized__ =
function methodized(){
- return fn.apply(this, [this].concat( Y(arguments) ));
+ return fn.apply(this, [this].concat( slice.call(arguments) ));
};
m[WRAPS] = fn;
return m;
g = fn.__genericized__ =
function genericized(){
- var args = Y(arguments);
+ var args = slice.call(arguments);
return fn.apply(args.shift(), args);
};
g[WRAPS] = fn;
function _composer(x,fn){ return fn.call(this, x); }
function compose(f,g){
- var fns = Y(arguments).map(Function.toFunction);
+ var fns = slice.call(arguments).map(Function.toFunction);
return function(){
- return fns.reduce(_composer, Y(arguments), this);
+ return fns.reduce(_composer, slice.call(arguments), this);
};
}
function chain(f,g){
- var fns = Y(arguments).map(Function.toFunction);
+ var fns = slice.call(arguments).map(Function.toFunction);
if ( g.__sequence__ )
fns = g.__sequence__.concat( fns.slice(1) );
function chained(){
- var args = Y(arguments)
+ var args = slice.call(arguments)
, i = fns.length;
while (i-- > 0) args = fns[i].call(this, x);
return args;
// YFunction.prototype.lazy = methodize(lazy);
// function lazy(fn){
-// var args = Y(arguments, 1)
+// var args = slice.call(arguments, 1)
// , L = unwrap(fn).length
// , lazied = function(){
-// var _args = Y(arguments)
+// var _args = slice.call(arguments)
// , f = _args[0];
//
// if ( isFunction(f) ) {
var _bind = _Function.prototype.bind;
function bind(fn, context, args){
- var bound = _bind.apply(fn, Y(arguments,1));
+ var bound = _bind.apply(fn, slice.call(arguments,1));
bound[WRAPS] = fn;
return YFunction(bound);
}
// Remembers arguments but obeys current context
function partial(fn){
- var args = Y(arguments,1)
+ var args = slice.call(arguments,1)
, partially =
function partially(){
- return fn.apply( this, args.concat(Y(arguments)) );
+ return fn.apply( this, args.concat(slice.call(arguments)) );
};
partially[WRAPS] = fn;
return YFunction(partially);
fn.__memoized__ =
function memorizer(){
// toJSON would be a better alternative, but that won't work cross-browser
- var key = Y(arguments).join('\0\0\0')
+ var key = slice.call(arguments).join('\0\0\0')
, cache = arguments.callee.cache;
if ( !(key in cache) )
cache[key] = fn.apply(this, arguments);
_ofArityWrapper =
YFunction._ofArityWrapper =
memoize(function(n, limit){
+ var i = n, args = [];
+ while (i-- > 0) args.unshift('$'+i);
+ // range(n).map( op.add('$') ).join(',')
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')+
+ 'return function('+args.join(',')+'){ '+
+ 'return fn.apply(this,' + (limit ? 'slice.call(arguments, 0,'+n+')' : 'arguments')+
'); }; })');
});
return fn.className || fn.name || (fn+'').match( /function\s*([^\(]*)\(/ )[1] || '';
}
-function splat(fn, x){
- return fn[ isArray(x) ? "apply" : "call"](this, x);
-}
+// function splat(fn, x){
+// return fn[ isArray(x) ? "apply" : "call"](this, x);
+// }
exports['aritize'] = aritize;
exports['limit'] = limit;
exports['getName'] = getName;
-// exports['splat'] = splat;
// Methodize and then attach to YFunction's prototype
YFP.extend(core.map(exports, methodize));
-var Y = require('Y').Y
+var YCollection = require('Y/types/collection').YCollection
, op = require('Y/op')
;
exports['YNumber'] =
-Y.YCollection.subclass('YNumber', {
+YCollection.subclass('YNumber', {
init: function(o){
this._o = o || 0;
},
-var Y = require('Y').Y
-, isArray = Y.isArray
+var YCollection = require('Y/types/collection').YCollection
+, type = require('Y/type')
+, isArray = type.isArray
;
exports['YObject'] =
-Y.YCollection.subclass('YObject', {
+YCollection.subclass('YObject', {
'init': function initYObject(o){
this._o = o || {};
-var Y = require('Y').Y
-, mixinNames = require('Y/class').mixinNames
-, op = require('Y/op')
+var YCollection = require('Y/types/collection').YCollection
+, mixin = require('Y/utils').mixin
+, op = require('Y/op')
+, core = require('Y/core')
+, slice = core.slice
;
exports['YString'] =
-Y.YCollection.subclass('YString', function(YString){
+YCollection.subclass('YString', function(YString){
- mixinNames(YString, String, [
- 'slice', 'split',
- 'substr', 'substring',
- 'concat', 'replace',
- 'toLowerCase', 'toUpperCase'
- ], true, true);
- mixinNames(YString, String, [ 'indexOf', 'lastIndexOf', 'charAt', 'charCodeAt' ], true, false);
+ mixin(YString, { donor:String, wrap:YString,
+ names:'slice split substr substring concat replace toLowerCase toUpperCase'.split(' ') });
+ mixin(YString, { donor:String,
+ names:'indexOf lastIndexOf charAt charCodeAt'.split(' ') });
function trim(val){
var s = this._o+'';
howMany = Number(howMany > 0 ? howMany : 0);
var prefix = s.slice(0, idx)
- , insert = Y(arguments, 2).join('')
+ , insert = slice.call(arguments, 2).join('')
, suffix = s.slice(idx+howMany)
;
this._o = prefix + insert + suffix;
* Negative values for start and/or end are allowed.
*/
mutate : function mutate(start, end){
- return this.splice.apply(this, [start, end-start].concat(Y(arguments, 2)) );
- // var s = this._o, len = s.length ;
- //
- // if (start < 0) start += len;
- // if (end < 0) end += len;
- //
- // var prefix = s.slice(0, start)
- // , insert = Y(arguments, 2).join('')
- // , suffix = s.slice(end)
- // ;
- // this._o = prefix + insert + suffix;
- // return this;
+ // var args = slice.call(arguments);
+ arguments[1] = end-start;
+ return this.splice.apply(this, arguments);
},
strip: function strip(){
this.set = function set(key, value, def){
var s = this._o, _val = (value !== undefined ? value : def);
- if ( Y.isNumber(key) )
+ if ( isNumber(key) )
return this.splice(key, 1, _val);
- if ( Y.isArray(key) )
+ if ( isArray(key) )
return this.splice.apply(this, key.slice(0,2).concat([_val]) );
// TODO: Should cache the new properties and re-applied them whenever we mutate _o,
var s = this._o;
// set
if ( value !== undefined || def !== undefined )
- return Y.attr(this, key, value, def);
+ return core.dattr(this, key, value, def);
// get
else {
- if ( Y.isNumber(key) )
+ if ( isNumber(key) )
return s.charAt(key);
- if ( Y.isArray(key) )
+ if ( isArray(key) )
return s.slice.apply(s, key);
return s[key];
}
};
- this.attr.__wraps__ = Y.attr;
+ this.attr.__wraps__ = core.dattr;
this.reduce = function reduce(fn, acc){
fn = Function.toFunction(fn);
--- /dev/null
+var YFunction = require('Y/types/function').YFunction
+, isFunction = require('Y/type').isFunction
+, core = require('Y/core')
+, op = require('Y/op')
+;
+
+
+function bindName(k){
+ var v = this[k];
+ if ( isFunction(v) )
+ this[k] = YFunction(v).bind(this);
+}
+
+function bindAll(o, names){
+ if (!o)
+ return o;
+ if (arguments.length === 1)
+ names = core.map(o, op.nth(1));
+ else
+ names = slice.call(arguments, 1);
+ names.forEach(bindName, o);
+ return o;
+}
+
+
+var defaults = {
+ 'donor' : null,
+ 'names' : null,
+ 'override' : true,
+ 'wrap' : false,
+ 'chain' : false
+};
+function mixin(target, options){
+ var opt = op.extend({}, defaults, options), Donor = opt.donor
+ , target = ( isFunction(target) ? target.prototype : target )
+ , proto = ( isFunction(Donor) ? Donor.prototype : Donor )
+ , names = opt.names
+ ;
+
+ // Need a closure to capture the name
+ names.forEach(function(name){
+ var fn = proto[name];
+ if ( isFunction(fn) && (opt.override || !(name in target)) )
+ target[name] = function(){
+ var r = fn.apply(this._o || target, arguments);
+ return (opt.chain ? this : (opt.wrap ? opt.wrap(r) : r));
+ };
+ });
+
+ return o;
+}
+
+
+// function chainDelegates(type, names){
+// var proto = type.prototype;
+// names.forEach(function(name){
+// proto[name] = function(){
+// var o = this._o || this;
+// o[name].apply(o, arguments);
+// return this;
+// };
+// });
+// return type;
+// }
+// exports['chainDelegates'] = chainDelegates;
+
+exports['bindAll'] = bindAll;
+exports['mixin'] = mixin;
+// -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
var undefined
, globals = (function(){ return this; })()
, _Object = globals.Object
-(function(undefined){
// Inspired by John Resig's "Simple Class Inheritence" -- http://ejohn.org/blog/simple-javascript-inheritance/
/*
Metaprogramming API
Note: Metaprogramming events cannot depend on Class.
*/
+var Y = require('Y').Y
+, Emitter = require('Y/modules/y.event').Emitter
-
-var Evt = this.Evt = (this.Evt || {})
-, KNOWN_CLASSES = Class.KNOWN_CLASSES = {}
, isFunction = Y.isFunction
+, KNOWN_CLASSES = Class.KNOWN_CLASSES = exports['KNOWN_CLASSES'] = {}
, getProto = Object.getPrototypeOf
, hasOwn = Object.prototype.hasOwnProperty
, objToString = Object.prototype.toString
// Private delegating constructor -- must be defined for every
// new class to prevent shared state. All construction is
// actually done in the init method.
-Evt.ConstructorTemplate = ConstructorTemplate;
+exports['ConstructorTemplate'] = ConstructorTemplate;
function ConstructorTemplate() {
var cls = arguments.callee
, instance = this;
// Not subclassing
- if ( cls.caller !== Evt.Class.fabricate ) {
+ if ( cls.caller !== Class.fabricate ) {
cls.fire('create', instance, {
'instance' : instance,
, init = NewClass.prototype.init
;
- instance.__emitter__ = new Y.event.Emitter(instance, NewClass);
+ instance.__emitter__ = new Emitter(instance, NewClass);
if (init) {
var result = init.apply(instance, arguments);
// Add class emitter
var ParentEmitter = (Parent.__emitter__ ? Parent : ClassFactory)
- , ClassEmitter = NewClass.__emitter__ = new Y.event.Emitter(NewClass, ParentEmitter)
+ , ClassEmitter = NewClass.__emitter__ = new Emitter(NewClass, ParentEmitter)
;
// Either invoke body constructor...
// Decorate with emitter methods and
// add metaprogramming data to Class object
Class.__super__ = Object;
-Class.__emitter__ = new Y.event.Emitter(Class);
+Class.__emitter__ = new Emitter(Class);
Class.fn = Class.prototype;
Class.fn.__class__ = Class;
Class.className = Class.fn.className = "Class";
// Expose
-Evt.Class =
-Evt.subclass = Class;
-
-
+exports['Class'] =
+exports['subclass'] = Class;
-})();
\ No newline at end of file
--- /dev/null
+// -*- mode: JavaScript; tab-width: 4; indent-tabs-mode: nil; -*-
+//@require('jquery')
+//@require('lessly/future')
+//@require('Y')
+
-(function($, undefined){
+//@require('jquery')
-var CONTEXT_ATTRS = Y([
+var undefined
+, Y = require('Y').Y
+, Vec = require('ezl/math/vec').Vec
+, loc = require('ezl/loc')
+, Loc = loc.Loc
+, BoundingBox = loc.BoundingBox
+,
+CONTEXT_ATTRS = Y([
'globalAlpha', 'globalCompositeOperation',
'strokeStyle', 'fillStyle',
'lineWidth', 'lineCap', 'lineJoin', 'miterLimit',
'shadowOffsetX', 'shadowOffsetY', 'shadowBlur', 'shadowColor'
-]);
+])
+,
-
-
-Layer = Y.subclass('Layer', {
- _cssClasses : 'portal layer',
+Layer =
+exports['Layer'] =
+Y.subclass('Layer', {
+ _cssClasses : 'ezl layer',
canvas : null,
$(function(){
$('<style />')
.text([
- '.portal.layer { position:absolute; z-index:1; top:0; left:0; line-height:0; }',
- // '.portal.layer { outline:1px solid #000000; }',
- '.portal.layer canvas { z-index:0; }'
+ '.ezl.layer { position:absolute; z-index:1; top:0; left:0; line-height:0; }',
+ // '.ezl.layer { outline:1px solid #000000; }',
+ '.ezl.layer canvas { z-index:0; }'
].join('\n'))
.appendTo('head');
});
-
-})(jQuery);
--- /dev/null
+var Y = require('Y').Y
+, math = require('ezl/math')
+, Vec = math.Vec
+, Line = math.Line
+, Rect = math.Rect
+,
+
+BoundingBox =
+exports['BoundingBox'] =
+Rect.subclass('BoundingBox', {
+ init : function initBoundingBox(x1,y1, x2,y2){
+ Rect.init.call(this, x1,y1, x2,y2);
+
+ this.sides = {
+ top : new Line(x1,y1, x2,y1),
+ bottom : new Line(x1,y2, x2,y2),
+ left : new Line(x1,y1, x1,y2),
+ right : new Line(x2,y1, x2,y2)
+ };
+ },
+
+ set : function set(k, v, def){
+ v = (v !== undefined ? v : def);
+
+ switch (k) {
+ case 'x1': case 0: case 'x': this.x1 = this[0] = this.x = v; break;
+ case 'y1': case 1: case 'y': this.y1 = this[1] = this.y = v; break;
+ case 'x2': case 2: this.x2 = this[2] = v; break;
+ case 'y1': case 3: this.y2 = this[3] = v; break;
+
+ default: this[k] = v;
+ }
+
+ this.width = this.x2 - this.x1;
+ this.height = this.y2 - this.y1;
+
+ return this._updateSides();
+ },
+
+ _updateSides : function _updateSides(){
+ var s = this.sides
+ , x1 = this.x1, y1 = this.y1
+ , x2 = this.x2, y2 = this.y2
+ , dx1 = x1 !== s.top.x1, dy1 = y1 !== s.top.y1
+ , dx2 = x2 !== s.top.x2, dy2 = y2 !== s.left.y2
+ ;
+
+ if ( dx1 || dy1 ) this.p1 = new Vec(x1,y1);
+ if ( dx2 || dy2 ) this.p2 = new Vec(x2,y2);
+
+ if ( dx1 || dy1 || dx2 ) s.top = new Line(x1,y1, x2,y1);
+ if ( dx1 || dx2 || dy2 ) s.bottom = new Line(x1,y2, x2,y2);
+ if ( dx1 || dy1 || dy2 ) s.left = new Line(x1,y1, x1,y2);
+ if ( dy1 || dy2 || dx2 ) s.right = new Line(x2,y1, x2,y2);
+
+ return this;
+ },
+
+ attr : Y.attr.methodize(),
+
+ add : function add(x,y){
+ return new BoundingBox(x,y, x+this.width,y+this.height);
+ },
+
+ resize : function resize(w,h){
+ var x = this.x, y = this.y;
+ return new BoundingBox(x,y, x+w,y+h);
+ },
+
+ clone : function clone(){
+ return new BoundingBox( this.p1.clone(), this.p2.clone() );
+ }
+
+});
--- /dev/null
+var Y = require('Y').Y;
+
+Y.extend(exports, {
+ 'Loc' : require('ezl/loc/loc').Loc,
+ 'BoundingBox' : require('ezl/loc/boundingbox').BoundingBox,
+ 'Square' : require('ezl/loc/square').Square
+});
--- /dev/null
+var Y = require('Y').Y
+, Vec = require('ezl/math/vec').Vec
+
+, PI = Math.PI
+, QUARTER_PI = PI/4
+, HALF_PI = PI/2
+, PI_AND_HALF = PI + HALF_PI
+, TWO_PI = PI*2
+,
+
+
+Loc =
+exports['Loc'] =
+Y.subclass('Loc', new Vec(0,0), {
+
+ // init : function init(x,y){
+ // Vec.init.call(this, x,y);
+ // },
+
+ set : function set(k, v, def){
+ v = (v !== undefined ? v : def);
+ switch (k) {
+ case 'x': case 0:
+ this.x = this[0] = v; break;
+ case 'y': case 1:
+ this.y = this[1] = v; break;
+ default:
+ this[k] = v;
+ }
+ return this;
+ },
+ attr : Y.attr.methodize(),
+
+ clone : function clone(){
+ return new Loc(this.x, this.y);
+ },
+
+ moveBy : function moveBy(x,y){
+ return new Loc(this.x+x, this.y+y);
+ },
+
+ moveByAngle : function moveByAngle(theta, v){
+ var x = this.x + v*Math.cos(theta)
+ , y = this.y + v*Math.sin(theta);
+ return new Loc(x,y);
+ },
+
+ moveByDir : function moveByDir(dir, v){
+ return this.moveByAngle( Loc.dirToAngle(dir), v );
+ },
+
+ toSquare : function toSquare(){
+ return Loc.Square.fromLoc(this.x, this.y);
+ },
+
+ /**
+ * Converts relative locations like ('50%','50%') to a numeric location.
+ */
+ absolute : function absolute(w,h){
+ var x = this.x, y = this.y
+ return new Loc( Y.isString(x) ? parseFloat(x.slice(0,-1))/100 * w : x
+ , Y.isString(y) ? parseFloat(y.slice(0,-1))/100 * h : y );
+ },
+
+ toUnits : function toUnits(units){
+ units = units || 'px';
+ var x = this.x, y = this.y;
+ return { 'x' : Y.isNumber(x) ? x+units : x
+ , 'y' : Y.isNumber(y) ? y+units : y };
+ },
+
+ toString : function toString(){
+ var x = this.x, y = this.y;
+ x = Y.isNumber(x) ? x.toFixed(2) : x;
+ y = Y.isNumber(y) ? y.toFixed(2) : y;
+ return '('+x+','+y+')';
+ }
+
+});
+Y(Loc).extend({
+ UP : 'up', DOWN : 'down',
+ RIGHT : 'right', LEFT : 'left',
+
+ UP_RIGHT : 'right up', UP_LEFT : 'left up',
+ DOWN_RIGHT : 'down right', DOWN_LEFT : 'down left',
+
+ dirToAngle : function dirToAngle(dir){
+ switch (dir) {
+ case Loc.RIGHT: return 0;
+ case Loc.DOWN_RIGHT: return QUARTER_PI;
+ case Loc.DOWN: return HALF_PI;
+ case Loc.DOWN_LEFT: return HALF_PI+QUARTER_PI;
+ case Loc.LEFT: return PI;
+ case Loc.UP_LEFT: return PI+QUARTER_PI;
+ case Loc.UP: return PI_AND_HALF;
+ case Loc.UP_RIGHT: return PI_AND_HALF+QUARTER_PI;
+
+ default: throw new Error("wtf direction is "+dir+"??");
+ }
+ },
+
+ fromSquare : function fromSquare(col, row){
+ return new Loc(
+ col * REF_SIZE,
+ row * REF_SIZE );
+ },
+
+ // XXX: Probably wrong for negative locations
+ centerInSquare : function centerInSquare(v){
+ return Math.floor(v/REF_SIZE)*REF_SIZE + REF_SIZE/2;
+ }
+
+});
+
--- /dev/null
+var Loc = require('ezl/loc/loc').Loc
+, BoundingBox = require('ezl/loc/boundingbox').BoundingBox
+,
+
+
+Square =
+exports['Square'] =
+BoundingBox.subclass('Square', {
+ init : function init(col, row){
+ this.col = col;
+ this.row = row;
+
+ var x1 = col * REF_SIZE, y1 = row * REF_SIZE
+ , x2 = x1 + REF_SIZE, y2 = y1 + REF_SIZE
+ ;
+
+ BoundingBox.init.call(this, x1,y1, x2,y2);
+ },
+
+ clone : function clone(){
+ return new Square(this.col, this.row);
+ },
+
+ toLoc : function toLoc(){
+ return Loc.fromSquare(this.col, this.row);
+ },
+
+ toString : function toString(){
+ return this.col+'_'+this.row;
+ }
+
+});
+
+// XXX: Negative grid positions don't round correctly
+Square.fromLoc = function(x, y){
+ return new Square(
+ Math.floor(x / REF_SIZE),
+ Math.floor(y / REF_SIZE) );
+};
+
-Cooldown = Y.subclass('Cooldown', {
+var Y = require('Y').Y
+,
+
+Cooldown =
+exports['Cooldown'] =
+Y.subclass('Cooldown', {
'init' : function(cooldown, isReady){
this.cooldown = cooldown; // ms
this.ready = isReady || true;
-(function(){
+var Y = require('Y').Y
+, Emitter = require('Y/modules/y.event').Emitter
-function add(a,b){ return a+b; }
-
-function decorate(delegate){
- if (!delegate) return;
- Y.event.Emitter.prototype.decorate.call(this, delegate);
- 'start stop reset'.split(' ').forEach(function(k){
- delegate[k] = methods[k].bind(this);
- }, this);
- return delegate;
-}
-
-var
-MIN_TICK_INTERVAL = 0, // ms
-NUM_SAMPLES = 33,
+, MIN_TICK_INTERVAL = 0 // ms
+, NUM_SAMPLES = 33
+,
methods = {
// framerate : 0, // Target framerate
init : function init(target, framerate, samples){
- Y.event.Emitter.init.call(this, target);
+ Emitter.init.call(this, target);
decorate.call(this, target);
this.tick = this.tick.bind(this);
this.decorate = decorate.bind(this);
return (this.realtimes.reduce(Y.op.add,0) / this.realtimes.length);
}
-};
-this.EventLoop = new Y.Class('EventLoop', Y.event.Emitter, methods);
+},
+
+EventLoop =
+exports['EventLoop'] =
+Emitter.subclass('EventLoop', methods)
+;
+
+function decorate(delegate){
+ if (!delegate) return;
+ Emitter.prototype.decorate.call(this, delegate);
+ ['start', 'stop', 'reset']
+ .forEach(function(k){
+ delegate[k] = methods[k].bind(this);
+ }, this);
+ return delegate;
+}
+
})();
-FpsSparkline = Y.subclass('FpsSparkline', {
+//@require('jquery')
+//@require('jquery.sparkline.min')
+var Y = require('Y').Y
+,
+
+FpsSparkline =
+exports['FpsSparkline'] =
+Y.subclass('FpsSparkline', {
- init : function init(loop, el, w,h, maxBuffer, interval){
+ init : function initFpsSparkline(loop, el, w,h, maxBuffer, interval){
this.buffer = [];
this.el = el;
--- /dev/null
+var Y = require('Y').Y;
+
+Y.extend(exports, {
+ 'EventLoop' : require('ezl/loop/eventloop').EventLoop,
+ 'Cooldown' : require('ezl/loop/cooldown').Cooldown,
+ 'FpsSparkline' : require('ezl/loop/fps').FpsSparkline
+});
--- /dev/null
+var Y = require('Y').Y
+, Vec = require('ezl/math/vec').Vec
+;
+
+Y(exports, {
+ 'Vec' : Vec,
+ 'Line' : require('ezl/math/line').Line,
+ 'Rect' : require('ezl/math/rect').Rect,
+
+ 'clamp' : function clamp(value, min, max) {
+ return Math.min(Math.max(value, min), max);
+ },
+
+ 'lerp' : function lerp(x, a, b) {
+ return a + x*(b - a);
+ },
+
+ 'reflect' : function reflect(v, line){
+ var dot = Vec.dot
+ , basev = Vec.difference(v, line.p1);
+ return line.vec()
+ .scale(2 * dot(basev,line) / dot(line,line))
+ .subtract(basev)
+ .add(line.p1);
+ }
+
+});
-(function(){
-
-var
-Vec = math.Vec,
-HALF_PI = Math.PI/2,
-SIN_HALF_PI = Math.sin(HALF_PI),
-COS_HALF_PI = Math.cos(HALF_PI);
-
-
/**
* A line in the cartesian plane.
*/
-math.Line = math.Vec.subclass('Line', {
+
+var Vec = require('ezl/math/vec').Vec
+, HALF_PI = Math.PI/2
+, SIN_HALF_PI = Math.sin(HALF_PI)
+, COS_HALF_PI = Math.cos(HALF_PI)
+,
+
+Line =
+exports['Line'] =
+Vec.subclass('Line', {
init : function initLine(x1,y1, x2,y2, tdist){
this.x1 = x1; this.y1 = y1;
, yi = this.yint = -x1*m + y1
, xi = this.xint = -y1/m + x1
;
- math.Vec.init.call(this, x0,y0);
+ Vec.init.call(this, x0,y0);
- this.p1 = new math.Vec(x1,y1);
- this.p2 = new math.Vec(x2,y2);
+ this.p1 = new Vec(x1,y1);
+ this.p2 = new Vec(x2,y2);
this.theta = Math.atan2(y0, x0);
this._cos = Math.cos(this.theta);
},
clone : function clone(){
- return new math.Line(this.x1,this.y1, this.x2,this.y2, this.tdist);
+ return new Line(this.x1,this.y1, this.x2,this.y2, this.tdist);
},
},
parametric : function parametric(t){
- return new math.Vec( this.x1 + t*this.pa ,
- this.y1 + t*this.pb );
+ return new Vec( this.x1 + t*this.pa ,
+ this.y1 + t*this.pb );
},
iparametric : function iparametric(x,y){
- return new math.Vec( (x-this.x1)/this.pa ,
- (y-this.y1)/this.pa );
+ return new Vec( (x-this.x1)/this.pa ,
+ (y-this.y1)/this.pa );
},
- pointAtX : function pointAtX(x){ return new math.Vec(x, this.calcY(x)); },
- pointAtY : function pointAtY(y){ return new math.Vec(this.calcX(y), y); },
+ pointAtX : function pointAtX(x){ return new Vec(x, this.calcY(x)); },
+ pointAtY : function pointAtY(y){ return new Vec(this.calcX(y), y); },
calcY : function calcY(x){ return (x !== this.xint ? x*this.slope + this.yint : 0); },
calcX : function calcX(y){ return (y !== this.yint ? y/this.slope + this.xint : 0); },
intersects : function intersects(x,y){
var o = x;
- if (o instanceof math.Line)
+ if (o instanceof Line)
return this.slope !== o.slope || this.equals(o);
- if (o instanceof math.Vec) {
+ if (o instanceof Vec) {
x = o.x;
y = o.y;
}
vec : function vec(){
- return new math.Vec(this.x, this.y); // reset to vector from origin
+ return new Vec(this.x, this.y); // reset to vector from origin
},
base : function base(){
if (!this._base)
- this._base = new math.Line(0,0, this.x,this.y);
+ this._base = new Line(0,0, this.x,this.y);
return this._base;
},
var slope = this.slope;
if ( slope === 0 )
- return new math.Line(at.x,at.y, at.x,at.y+1, this.tdist);
+ return new Line(at.x,at.y, at.x,at.y+1, this.tdist);
if ( !isFinite(slope) )
- return new math.Line(at.x,at.y, at.x+1,at.y, this.tdist);
+ return new Line(at.x,at.y, at.x+1,at.y, this.tdist);
var x1 = at.x, y1 = at.y
, x2 = at.x - at.y + (at.y !== this.y1 ? this.y1 : this.y2)
, y2 = at.y + at.x - (at.x !== this.x1 ? this.x1 : this.x2) ;
- return new math.Line(x1,y1, x2,y2, this.tdist);
+ return new Line(x1,y1, x2,y2, this.tdist);
},
toString : function toString(){
}
});
-
-})();
\ No newline at end of file
+++ /dev/null
-math = {
- clamp : function clamp(value, min, max) {
- return Math.min(Math.max(value, min), max);
- },
-
- lerp : function lerp(x, a, b) {
- return a + x*(b - a);
- },
-
- reflect : function reflect(v, line){
- var dot = math.Vec.dot
- , basev = math.Vec.difference(v, line.p1);
- return line.vec()
- .scale(2 * dot(basev,line) / dot(line,line))
- .subtract(basev)
- .add(line.p1);
- }
-
-};
\ No newline at end of file
+var Vec = require('ezl/math/vec').Vec
+,
+
+Rect =
+exports['Rect'] =
+Y.subclass('Rect', [], {
+
+ init : function initRect(x1,y1, x2,y2){
+ if (x1 instanceof Array && y1 instanceof Array) {
+ y2 = y1[1]; x2 = y1[0];
+ y1 = x1[1]; x1 = x1[0];
+ }
+ // init : function initRect(_x1,_y1, _x2,_y2){
+ // if (_x1 instanceof Array && _y1 instanceof Array) {
+ // _y2 = _y1[1]; _x2 = _y1[0];
+ // _y1 = _x1[1]; _x1 = _x1[0];
+ // }
+ // var x1 = Math.min(_x1,_x2), x2 = Math.max(_x1,_x2)
+ // , y1 = Math.min(_y1,_y2), y2 = Math.max(_y1,_y2);
+
+ this.length = 4;
+ 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.p1 = new Vec(x1,y1);
+ this.p2 = new Vec(x2,y2);
+ },
+
+ contains : function contains(x,y){
+ return ( x >= this.x1 && x <= this.x2 &&
+ y >= this.y1 && y <= this.y2 );
+ },
+
+ intersects : function intersects(line){
+ var x1 = Math.min(this.x1,this.x2), x2 = Math.max(this.x1,this.x2)
+ , y1 = Math.min(this.y1,this.y2), y2 = Math.max(this.y1,this.y2)
+ , cx1,cy1, cx2,cy2 ;
+ return ( ( (cx1 = line.calcX(y1)) >= x1 && cx1 <= x2 )
+ || ( (cy1 = line.calcY(x1)) >= y1 && cy1 <= y2 )
+ || ( (cx2 = line.calcX(y2)) >= x1 && cx2 <= x2 )
+ || ( (cy2 = line.calcY(x2)) >= y1 && cy2 <= y2 ) );
+ },
+
+ midpoint : function midpoint(){
+ return new Vec( this.x1 + this.width /2
+ , this.y1 + this.height/2 );
+ },
+
+ clone : function clone(){
+ return new Rect( this.p1.clone()
+ , this.p2.clone() );
+ },
+
+ toString : function toString(){
+ return '['+this.p1+' '+this.p2+']';
+ }
+});
/**
* A 2-dimensional vector.
*/
-math.Vec = new Y.Class('Vec', [], {
+var Vec =
+exports['Vec'] =
+new Y.Class('Vec', [], {
init : function init(x, y){
this.length = 2;
},
clone : function clone(){
- return new math.Vec(this.x, this.y);
+ return new Vec(this.x, this.y);
},
setXY : function setXY(x,y){
},
manhattan: function manhattan(x2,y2) {
- if (x2 instanceof math.Vec) {
+ if (x2 instanceof Vec) {
y2 = x2.y; x2 = x2.x;
}
var d1 = Math.abs(x2 - this.x)
});
-Y.extend(math.Vec, {
+Y.extend(Vec, {
sum : function sum(a, b) {
- return new math.Vec(a.x+b.x, a.y+b.y);
+ return new Vec(a.x+b.x, a.y+b.y);
},
difference : function difference(a, b) {
- return new math.Vec(a.x-b.x, a.y-b.y);
+ return new Vec(a.x-b.x, a.y-b.y);
},
dot : function dot(a, b) {
},
lerp : function lerp(x, a, b) {
- return new math.Vec( math.lerp(a.x, b.x, x),
- math.lerp(a.y, b.y, x) );
+ return new Vec( math.lerp(a.x, b.x, x),
+ math.lerp(a.y, b.y, x) );
},
- // manhattan: function manhattan(p1, p2) {
- // var d1 = Math.abs(p2.x - p1.x)
- // , d2 = Math.abs(p2.y - p1.y) ;
- // return d1 + d2;
- // },
-
- // manhattan4: function manhattan4(x1,y1, x2,y2) {
- // var d1 = Math.abs(x2 - x1)
- // , d2 = Math.abs(y2 - y1) ;
- // return d1 + d2;
- // },
-
manhattan: function manhattan(x1,y1, x2,y2) {
if (x1 instanceof Array && y1 instanceof Array) {
y2 = y1[1]; x2 = y1[0];
var d1 = Math.abs(x2 - x1)
, d2 = Math.abs(y2 - y1) ;
return d1 + d2;
- },
-
+ }
});
Circle = new Y.Class('Circle', Shape, {
- _cssClasses : 'portal layer shape circle',
+ _cssClasses : 'ezl layer shape circle',
init : function initCircle(radius, centerTL){
Layer.init.call(this);
--- /dev/null
+exports['Shape'] = require('ezl/shape/shape').Shape;
+exports['Rect'] = require('ezl/shape/rect').Rect;
+exports['Circle'] = require('ezl/shape/circle').Circle;
+exports['Line'] = require('ezl/shape/line').Line;
+
+var polygon = require('ezl/shape/polygon');
+exports['Polygon'] = polygon.Polygon;
+exports['Triangle'] = polygon.Triangle;
+exports['Quad'] = polygon.Quad;
+
+
Line = new Y.Class('Line', Shape, {
- _cssClasses : 'portal layer shape line',
+ _cssClasses : 'ezl layer shape line',
useCanvasScaling : true,
fillStyle : 'transparent',
+var Y = require('Y').Y
+, Shape = require('ezl/shape/shape').Shape
+, Loc = require('ezl/loc').Loc
+,
-Polygon = new Y.Class('Polygon', Shape, {
- _cssClasses : 'portal layer shape polygon',
+Polygon =
+exports['Polygon'] =
+Shape.subclass('Polygon', {
+ _cssClasses : 'ezl layer shape polygon',
/**
* Expects two arrays of coordinate-halfs, which could be zipped
* x0 and y0 will always be 0.
*/
init : function initPolygon(xs, ys){
- Layer.init.call(this);
+ Shape.init.call(this);
var xs = this._calcDimension('x', xs)
, ys = this._calcDimension('y', ys)
;
this.points = Y(xs).zip(ys).map(Loc.instantiate, Loc);
- this.width(w)
- .height(h);
+ this.width(w).height(h);
// .origin(w/2, h/2);
},
});
ctx.fill();
}
-});
+})
+,
-Triangle = new Y.Class('Triangle', Polygon, {
- _cssClasses : 'portal layer shape polygon triangle',
+Triangle =
+exports['Triangle'] =
+Polygon.subclass('Triangle', {
+ _cssClasses : 'ezl layer shape polygon triangle',
init : function initTriangle(x1,y1, x2,y2){
Polygon.init.call(this, [x1,x2], [y1,y2]);
, 'y' : offY + (x1*C - x2*B)/D * -1 // fix inverted Y-axis
};
},
-});
+})
+,
-Quad = new Y.Class('Quad', Polygon, {
- _cssClasses : 'portal layer shape polygon quad',
+Quad =
+exports['Quad'] =
+Polygon.subclass('Quad', {
+ _cssClasses : 'ezl layer shape polygon quad',
init : function initQuad(x1,y1, x2,y2, x3,y3){
Polygon.init.call(this, [x1,x2,x3], [y1,y2,y3]);
}
-});
+})
+;
+var Shape = require('ezl/shape').Shape
+,
-Rect = Shape.subclass('Rect', {
- _cssClasses : 'portal layer shape rect',
+Rect =
+exports['Rect'] =
+Shape.subclass('Rect', {
+ _cssClasses : 'ezl layer shape rect',
init : function initRect(w,h){
- Layer.init.call(this);
-
- this.width(w)
- .height(h);
+ Shape.init.call(this);
+ this.width(w).height(h);
// .origin(w/2, h/2);
},
});
Rect.fromPoints = function(x1,y1, x2,y2){
return new Rect(x2-x1, y2-y1).position(x1,y1);
-};
\ No newline at end of file
+};
Shape = new Y.Class('Shape', Layer, {
- _cssClasses : 'portal layer shape',
+ _cssClasses : 'ezl layer shape',
fillStyle : 'rgba(231,48,117, 1)',
strokeStyle : 'transparent',
lineWidth : 0,
--- /dev/null
+/* astar.js http://github.com/bgrins/javascript-astar
+ MIT License
+
+ Modified by David Schoonover -- dsc@less.ly
+
+ Implements the astar search algorithm in javascript using a binary heap
+ **Requires graph.js**
+
+ Example Usage:
+ var graph = new Graph([
+ [0,0,0,0],
+ [1,0,0,1],
+ [1,1,0,0]
+ ]);
+ var start = graph.nodes[0][0];
+ var end = graph.nodes[1][2];
+ astar.search(graph.nodes, start, end);
+*/
+var BinaryHeap = require('ezl/util/binaryheap').BinaryHeap;
+
+exports['init'] = init;
+function init(grid) {
+ // var copy = [];
+ for(var x = 0, xl = grid.length; x < xl; x++) {
+ var yl = grid[x].length;
+ // copy[x] = new Array(yl);
+ for(var y = 0; y < yl; y++) {
+ // var node = grid[x][y].clone();
+ var node = grid[x][y];
+ node.f = 0;
+ node.g = 0;
+ node.h = 0;
+ node.visited = false;
+ node.closed = false;
+ node.parent = null;
+ // copy[x][y] = node;
+ }
+ }
+ // return copy;
+}
+
+exports['search'] = search;
+function search(grid, start, end, heuristic, ignore) {
+ init(grid);
+ heuristic = heuristic || manhattan;
+
+ ignore = ignore || [];
+ ignore.push(start.value);
+ ignore.push(end.value);
+
+ var open = new BinaryHeap('f');
+ open.push(start);
+
+ while( open.length > 0 ) {
+
+ // Grab the lowest f(x) to process next. Heap keeps this sorted for us.
+ var current = open.pop();
+
+ // End case -- result has been found, return the traced path
+ if(current === end) {
+ var path = []
+ , node = current;
+ while( node.parent ) {
+ path.push( node.clone() );
+ node = node.parent;
+ }
+ return path.reverse();
+ }
+
+ // Normal case -- move current from open to closed, process each of its neighbors
+ current.closed = true;
+
+ var neighbors = getNeighbors(grid, current);
+ for(var i=0, il = neighbors.length; i < il; i++) {
+ var neighbor = neighbors[i];
+
+ // blocker
+ if( neighbor.closed || (neighbor.blocked && ignore.indexOf(neighbor.value) === -1) )
+ continue;
+
+ // g score is the shortest distance from start to current node, we need to check if
+ // the path we have arrived at this neighbor is the shortest one we have seen yet.
+ // We define the distance from a node to it's neighbor as 1, but this could be variable for weighted paths.
+ var g = current.g + 1;
+
+ if( !neighbor.visited || g < neighbor.g ) {
+
+ // Found an optimal (so far) path to this node. Take score for node to see how good it is.
+ neighbor.parent = current;
+ neighbor.h = neighbor.h || heuristic(neighbor, end);
+ neighbor.g = g;
+ neighbor.f = g + neighbor.h;
+
+ // New? Add to the set of nodes to process
+ if ( !neighbor.visited ) {
+ neighbor.visited = true;
+ open.push(neighbor);
+
+ // Seen, but since it has been rescored we need to reorder it in the heap
+ } else
+ open.rescore(neighbor);
+ }
+ }
+ }
+
+ // No result was found -- empty array signifies failure to find path
+ return [];
+}
+
+exports['manhattan'] = manhattan;
+function manhattan(p1, p2) {
+ // See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
+ var d1 = Math.abs(p2.x - p1.x)
+ , d2 = Math.abs(p2.y - p1.y) ;
+ return d1 + d2;
+}
+
+exports['getNeighbors'] = getNeighbors;
+function getNeighbors(grid, node) {
+ var ret = [];
+ var x = node.x;
+ var y = node.y;
+
+ if(grid[x-1] && grid[x-1][y]) {
+ ret.push(grid[x-1][y]);
+ }
+ if(grid[x+1] && grid[x+1][y]) {
+ ret.push(grid[x+1][y]);
+ }
+ if(grid[x] && grid[x][y-1]) {
+ ret.push(grid[x][y-1]);
+ }
+ if(grid[x] && grid[x][y+1]) {
+ ret.push(grid[x][y+1]);
+ }
+ return ret;
+}
+++ /dev/null
-/* astar.js http://github.com/bgrins/javascript-astar
- MIT License
-
- Implements the astar search algorithm in javascript using a binary heap
- **Requires graph.js**
-
- Example Usage:
- var graph = new Graph([
- [0,0,0,0],
- [1,0,0,1],
- [1,1,0,0]
- ]);
- var start = graph.nodes[0][0];
- var end = graph.nodes[1][2];
- astar.search(graph.nodes, start, end);
-*/
-
-var astar = {
-
- init: function initAStar(grid) {
- // var copy = [];
- for(var x = 0, xl = grid.length; x < xl; x++) {
- var yl = grid[x].length;
- // copy[x] = new Array(yl);
- for(var y = 0; y < yl; y++) {
- // var node = grid[x][y].clone();
- var node = grid[x][y];
- node.f = 0;
- node.g = 0;
- node.h = 0;
- node.visited = false;
- node.closed = false;
- node.parent = null;
- // copy[x][y] = node;
- }
- }
- // return copy;
- },
-
- search: function search(grid, start, end, heuristic, ignore) {
- astar.init(grid);
- heuristic = heuristic || astar.manhattan;
-
- ignore = ignore || [];
- ignore.push(start.value);
- ignore.push(end.value);
-
- var open = new BinaryHeap('f');
- open.push(start);
-
- while( open.length > 0 ) {
-
- // Grab the lowest f(x) to process next. Heap keeps this sorted for us.
- var current = open.pop();
-
- // End case -- result has been found, return the traced path
- if(current === end) {
- var path = []
- , node = current;
- while( node.parent ) {
- path.push( node.clone() );
- node = node.parent;
- }
- return path.reverse();
- }
-
- // Normal case -- move current from open to closed, process each of its neighbors
- current.closed = true;
-
- var neighbors = astar.neighbors(grid, current);
- for(var i=0, il = neighbors.length; i < il; i++) {
- var neighbor = neighbors[i];
-
- // blocker
- if( neighbor.closed || (neighbor.blocked && ignore.indexOf(neighbor.value) === -1) )
- continue;
-
- // g score is the shortest distance from start to current node, we need to check if
- // the path we have arrived at this neighbor is the shortest one we have seen yet.
- // We define the distance from a node to it's neighbor as 1, but this could be variable for weighted paths.
- var g = current.g + 1;
-
- if( !neighbor.visited || g < neighbor.g ) {
-
- // Found an optimal (so far) path to this node. Take score for node to see how good it is.
- neighbor.parent = current;
- neighbor.h = neighbor.h || heuristic(neighbor, end);
- neighbor.g = g;
- neighbor.f = g + neighbor.h;
-
- // New? Add to the set of nodes to process
- if ( !neighbor.visited ) {
- neighbor.visited = true;
- open.push(neighbor);
-
- // Seen, but since it has been rescored we need to reorder it in the heap
- } else
- open.rescore(neighbor);
- }
- }
- }
-
- // No result was found -- empty array signifies failure to find path
- return [];
- },
-
- manhattan: function manhattan(p1, p2) {
- // See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
- var d1 = Math.abs(p2.x - p1.x)
- , d2 = Math.abs(p2.y - p1.y) ;
- return d1 + d2;
- },
-
- manhattan4: function manhattan(x1,y1, x2,y2) {
- // See list of heuristics: http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
- var d1 = Math.abs(x2 - x1)
- , d2 = Math.abs(y2 - y1) ;
- return d1 + d2;
- },
-
- neighbors: function neighbors(grid, node) {
- var ret = [];
- var x = node.x;
- var y = node.y;
-
- if(grid[x-1] && grid[x-1][y]) {
- ret.push(grid[x-1][y]);
- }
- if(grid[x+1] && grid[x+1][y]) {
- ret.push(grid[x+1][y]);
- }
- if(grid[x] && grid[x][y-1]) {
- ret.push(grid[x][y-1]);
- }
- if(grid[x] && grid[x][y+1]) {
- ret.push(grid[x][y+1]);
- }
- return ret;
- }
-};
-(function(){
function BinaryHeap(score){
if (typeof score === 'string')
// Add methods to prototype
for (var k in methods) proto[k] = methods[k];
-this.BinaryHeap = BinaryHeap;
+exports['BinaryHeap'] = BinaryHeap;
-})();
\ No newline at end of file
+var Vec = require('ezl/math/vec').Vec;
+
+exports['Graph'] =
function Graph(grid) {
this.grid = grid;
this.nodes = [];
var row = grid[x];
this.nodes[x] = [];
for (var y = 0; y < row.length; y++) {
- var n = new math.Vec(x,y);
+ var n = new Vec(x,y);
n.blocked = !!row[y];
this.nodes[x].push(n);
}
}
-}
+};
-(function(){
+var CAPACITY = 8
+, REGION_ID = 0
+,
-function Rect(x1,y1, x2,y2){
- var sm_x = Math.min(x1,x2), lg_x = Math.max(x1,x2)
- , sm_y = Math.min(y1,y2), lg_y = Math.max(y1,y2);
- this.x1 = this.x = sm_x;
- this.y1 = this.y = sm_y;
- this.x2 = lg_x;
- this.y2 = lg_y;
- this.width = lg_x-sm_x;
- this.height = lg_y-sm_y;
-}
-function rectToString(o){
- var p = 2
- , x1 = o.x1, y1 = o.y1
- , x2 = o.x2, y2 = o.y2 ;
- x1 = ((x1 % 1 !== 0) ? x1.toFixed(p) : x1);
- y1 = ((y1 % 1 !== 0) ? y1.toFixed(p) : y1);
- x2 = ((x2 % 1 !== 0) ? x2.toFixed(p) : x2);
- y2 = ((y2 % 1 !== 0) ? y2.toFixed(p) : y2);
- return '['+x1+','+y1+', '+x2+','+y2+']';
-}
-var
-CAPACITY = 8,
-REGION_ID = 0,
-
-Region = Y.subclass('Region', {
+Region =
+exports['Region'] =
+Y.subclass('Region', {
init : function init(x1,y1, x2,y2, value){
Rect.call(this, x1,y1, x2,y2);
this.id = REGION_ID++;
toString : function toString(){
return this.className+'(id='+this.id+', rect='+rectToString(this)+', value='+this.value+')';
}
-}),
+})
+,
+
-QuadTree = Y.subclass('QuadTree', {
+QuadTree =
+exports['QuadTree'] =
+Y.subclass('QuadTree', {
depth : 0,
parent : null,
regions : [],
}
});
-QuadTree['Region'] = Region;
-this['QuadTree'] = QuadTree;
-})();
+
+function Rect(x1,y1, x2,y2){
+ var sm_x = Math.min(x1,x2), lg_x = Math.max(x1,x2)
+ , sm_y = Math.min(y1,y2), lg_y = Math.max(y1,y2);
+ this.x1 = this.x = sm_x;
+ this.y1 = this.y = sm_y;
+ this.x2 = lg_x;
+ this.y2 = lg_y;
+ this.width = lg_x-sm_x;
+ this.height = lg_y-sm_y;
+}
+function rectToString(o){
+ var p = 2
+ , x1 = o.x1, y1 = o.y1
+ , x2 = o.x2, y2 = o.y2 ;
+ x1 = ((x1 % 1 !== 0) ? x1.toFixed(p) : x1);
+ y1 = ((y1 % 1 !== 0) ? y1.toFixed(p) : y1);
+ x2 = ((x2 % 1 !== 0) ? x2.toFixed(p) : x2);
+ y2 = ((y2 % 1 !== 0) ? y2.toFixed(p) : y2);
+ return '['+x1+','+y1+', '+x2+','+y2+']';
+}
+
-(function(){
-var RED = "Red"
-, BLACK = "Black"
+var RED = exports['RED'] = "Red"
+, BLACK = exports['BLACK'] = "Black"
, FLIP_COLOR = {};
+
FLIP_COLOR[RED] = BLACK;
FLIP_COLOR[BLACK] = RED;
-
-function isRed(n) { return n && (n.color == RED); }
-function isBlack(n) { return n && (n.color == BLACK); }
-function size(n) { return (n && n.N) || 0; }
-
-
-function Node(key, val, color, N) {
- this.key = key;
- this.val = val;
- this.color = color;
- this.N = N;
- this.left = null;
- this.right = null;
-}
-Node.prototype.toString = function(){
- var S = (this.color === RED ? '[' : '(')
- , E = (this.color === RED ? ']' : ')');
- return S+this.key+' '+this.val+E;
-};
-
-var
-RedBlackTree = Y.subclass('RedBlackTree', {
- init : function init(key, value){
+RedBlackTree =
+exports['RedBlackTree'] =
+Y.subclass('RedBlackTree', {
+ _root : null,
+
+
+ init : function initRedBlackTree(key, value){
if (this.key !== undefined)
this.setKey(key, value);
},
- _root : null,
-
/*************************************************************************
* Size methods
*************************************************************************/
});
-RedBlackTree['RED'] = RED;
-RedBlackTree['BLACK'] = BLACK;
-RedBlackTree['Node'] = Node;
-this['RedBlackTree'] = RedBlackTree;
+function isRed(n) { return n && (n.color == RED); }
+function isBlack(n) { return n && (n.color == BLACK); }
+function size(n) { return (n && n.N) || 0; }
-})();
+var
+Node =
+exports['Node'] =
+function Node(key, val, color, N) {
+ this.key = key;
+ this.val = val;
+ this.color = color;
+ this.N = N;
+ this.left = null;
+ this.right = null;
+};
+Node.prototype.toString = function(){
+ var S = (this.color === RED ? '[' : '(')
+ , E = (this.color === RED ? ']' : ')');
+ return S+this.key+' '+this.val+E;
+};
Level = Rect.subclass('Level', {
- _cssClasses : 'portal layer level',
+ _cssClasses : 'ezl layer level',
init : function init(game, w,h){
Rect.init.call(this, w,h);
+++ /dev/null
-// [x,y]
-Loc = new Y.Class('Loc', new math.Vec(0,0), {
-
- // init : function init(x,y){
- // math.Vec.init.call(this, x,y);
- // },
-
- set : function set(k, v, def){
- v = (v !== undefined ? v : def);
- switch (k) {
- case 'x': case 0:
- this.x = this[0] = v; break;
- case 'y': case 1:
- this.y = this[1] = v; break;
- default:
- this[k] = v;
- }
- return this;
- },
- attr : Y.attr.methodize(),
-
- clone : function clone(){
- return new Loc(this.x, this.y);
- },
-
- moveBy : function moveBy(x,y){
- return new Loc(this.x+x, this.y+y);
- },
-
- moveByAngle : function moveByAngle(theta, v){
- var x = this.x + v*Math.cos(theta)
- , y = this.y + v*Math.sin(theta);
- return new Loc(x,y);
- },
-
- moveByDir : function moveByDir(dir, v){
- return this.moveByAngle( Loc.dirToAngle(dir), v );
- },
-
- toSquare : function toSquare(){
- return Loc.Square.fromLoc(this.x, this.y);
- },
-
- /**
- * Converts relative locations like ('50%','50%') to a numeric location.
- */
- absolute : function absolute(w,h){
- var x = this.x, y = this.y
- return new Loc( Y.isString(x) ? parseFloat(x.slice(0,-1))/100 * w : x
- , Y.isString(y) ? parseFloat(y.slice(0,-1))/100 * h : y );
- },
-
- toUnits : function toUnits(units){
- units = units || 'px';
- var x = this.x, y = this.y;
- return { 'x' : Y.isNumber(x) ? x+units : x
- , 'y' : Y.isNumber(y) ? y+units : y };
- },
-
- toString : function toString(){
- var x = this.x, y = this.y;
- x = Y.isNumber(x) ? x.toFixed(2) : x;
- y = Y.isNumber(y) ? y.toFixed(2) : y;
- return '('+x+','+y+')';
- }
-
-});
-Y(Loc).extend({
- UP : 'up', DOWN : 'down',
- RIGHT : 'right', LEFT : 'left',
-
- UP_RIGHT : 'right up', UP_LEFT : 'left up',
- DOWN_RIGHT : 'down right', DOWN_LEFT : 'down left',
-
- dirToAngle : function dirToAngle(dir){
- switch (dir) {
- case Loc.RIGHT: return 0;
- case Loc.DOWN_RIGHT: return QUARTER_PI;
- case Loc.DOWN: return HALF_PI;
- case Loc.DOWN_LEFT: return HALF_PI+QUARTER_PI;
- case Loc.LEFT: return PI;
- case Loc.UP_LEFT: return PI+QUARTER_PI;
- case Loc.UP: return PI_AND_HALF;
- case Loc.UP_RIGHT: return PI_AND_HALF+QUARTER_PI;
-
- default: throw new Error("wtf direction is "+dir+"??");
- }
- },
-
- fromSquare : function fromSquare(col, row){
- return new Loc(
- col * REF_SIZE,
- row * REF_SIZE );
- },
-
- // XXX: Probably wrong for negative locations
- centerInSquare : function centerInSquare(v){
- return Math.floor(v/REF_SIZE)*REF_SIZE + REF_SIZE/2;
- }
-
-});
-
-// [x1,y1, x2,y2]
-Loc.Rect = new Y.Class('Rect', [], {
-
- init : function initRect(x1,y1, x2,y2){
- if (x1 instanceof Array && y1 instanceof Array) {
- y2 = y1[1]; x2 = y1[0];
- y1 = x1[1]; x1 = x1[0];
- }
- // init : function initRect(_x1,_y1, _x2,_y2){
- // if (_x1 instanceof Array && _y1 instanceof Array) {
- // _y2 = _y1[1]; _x2 = _y1[0];
- // _y1 = _x1[1]; _x1 = _x1[0];
- // }
- // var x1 = Math.min(_x1,_x2), x2 = Math.max(_x1,_x2)
- // , y1 = Math.min(_y1,_y2), y2 = Math.max(_y1,_y2);
-
- this.length = 4;
- 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.p1 = new Loc(x1,y1);
- this.p2 = new Loc(x2,y2);
- },
-
- contains : function contains(x,y){
- return ( x >= this.x1 && x <= this.x2 &&
- y >= this.y1 && y <= this.y2 );
- },
-
- intersects : function intersects(line){
- var x1 = Math.min(this.x1,this.x2), x2 = Math.max(this.x1,this.x2)
- , y1 = Math.min(this.y1,this.y2), y2 = Math.max(this.y1,this.y2)
- , cx1,cy1, cx2,cy2 ;
- return ( ( (cx1 = line.calcX(y1)) >= x1 && cx1 <= x2 )
- || ( (cy1 = line.calcY(x1)) >= y1 && cy1 <= y2 )
- || ( (cx2 = line.calcX(y2)) >= x1 && cx2 <= x2 )
- || ( (cy2 = line.calcY(x2)) >= y1 && cy2 <= y2 ) );
- },
-
- midpoint : function midpoint(){
- return new Loc( this.x1 + this.width /2
- , this.y1 + this.height/2 );
- },
-
- clone : function clone(){
- return new Loc.Rect( this.p1.clone()
- , this.p2.clone() );
- },
-
- toString : function toString(){
- return '['+this.p1+' '+this.p2+']';
- }
-});
-
-Loc.BoundingBox = Loc.Rect.subclass('BoundingBox', {
- init : function initBoundingBox(x1,y1, x2,y2){
- Loc.Rect.init.call(this, x1,y1, x2,y2);
-
- 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){
- v = (v !== undefined ? v : def);
-
- switch (k) {
- case 'x1': case 0: case 'x': this.x1 = this[0] = this.x = v; break;
- case 'y1': case 1: case 'y': this.y1 = this[1] = this.y = v; break;
- case 'x2': case 2: this.x2 = this[2] = v; break;
- case 'y1': case 3: this.y2 = this[3] = v; break;
-
- default: this[k] = v;
- }
-
- this.width = this.x2 - this.x1;
- this.height = this.y2 - this.y1;
-
- return this._updateSides();
- },
-
- _updateSides : function _updateSides(){
- var s = this.sides
- , x1 = this.x1, y1 = this.y1
- , x2 = this.x2, y2 = this.y2
- , dx1 = x1 !== s.top.x1, dy1 = y1 !== s.top.y1
- , dx2 = x2 !== s.top.x2, dy2 = y2 !== s.left.y2
- ;
-
- if ( dx1 || dy1 ) this.p1 = new Loc(x1,y1);
- if ( dx2 || dy2 ) this.p2 = new Loc(x2,y2);
-
- if ( dx1 || dy1 || dx2 ) s.top = new math.Line(x1,y1, x2,y1);
- if ( dx1 || dx2 || dy2 ) s.bottom = new math.Line(x1,y2, x2,y2);
- if ( dx1 || dy1 || dy2 ) s.left = new math.Line(x1,y1, x1,y2);
- if ( dy1 || dy2 || dx2 ) s.right = new math.Line(x2,y1, x2,y2);
-
- return this;
- },
-
- attr : Y.attr.methodize(),
-
- add : function add(x,y){
- return new Loc.BoundingBox(x,y, x+this.width,y+this.height);
- },
-
- resize : function resize(w,h){
- var x = this.x, y = this.y;
- return new Loc.BoundingBox(x,y, x+w,y+h);
- },
-
- clone : function clone(){
- return new Loc.BoundingBox( this.p1.clone(), this.p2.clone() );
- }
-
-});
-
-Loc.Square = new Y.Class('Square', Loc.BoundingBox, {
- init : function init(col, row){
- this.col = col;
- this.row = row;
-
- var x1 = col * REF_SIZE, y1 = row * REF_SIZE
- , x2 = x1 + REF_SIZE, y2 = y1 + REF_SIZE
- ;
-
- Loc.Rect.init.call(this, x1,y1, x2,y2);
- },
-
- clone : function clone(){
- return new Square(this.col, this.row);
- },
-
- toLoc : function toLoc(){
- return Loc.fromSquare(this.col, this.row);
- },
-
- toString : function toString(){
- return this.col+'_'+this.row;
- }
-
-});
-
-// XXX: Negative grid positions don't round correctly
-Loc.Square.fromLoc = function(x, y){
- return new Loc.Square(
- Math.floor(x / REF_SIZE),
- Math.floor(y / REF_SIZE) );
-};
-
Grid = new Y.Class('Grid', Rect, {
- _cssClasses : 'portal layer shape rect grid',
+ _cssClasses : 'ezl layer shape rect grid',
lineWidth : 0.5,
strokeStyle : '#6E6E6E',
const SRC_AND_LIB = 6; // LIB_SCRIPTS | SRC_SCRIPTS;
const ALL_SCRIPTS = 7; // MAIN_SCRIPTS | LIB_SCRIPTS | SRC_SCRIPTS;
+ const BUILD_DIR = "build";
- static $mainCJS = array(
- "src/tanks/ui/main.cjs"
+ static $modules = array(
+ array( "main" => "src/Y/index.cjs", "loader" => "y-loader.js" )
);
+
+
static $mainScripts = array(
"src/tanks/ui/main.js"
);
-
-
static $srcScripts = array(
"src/tanks/tanks.js",
"src/tanks/globals.js",
static function writeTags($scripts=null, $prefix="", $recompile=true) {
$scripts = $scripts ? $scripts : Tanks::SRC_AND_LIB;
- if ($recompile) Tanks::compile();
-
if ($scripts & Tanks::LIB_SCRIPTS) foreach (self::$libScripts as $s) js($s, $prefix);
if ($scripts & Tanks::SRC_SCRIPTS) foreach (self::$srcScripts as $s) js($s, $prefix);
if ($scripts & Tanks::MAIN_SCRIPTS) foreach (self::$mainScripts as $s) js($s, $prefix);
}
- static function compile($main=null) {
- $main = ($main ? $main : self::$mainCJS);
- $scripts = join($main, " ");
- shell_exec("cjs.py $scripts");
+ static function compile($modules=null) {
+ $modules = ($modules ? $modules : self::$modules);
+ $PYTHONPATH = "PYTHONPATH='/Users/dsc/.python/lib/python:/usr/local/lib/python2.7/site-packages:/usr/local/lib/python2.6/site-packages'";
+ // error_reporting(E_ALL);
+ // echo "<!--";
+ foreach ($modules as $module) {
+ $ret = shell_exec("$PYTHONPATH bin/cjs.py -s {$module['main']} -- src lib 2>&1");
+ echo " ".trim(join("\n ", split("\n", $ret)));
+ }
+ // echo "-->";
}
+ static function writeLoaders($modules=null, $recompile=true){
+ $modules = ($modules ? $modules : self::$modules);
+ js('lib/cjs/require.js');
+ if ($recompile) Tanks::compile($modules);
+ // foreach ($modules as $module) js($module['loader'], Tanks::BUILD_DIR."/");
+ }
}