diff --git a/index.html b/index.html
index 03cdd04..31f9e78 100644
--- a/index.html
+++ b/index.html
@@ -1,23 +1,17 @@
-
+
-
-genossen! am 30.11. laden neingeist und starbug ein zu einem cosmonautischen fest!
-
-
-
-
-
-
-
-
+
+ genossen! am 30.11. laden neingeist und starbug ein zu einem cosmonautischen fest!
-
-
+
+
+
+
diff --git a/lib/quintus.js b/lib/quintus.js
deleted file mode 100644
index b487d0a..0000000
--- a/lib/quintus.js
+++ /dev/null
@@ -1,1599 +0,0 @@
-// Quintus Game Engine
-// (c) 2012 Pascal Rettig, Cykod LLC
-// Quintus may be freely distributed under the MIT license or GPLv2 License.
-// For all details and documentation:
-// http://html5quintus.com
-//
-/**
-Quintus HTML5 Game Engine
-
-The code in `quintus.js` defines the base `Quintus()` method
-which create an instance of the engine. The basic engine doesn't
-do a whole lot - it provides an architecture for extension, a
-game loop, and a method for creating or binding to an exsiting
-canvas context. The engine has dependencies on Underscore.js and jQuery,
-although the jQuery dependency will be removed in the future.
-
-Most of the game-specific functionality is in the
-various other modules:
-
-* `quintus_input.js` - `Input` module, which allows for user input via keyboard and touchscreen
-* `quintus_sprites.js` - `Sprites` module, which defines a basic `Q.Sprite` class along with spritesheet support in `Q.SpriteSheet`.
-* `quintus_scenes.js` - `Scenes` module. It defines the `Q.Scene` class, which allows creation of reusable scenes, and the `Q.Stage` class, which handles managing a number of sprites at once.
-* `quintus_anim.js` - `Anim` module, which adds in support for animations on sprites along with a `viewport` component to follow the player around and a `Q.Repeater` class that can create a repeating, scrolling background.
-
-@module Quintus
-*/
-
-/**
- Top-level Quintus engine factory wrapper,
- creates new instances of the engine by calling:
-
- var Q = Quintus({ ... });
-
- Any initial setup methods also all return the `Q` object, allowing any initial
- setup calls to be chained together.
-
- var Q = Quintus()
- .include("Input, Sprites, Scenes")
- .setup('quintus', { maximize: true })
- .controls();
-
- `Q` is used internally as the object name, and is used in most of the examples,
- but multiple instances of the engine on the same page can have different names.
-
- var Game1 = Quintus(), Game2 = Quintus();
-
-@class Quintus
-**/
-var Quintus = function Quintus(opts) {
-
- /**
- A la jQuery - the returned `Q` object is actually
- a method that calls `Q.select`. `Q.select` doesn't do anything
- initially, but can be overridden by a module to allow
- selection of game objects. The `Scenes` module adds in
- the select method which selects from the default stage.
-
- var Q = Quintus().include("Sprites, Scenes");
- ... Game Code ...
- // Set the angry property on all Enemy1 class objects to true
- Q("Enemy1").p({ angry: true });
-
- @method Q
- @for Quintus
- */
- var Q = function(selector,scope,options) {
- return Q.select(selector,scope,options);
- };
-
- /**
- Default no-op select method. Replaced with the Quintus.Scene class
-
- @method Q.select
- @for Quintus
- */
- Q.select = function() { /* No-op */ };
-
- // Syntax for including other modules into quintus, can accept a comma-separated
- // list of strings, an array of strings, or an array of actual objects. Example:
- //
- // Q.include("Input, Sprites, Scenes")
- //
- Q.include = function(mod) {
- Q._each(Q._normalizeArg(mod),function(name) {
- var m = Quintus[name] || name;
- if(!Q._isFunction(m)) { throw "Invalid Module:" + name; }
- m(Q);
- });
- return Q;
- };
-
- // Utility Methods
- // ===============
- //
- // Most of these utility methods are a subset of Underscore.js,
- // Most are pulled directly from underscore and some are
- // occasionally optimized for speed and memory usage in lieu of flexibility.
- // Underscore.js is (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
- // Underscore is freely distributable under the MIT license.
- // http://underscorejs.org
-
- // An internal utility method (utility methods are prefixed with underscores)
- // It's used to take a string of comma separated names and turn it into an `Array`
- // of names. If an array of names is passed in, it's left as is. Example usage:
- //
- // Q._normalizeArg("Sprites, Scenes, Physics ");
- // // returns [ "Sprites", "Scenes", "Physics" ]
- //
- // Used by `Q.include` and `Q.Sprite.add` to add modules and components, respectively.
- Q._normalizeArg = function(arg) {
- if(Q._isString(arg)) {
- arg = arg.replace(/\s+/g,'').split(",");
- }
- if(!Q._isArray(arg)) {
- arg = [ arg ];
- }
- return arg;
- };
-
-
- // Extends a destination object
- // with a source object
- Q._extend = function(dest,source) {
- if(!source) { return dest; }
- for (var prop in source) {
- dest[prop] = source[prop];
- }
- return dest;
- };
-
- // Return a shallow copy of an object. Sub-objects (and sub-arrays) are not cloned.
- Q._clone = function(obj) {
- return Q._extend({},obj);
- };
-
- // Method that adds default properties onto
- // an object only if the key is undefined
- Q._defaults = function(dest,source) {
- if(!source) { return dest; }
- for (var prop in source) {
- if(dest[prop] === void 0) {
- dest[prop] = source[prop];
- }
- }
- return dest;
- };
-
- // Shortcut for hasOwnProperty
- Q._has = function(obj, key) {
- return Object.prototype.hasOwnProperty.call(obj, key);
- };
-
- // Check if something is a string
- // NOTE: this fails for non-primitives
- Q._isString = function(obj) {
- return typeof obj === "string";
- };
-
- Q._isNumber = function(obj) {
- return Object.prototype.toString.call(obj) === '[object Number]';
- };
-
- // Check if something is a function
- Q._isFunction = function(obj) {
- return Object.prototype.toString.call(obj) === '[object Function]';
- };
-
- // Check if something is a function
- Q._isObject = function(obj) {
- return Object.prototype.toString.call(obj) === '[object Object]';
- };
-
- // Check if something is a function
- Q._isArray = function(obj) {
- return Object.prototype.toString.call(obj) === '[object Array]';
- };
-
- // Check if something is undefined
- Q._isUndefined = function(obj) {
- return obj === void 0;
- };
-
- // Removes a property from an object and returns it
- Q._popProperty = function(obj,property) {
- var val = obj[property];
- delete obj[property];
- return val;
- };
-
- // Basic iteration method. This can often be a performance
- // handicap when the callback iterator is created inline,
- // as this leads to lots of functions that need to be GC'd.
- // Better is to define the iterator as a private method so
- // it is only created once.
- Q._each = function(obj,iterator,context) {
- if (obj == null) { return; }
- if (obj.forEach) {
- obj.forEach(iterator,context);
- } else if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- iterator.call(context, obj[i], i, obj);
- }
- } else {
- for (var key in obj) {
- iterator.call(context, obj[key], key, obj);
- }
- }
- };
-
- // Invoke the named property on each element of the array
- Q._invoke = function(arr,property,arg1,arg2) {
- if (arr == null) { return; }
- for (var i = 0, l = arr.length; i < l; i++) {
- arr[i][property](arg1,arg2);
- }
- };
-
-
-
- // Basic detection method, returns the first instance where the
- // iterator returns truthy.
- Q._detect = function(obj,iterator,context,arg1,arg2) {
- var result;
- if (obj == null) { return; }
- if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- result = iterator.call(context, obj[i], i, arg1,arg2);
- if(result) { return result; }
- }
- return false;
- } else {
- for (var key in obj) {
- result = iterator.call(context, obj[key], key, arg1,arg2);
- if(result) { return result; }
- }
- return false;
- }
- };
-
- // Returns a new Array with entries set to the return value of the iterator.
- Q._map = function(obj, iterator, context) {
- var results = [];
- if (obj == null) { return results; }
- if (obj.map) { return obj.map(iterator, context); }
- Q._each(obj, function(value, index, list) {
- results[results.length] = iterator.call(context, value, index, list);
- });
- if (obj.length === +obj.length) { results.length = obj.length; }
- return results;
- };
-
- // Returns a sorted copy of unique array elements with null remove
- Q._uniq = function(arr) {
- arr = arr.slice().sort();
-
- var output = [];
-
- var last = null;
- for(var i=0;i Q.options.frameTimeLimit) { dt = Q.options.frameTimeLimit; }
- callback.apply(Q,[dt / 1000]);
- Q.lastGameLoopFrame = now;
- };
-
- window.requestAnimationFrame(Q.gameLoopCallbackWrapper);
- return Q;
- };
-
- // Pause the entire game by canceling the requestAnimationFrame call. If you use setTimeout or
- // setInterval in your game, those will, of course, keep on rolling...
- Q.pauseGame = function() {
- if(Q.loop) {
- window.cancelAnimationFrame(Q.loop);
- }
- Q.loop = null;
- };
-
- // Unpause the game by restarting the requestAnimationFrame-based loop.
- Q.unpauseGame = function() {
- if(!Q.loop) {
- Q.lastGameLoopFrame = new Date().getTime();
- Q.loop = window.requestAnimationFrame(Q.gameLoopCallbackWrapper);
- }
- };
-
-
- /**
- The base Class object
-
- Quintus uses the Simple JavaScript inheritance Class object, created by
- John Resig and described on his blog:
-
- [http://ejohn.org/blog/simple-javascript-inheritance/](http://ejohn.org/blog/simple-javascript-inheritance/)
-
- The class is used wholesale, with the only differences being that instead
- of appearing in a top-level namespace, the `Class` object is available as
- `Q.Class` and a second argument on the `extend` method allows for adding
- class level methods and the class name is passed in a parameter for introspection
- purposes.
-
- Classes can be created by calling `Q.Class.extend(name,{ .. })`, although most of the time
- you'll want to use one of the derivitive classes, `Q.Evented` or `Q.GameObject` which
- have a little bit of functionality built-in. `Q.Evented` adds event binding and
- triggering support and `Q.GameObject` adds support for components and a destroy method.
-
- The main things Q.Class get you are easy inheritance, a constructor method called `init()`,
- dynamic addition of a this._super method when a method is overloaded (be careful with
- this as it adds some overhead to method calls.) Calls to `instanceof` also all
- work as you'd hope.
-
- By convention, classes should be added onto to the `Q` object and capitalized, so if
- you wanted to create a new class for your game, you'd write:
-
- Q.Class.extend("MyClass",{ ... });
-
- Examples:
-
- Q.Class.extend("Bird",{
- init: function(name) { this.name = name; },
- speak: function() { console.log(this.name); },
- fly: function() { console.log("Flying"); }
- });
-
- Q.Bird.extend("Penguin",{
- speak: function() { console.log(this.name + " the penguin"); },
- fly: function() { console.log("Can't fly, sorry..."); }
- });
-
- var randomBird = new Q.Bird("Frank"),
- pengy = new Q.Penguin("Pengy");
-
- randomBird.fly(); // Logs "Flying"
- pengy.fly(); // Logs "Can't fly,sorry..."
-
- randomBird.speak(); // Logs "Frank"
- pengy.speak(); // Logs "Pengy the penguin"
-
- console.log(randomBird instanceof Q.Bird); // true
- console.log(randomBird instanceof Q.Penguin); // false
- console.log(pengy instanceof Q.Bird); // true
- console.log(pengy instanceof Q.Penguin); // true
-
- Simple JavaScript Inheritance
- By John Resig http://ejohn.org/
- MIT Licensed.
-
- Inspired by base2 and Prototype
- @class Q.Class
- @for Quintus
- */
- (function(){
- var initializing = false,
- fnTest = /xyz/.test(function(){ var xyz;}) ? /\b_super\b/ : /.*/;
- /** The base Class implementation (does nothing)
- *
- * @constructor
- * @for Q.Class
- */
- Q.Class = function(){};
-
- /**
- * See if a object is a specific class
- *
- * @method isA
- */
- Q.Class.prototype.isA = function(className) {
- return this.className === className;
- };
-
- /**
- * Create a new Class that inherits from this class
- *
- * @method extend
- */
- Q.Class.extend = function(className, prop, classMethods) {
- /* No name, don't add onto Q */
- if(!Q._isString(className)) {
- classMethods = prop;
- prop = className;
- className = null;
- }
- var _super = this.prototype,
- ThisClass = this;
-
- /* Instantiate a base class (but only create the instance, */
- /* don't run the init constructor) */
- initializing = true;
- var prototype = new ThisClass();
- initializing = false;
-
- function _superFactory(name,fn) {
- return function() {
- var tmp = this._super;
-
- /* Add a new ._super() method that is the same method */
- /* but on the super-class */
- this._super = _super[name];
-
- /* The method only need to be bound temporarily, so we */
- /* remove it when we're done executing */
- var ret = fn.apply(this, arguments);
- this._super = tmp;
-
- return ret;
- };
- }
-
- /* Copy the properties over onto the new prototype */
- for (var name in prop) {
- /* Check if we're overwriting an existing function */
- prototype[name] = typeof prop[name] === "function" &&
- typeof _super[name] === "function" &&
- fnTest.test(prop[name]) ?
- _superFactory(name,prop[name]) :
- prop[name];
- }
-
- /* The dummy class constructor */
- function Class() {
- /* All construction is actually done in the init method */
- if ( !initializing && this.init ) {
- this.init.apply(this, arguments);
- }
- }
-
- /* Populate our constructed prototype object */
- Class.prototype = prototype;
-
- /* Enforce the constructor to be what we expect */
- Class.prototype.constructor = Class;
- /* And make this class extendable */
- Class.extend = Q.Class.extend;
-
- /* If there are class-level Methods, add them to the class */
- if(classMethods) {
- Q._extend(Class,classMethods);
- }
-
- if(className) {
- /* Save the class onto Q */
- Q[className] = Class;
-
- /* Let the class know its name */
- Class.prototype.className = className;
- Class.className = className;
- }
-
- return Class;
- };
- }());
-
-
- // Event Handling
- // ==============
-
- /**
- The `Q.Evented` class adds event handling onto the base `Q.Class`
- class. Q.Evented objects can trigger events and other objects can
- bind to those events.
-
- @class Q.Evented
- @for Quintus
- */
- Q.Class.extend("Evented",{
-
- /**
- Binds a callback to an event on this object. If you provide a
- `target` object, that object will add this event to it's list of
- binds, allowing it to automatically remove it when it is destroyed.
-
- @method on
- @for Q.Evented
- */
- on: function(event,target,callback) {
- if(Q._isArray(event) || event.indexOf(",") !== -1) {
- event = Q._normalizeArg(event);
- for(var i=0;i=0;i--) {
- if(l[i][0] === target) {
- if(!callback || callback === l[i][1]) {
- this.listeners[event].splice(i,1);
- }
- }
- }
- }
- }
- },
-
- // `debind` is called to remove any listeners an object had
- // on other objects. The most common case is when an object is
- // destroyed you'll want all the event listeners to be removed
- // for you.
- debind: function() {
- if(this.binds) {
- for(var i=0,len=this.binds.length;i resampleWidth) ||
- (resampleHeight && h > resampleHeight)) &&
- Q.touchDevice) {
- Q.el.style.height = h + "px";
- Q.el.style.width = w + "px";
- Q.el.width = w / 2;
- Q.el.height = h / 2;
- } else {
- Q.el.style.height = h + "px";
- Q.el.style.width = w + "px";
- Q.el.width = w;
- Q.el.height = h;
- }
-
- var elParent = Q.el.parentNode;
-
- if(elParent) {
- Q.wrapper = document.createElement("div");
- Q.wrapper.id = id + '_container';
- Q.wrapper.style.width = w + "px";
- Q.wrapper.style.margin = "0 auto";
- Q.wrapper.style.position = "relative";
-
-
- elParent.insertBefore(Q.wrapper,Q.el);
- Q.wrapper.appendChild(Q.el);
- }
-
- Q.el.style.position = 'relative';
-
- Q.ctx = Q.el.getContext &&
- Q.el.getContext("2d");
-
-
- Q.width = parseInt(Q.el.width,10);
- Q.height = parseInt(Q.el.height,10);
- Q.cssWidth = w;
- Q.cssHeight = h;
-
- window.addEventListener('orientationchange',function() {
- setTimeout(function() { window.scrollTo(0,1); }, 0);
- });
-
- return Q;
- };
-
-
- // Clear the canvas completely.
- Q.clear = function() {
- if(Q.clearColor) {
- Q.ctx.globalAlpha = 1;
- Q.ctx.fillStyle = Q.clearColor;
- Q.ctx.fillRect(0,0,Q.width,Q.height);
- } else {
- Q.ctx.clearRect(0,0,Q.width,Q.height);
- }
- };
-
-
- // Return canvas image data given an Image object.
- Q.imageData = function(img) {
- var canvas = document.createElement("canvas");
-
- canvas.width = img.width;
- canvas.height = img.height;
-
- var ctx = canvas.getContext("2d");
- ctx.drawImage(img,0,0);
-
- return ctx.getImageData(0,0,img.width,img.height);
- };
-
-
-
- // Asset Loading Support
- // =====================
- //
- // The engine supports loading assets of different types using
- // `load` or `preload`. Assets are stored by their name so the
- // same asset won't be loaded twice if it already exists.
-
- // Augmentable list of asset types, loads a specific asset
- // type if the file type matches, otherwise defaults to a Ajax
- // load of the data.
- //
- // You can new types of assets based on file extension by
- // adding to `assetTypes` and adding a method called
- // loadAssetTYPENAME where TYPENAME is the name of the
- // type you added in.
- Q.assetTypes = {
- png: 'Image', jpg: 'Image', gif: 'Image', jpeg: 'Image',
- ogg: 'Audio', wav: 'Audio', m4a: 'Audio', mp3: 'Audio'
- };
-
-
- // Determine the type of asset based on the lookup table above
- Q.assetType = function(asset) {
- /* Determine the lowercase extension of the file */
- var fileParts = asset.split("."),
- fileExt = fileParts[fileParts.length-1].toLowerCase();
-
- // Use the web audio loader instead of the regular loader
- // if it's supported.
- var fileType = Q.assetTypes[fileExt];
- if(fileType === 'Audio' && Q.audio && Q.audio.type === "WebAudio") {
- fileType = 'WebAudio';
- }
-
- /* Lookup the asset in the assetTypes hash, or return other */
- return fileType || 'Other';
- };
-
- // Either return an absolute URL,
- // or add a base to a relative URL
- Q.assetUrl = function(base,url) {
- var timestamp = "";
- if(Q.options.development) {
- timestamp = (/\?/.test(url) ? "&" : "?") + "_t=" +new Date().getTime();
- }
- if(/^https?:\/\//.test(url) || url[0] === "/") {
- return url + timestamp;
- } else {
- return base + url + timestamp;
- }
- };
-
- // Loader for Images, creates a new `Image` object and uses the
- // load callback to determine the image has been loaded
- Q.loadAssetImage = function(key,src,callback,errorCallback) {
- var img = new Image();
- img.onload = function() { callback(key,img); };
- img.onerror = errorCallback;
- img.src = Q.assetUrl(Q.options.imagePath,src);
- };
-
-
- // List of mime types given an audio file extension, used to
- // determine what sound types the browser can play using the
- // built-in `Sound.canPlayType`
- Q.audioMimeTypes = { mp3: 'audio/mpeg',
- ogg: 'audio/ogg; codecs="vorbis"',
- m4a: 'audio/m4a',
- wav: 'audio/wav' };
-
- Q._audioAssetExtension = function() {
- if(Q._audioAssetPreferredExtension) { return Q._audioAssetPreferredExtension; }
-
- var snd = new Audio();
-
- /* Find a supported type */
- return Q._audioAssetPreferredExtension =
- Q._detect(Q.options.audioSupported,
- function(extension) {
- return snd.canPlayType(Q.audioMimeTypes[extension]) ?
- extension : null;
- });
- };
-
- // Loader for Audio assets. By default chops off the extension and
- // will automatically determine which of the supported types is
- // playable by the browser and load that type.
- //
- // Which types are available are determined by the file extensions
- // listed in the Quintus `options.audioSupported`
- Q.loadAssetAudio = function(key,src,callback,errorCallback) {
- if(!document.createElement("audio").play || !Q.options.sound) {
- callback(key,null);
- return;
- }
-
- var baseName = Q._removeExtension(src),
- extension = Q._audioAssetExtension(),
- filename = null,
- snd = new Audio();
-
- /* No supported audio = trigger ok callback anyway */
- if(!extension) {
- callback(key,null);
- return;
- }
-
- snd.addEventListener("error",errorCallback);
-
- // Don't wait for canplaythrough on mobile
- if(!Q.touchDevice) {
- snd.addEventListener('canplaythrough',function() {
- callback(key,snd);
- });
- }
- snd.src = Q.assetUrl(Q.options.audioPath,baseName + "." + extension);
- snd.load();
-
- if(Q.touchDevice) {
- callback(key,snd);
- }
- };
-
- Q.loadAssetWebAudio = function(key,src,callback,errorCallback) {
- var request = new XMLHttpRequest(),
- baseName = Q._removeExtension(src),
- extension = Q._audioAssetExtension();
-
- request.open("GET", Q.assetUrl(Q.options.audioPath,baseName + "." + extension), true);
- request.responseType = "arraybuffer";
-
- // Our asynchronous callback
- request.onload = function() {
- var audioData = request.response;
-
- Q.audioContext.decodeAudioData(request.response, function(buffer) {
- callback(key,buffer);
- }, errorCallback);
- };
- request.send();
-
- };
-
- // Loader for other file types, just store the data
- // returned from an Ajax call.
- Q.loadAssetOther = function(key,src,callback,errorCallback) {
- var request = new XMLHttpRequest();
-
- var fileParts = src.split("."),
- fileExt = fileParts[fileParts.length-1].toLowerCase();
-
- request.onreadystatechange = function() {
- if(request.readyState === 4) {
- if(request.status === 200) {
- if(fileExt === 'json') {
- callback(key,JSON.parse(request.responseText));
- } else {
- callback(key,request.responseText);
- }
- } else {
- errorCallback();
- }
- }
- };
-
- request.open("GET", Q.assetUrl(Q.options.dataPath,src), true);
- request.send(null);
- };
-
- // Helper method to return a name without an extension
- Q._removeExtension = function(filename) {
- return filename.replace(/\.(\w{3,4})$/,"");
- };
-
- // Asset hash storing any loaded assets
- Q.assets = {};
-
-
- // Getter method to return an asset by its name.
- //
- // Asset names default to their filenames, but can be overridden
- // by passing a hash to `load` to set different names.
- Q.asset = function(name) {
- return Q.assets[name];
- };
-
- // Load assets, and call our callback when done.
- //
- // Also optionally takes a `progressCallback` which will be called
- // with the number of assets loaded and the total number of assets
- // to allow showing of a progress.
- //
- // Assets can be passed in as an array of file names, and Quintus
- // will use the file names as the name for reference, or as a hash of
- // `{ name: filename }`.
- //
- // Example usage:
- // Q.load(['sprites.png','sprites.,json'],function() {
- // Q.stageScene("level1"); // or something to start the game.
- // });
- Q.load = function(assets,callback,options) {
- var assetObj = {};
-
- /* Make sure we have an options hash to work with */
- if(!options) { options = {}; }
-
- /* Get our progressCallback if we have one */
- var progressCallback = options.progressCallback;
-
- var errors = false,
- errorCallback = function(itm) {
- errors = true;
- (options.errorCallback ||
- function(itm) { throw("Error Loading: " + itm ); })(itm);
- };
-
- /* Convert to an array if it's a string */
- if(Q._isString(assets)) {
- assets = Q._normalizeArg(assets);
- }
-
- /* If the user passed in an array, convert it */
- /* to a hash with lookups by filename */
- if(Q._isArray(assets)) {
- Q._each(assets,function(itm) {
- if(Q._isObject(itm)) {
- Q._extend(assetObj,itm);
- } else {
- assetObj[itm] = itm;
- }
- });
- } else {
- /* Otherwise just use the assets as is */
- assetObj = assets;
- }
-
- /* Find the # of assets we're loading */
- var assetsTotal = Q._keys(assetObj).length,
- assetsRemaining = assetsTotal;
-
- /* Closure'd per-asset callback gets called */
- /* each time an asset is successfully loadded */
- var loadedCallback = function(key,obj,force) {
- if(errors) { return; }
-
- // Prevent double callbacks (I'm looking at you Firefox, canplaythrough
- if(!Q.assets[key]||force) {
-
- /* Add the object to our asset list */
- Q.assets[key] = obj;
-
- /* We've got one less asset to load */
- assetsRemaining--;
-
- /* Update our progress if we have it */
- if(progressCallback) {
- progressCallback(assetsTotal - assetsRemaining,assetsTotal);
- }
- }
-
- /* If we're out of assets, call our full callback */
- /* if there is one */
- if(assetsRemaining === 0 && callback) {
- /* if we haven't set up our canvas element yet, */
- /* assume we're using a canvas with id 'quintus' */
- callback.apply(Q);
- }
- };
-
- /* Now actually load each asset */
- Q._each(assetObj,function(itm,key) {
-
- /* Determine the type of the asset */
- var assetType = Q.assetType(itm);
-
- /* If we already have the asset loaded, */
- /* don't load it again */
- if(Q.assets[key]) {
- loadedCallback(key,Q.assets[key],true);
- } else {
- /* Call the appropriate loader function */
- /* passing in our per-asset callback */
- /* Dropping our asset by name into Q.assets */
- Q["loadAsset" + assetType](key,itm,
- loadedCallback,
- function() { errorCallback(itm); });
- }
- });
-
- };
-
- // Array to store any assets that need to be
- // preloaded
- Q.preloads = [];
-
- // Let us gather assets to load at a later time,
- // and then preload them all at the same time with
- // a single callback. Options are passed through to the
- // Q.load method if used.
- //
- // Example usage:
- // Q.preload("sprites.png");
- // ...
- // Q.preload("sprites.json");
- // ...
- //
- // Q.preload(function() {
- // Q.stageScene("level1"); // or something to start the game
- // });
- Q.preload = function(arg,options) {
- if(Q._isFunction(arg)) {
- Q.load(Q._uniq(Q.preloads),arg,options);
- Q.preloads = [];
- } else {
- Q.preloads = Q.preloads.concat(arg);
- }
- };
-
-
- // Math Methods
- // ==============
- //
- // Math methods, for rotating and scaling points
-
- // A list of matrices available
- Q.matrices2d = [];
-
- Q.matrix2d = function() {
- return Q.matrices2d.length > 0 ? Q.matrices2d.pop().identity() : new Q.Matrix2D();
- };
-
- // A 2D matrix class, optimized for 2D points,
- // where the last row of the matrix will always be 0,0,1
- // Good Docs where:
- // https://github.com/heygrady/transform/wiki/calculating-2d-matrices
- Q.Matrix2D = Q.Class.extend({
- init: function(source) {
-
- if(source) {
- this.m = [];
- this.clone(source);
- } else {
- this.m = [1,0,0,0,1,0];
- }
- },
-
- // Turn this matrix into the identity
- identity: function() {
- var m = this.m;
- m[0] = 1; m[1] = 0; m[2] = 0;
- m[3] = 0; m[4] = 1; m[5] = 0;
- return this;
- },
-
- // Clone another matrix into this one
- clone: function(matrix) {
- var d = this.m, s = matrix.m;
- d[0]=s[0]; d[1]=s[1]; d[2] = s[2];
- d[3]=s[3]; d[4]=s[4]; d[5] = s[5];
- return this;
- },
-
- // a * b =
- // [ [ a11*b11 + a12*b21 ], [ a11*b12 + a12*b22 ], [ a11*b31 + a12*b32 + a13 ] ,
- // [ a21*b11 + a22*b21 ], [ a21*b12 + a22*b22 ], [ a21*b31 + a22*b32 + a23 ] ]
- multiply: function(matrix) {
- var a = this.m, b = matrix.m;
-
- var m11 = a[0]*b[0] + a[1]*b[3];
- var m12 = a[0]*b[1] + a[1]*b[4];
- var m13 = a[0]*b[2] + a[1]*b[5] + a[2];
-
- var m21 = a[3]*b[0] + a[4]*b[3];
- var m22 = a[3]*b[1] + a[4]*b[4];
- var m23 = a[3]*b[2] + a[4]*b[5] + a[5];
-
- a[0]=m11; a[1]=m12; a[2] = m13;
- a[3]=m21; a[4]=m22; a[5] = m23;
- return this;
- },
-
- // Multiply this matrix by a rotation matrix rotated radians radians
- rotate: function(radians) {
- if(radians === 0) { return this; }
- var cos = Math.cos(radians),
- sin = Math.sin(radians),
- m = this.m;
-
- var m11 = m[0]*cos + m[1]*sin;
- var m12 = m[0]*-sin + m[1]*cos;
-
- var m21 = m[3]*cos + m[4]*sin;
- var m22 = m[3]*-sin + m[4]*cos;
-
- m[0] = m11; m[1] = m12; // m[2] == m[2]
- m[3] = m21; m[4] = m22; // m[5] == m[5]
- return this;
- },
-
- // Helper method to rotate by a set number of degrees
- rotateDeg: function(degrees) {
- if(degrees === 0) { return this; }
- return this.rotate(Math.PI * degrees / 180);
- },
-
- // Multiply this matrix by a scaling matrix scaling sx and sy
- scale: function(sx,sy) {
- var m = this.m;
- if(sy === void 0) { sy = sx; }
-
- m[0] *= sx;
- m[1] *= sy;
- m[3] *= sx;
- m[4] *= sy;
- return this;
- },
-
-
- // Multiply this matrix by a translation matrix translate by tx and ty
- translate: function(tx,ty) {
- var m = this.m;
-
- m[2] += m[0]*tx + m[1]*ty;
- m[5] += m[3]*tx + m[4]*ty;
- return this;
- },
-
- // Memory Hoggy version
- transform: function(x,y) {
- return [ x * this.m[0] + y * this.m[1] + this.m[2],
- x * this.m[3] + y * this.m[4] + this.m[5] ];
- },
-
- // Transform an object with an x and y property by this Matrix
- transformPt: function(obj) {
- var x = obj.x, y = obj.y;
-
- obj.x = x * this.m[0] + y * this.m[1] + this.m[2];
- obj.y = x * this.m[3] + y * this.m[4] + this.m[5];
-
- return obj;
- },
-
- // Transform an array with an x and y property by this Matrix
- transformArr: function(inArr,outArr) {
- var x = inArr[0], y = inArr[1];
-
- outArr[0] = x * this.m[0] + y * this.m[1] + this.m[2];
- outArr[1] = x * this.m[3] + y * this.m[4] + this.m[5];
-
- return outArr;
- },
-
-
- // Return just the x component by this Matrix
- transformX: function(x,y) {
- return x * this.m[0] + y * this.m[1] + this.m[2];
- },
-
- // Return just the y component by this Matrix
- transformY: function(x,y) {
- return x * this.m[3] + y * this.m[4] + this.m[5];
- },
-
- // Release this Matrix to be reused
- release: function() {
- Q.matrices2d.push(this);
- return null;
- },
-
- setContextTransform: function(ctx) {
- var m = this.m;
- // source:
- // m[0] m[1] m[2]
- // m[3] m[4] m[5]
- // 0 0 1
- //
- // destination:
- // m11 m21 dx
- // m12 m22 dy
- // 0 0 1
- // setTransform(m11, m12, m21, m22, dx, dy)
- ctx.transform(m[0],m[3],m[1],m[4],m[2],m[5]);
- //ctx.setTransform(m[0],m[1],m[2],m[3],m[4],m[5]);
- }
-
- });
-
- // And that's it..
- // ===============
- //
- // Return the `Q` object from the `Quintus()` factory method. Create awesome games. Repeat.
- return Q;
-};
-
-// Lastly, add in the `requestAnimationFrame` shim, if necessary. Does nothing
-// if `requestAnimationFrame` is already on the `window` object.
-(function() {
- var lastTime = 0;
- var vendors = ['ms', 'moz', 'webkit', 'o'];
- for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
- window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
- window.cancelAnimationFrame =
- window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
- }
-
- if (!window.requestAnimationFrame) {
- window.requestAnimationFrame = function(callback, element) {
- var currTime = new Date().getTime();
- var timeToCall = Math.max(0, 16 - (currTime - lastTime));
- var id = window.setTimeout(function() { callback(currTime + timeToCall); },
- timeToCall);
- lastTime = currTime + timeToCall;
- return id;
- };
- }
-
- if (!window.cancelAnimationFrame) {
- window.cancelAnimationFrame = function(id) {
- clearTimeout(id);
- };
- }
-}());
-
-
diff --git a/lib/quintus_2d.js b/lib/quintus_2d.js
deleted file mode 100644
index be6b64a..0000000
--- a/lib/quintus_2d.js
+++ /dev/null
@@ -1,457 +0,0 @@
-/*global Quintus:false */
-
-Quintus["2D"] = function(Q) {
-
- Q.component('viewport',{
- added: function() {
- this.entity.on('prerender',this,'prerender');
- this.entity.on('render',this,'postrender');
- this.x = 0;
- this.y = 0;
- this.offsetX = 0;
- this.offsetY = 0;
- this.centerX = Q.width/2;
- this.centerY = Q.height/2;
- this.scale = 1;
- },
-
- extend: {
- follow: function(sprite,directions,boundingBox) {
- this.off('poststep',this.viewport,'follow');
- this.viewport.directions = directions || { x: true, y: true };
- this.viewport.following = sprite;
- this.viewport.boundingBox = boundingBox;
- this.on('poststep',this.viewport,'follow');
- this.viewport.follow(true);
- },
-
- unfollow: function() {
- this.off('poststep',this.viewport,'follow');
- },
-
- centerOn: function(x,y) {
- this.viewport.centerOn(x,y);
- },
-
- moveTo: function(x,y) {
- return this.viewport.moveTo(x,y);
- }
- },
-
- follow: function(first) {
- var followX = Q._isFunction(this.directions.x) ? this.directions.x(this.following) : this.directions.x;
- var followY = Q._isFunction(this.directions.y) ? this.directions.y(this.following) : this.directions.y;
-
- this[first === true ? 'centerOn' : 'softCenterOn'](
- followX ?
- this.following.p.x + this.following.p.w/2 - this.offsetX :
- undefined,
- followY ?
- this.following.p.y + this.following.p.h/2 - this.offsetY :
- undefined
- );
- },
-
- offset: function(x,y) {
- this.offsetX = x;
- this.offsetY = y;
- },
-
- softCenterOn: function(x,y) {
- if(x !== void 0) {
- var dx = (x - Q.width / 2 / this.scale - this.x)/3;
- if(this.boundingBox) {
- if(this.x + dx < this.boundingBox.minX) {
- this.x = this.boundingBox.minX / this.scale;
- }
- else if(this.x + dx > (this.boundingBox.maxX - Q.width) / this.scale) {
- this.x = (this.boundingBox.maxX - Q.width) / this.scale;
- }
- else {
- this.x += dx;
- }
- }
- else {
- this.x += dx;
- }
- }
- if(y !== void 0) {
- var dy = (y - Q.height / 2 / this.scale - this.y)/3;
- if(this.boundingBox) {
- if(this.y + dy < this.boundingBox.minY) {
- this.y = this.boundingBox.minY / this.scale;
- }
- else if(this.y + dy > (this.boundingBox.maxY - Q.height) / this.scale) {
- this.y = (this.boundingBox.maxY - Q.height) / this.scale;
- }
- else {
- this.y += dy;
- }
- }
- else {
- this.y += dy;
- }
- }
-
- },
- centerOn: function(x,y) {
- if(x !== void 0) {
- this.x = x - Q.width / 2 / this.scale;
- }
- if(y !== void 0) {
- this.y = y - Q.height / 2 / this.scale;
- }
-
- },
-
- moveTo: function(x,y) {
- if(x !== void 0) {
- this.x = x;
- }
- if(y !== void 0) {
- this.y = y;
- }
- return this.entity;
-
- },
-
- prerender: function() {
- this.centerX = this.x + Q.width / 2 /this.scale;
- this.centerY = this.y + Q.height / 2 /this.scale;
- Q.ctx.save();
- Q.ctx.translate(Math.floor(Q.width/2),Math.floor(Q.height/2));
- Q.ctx.scale(this.scale,this.scale);
- Q.ctx.translate(-Math.floor(this.centerX), -Math.floor(this.centerY));
- },
-
- postrender: function() {
- Q.ctx.restore();
- }
- });
-
-
- Q.TileLayer = Q.Sprite.extend({
-
- init: function(props) {
- this._super(props,{
- tileW: 32,
- tileH: 32,
- blockTileW: 10,
- blockTileH: 10,
- type: 1,
- layerIndex: 0
- });
- if(this.p.dataAsset) {
- this.load(this.p.dataAsset);
- }
- this.blocks = [];
- this.p.blockW = this.p.tileW * this.p.blockTileW;
- this.p.blockH = this.p.tileH * this.p.blockTileH;
- this.colBounds = {};
- this.directions = [ 'top','left','right','bottom'];
-
- this.collisionObject = {
- p: {
- w: this.p.tileW,
- h: this.p.tileH,
- cx: this.p.tileW/2,
- cy: this.p.tileH/2
- }
- };
-
- this.collisionNormal = { separate: []};
- },
-
- load: function(dataAsset) {
- var fileParts = dataAsset.split("."),
- fileExt = fileParts[fileParts.length-1].toLowerCase(),
- data;
-
- if (fileExt === "json") {
- data = Q._isString(dataAsset) ? Q.asset(dataAsset) : dataAsset;
- }
- else if (fileExt === "tmx" || fileExt === "xml") {
- var parser = new DOMParser(),
- doc = parser.parseFromString(Q.asset(dataAsset), "application/xml");
-
- var layer = doc.getElementsByTagName("layer")[this.p.layerIndex],
- width = parseInt(layer.getAttribute("width"),10),
- height = parseInt(layer.getAttribute("height"),10);
-
- var tiles = layer.getElementsByTagName("tile"),
- idx = 0;
-
- data = [];
-
- for(var y = 0;y < height;y++) {
- data[y] = [];
- for(var x = 0;x < width;x++) {
- var tile = tiles[idx];
- data[y].push(parseInt(tile.getAttribute("gid")-1,10));
- idx++;
- }
- }
- }
- else {
- throw "file type not supported";
- }
- this.p.tiles = data;
- this.p.rows = data.length;
- this.p.cols = data[0].length;
- this.p.w = this.p.cols * this.p.tileW;
- this.p.h = this.p.rows * this.p.tileH;
- },
-
- getTile: function(tileX,tileY) {
- return this.p.tiles[tileY] && this.p.tiles[tileY][tileX];
- },
-
- setTile: function(x,y,tile) {
- var p = this.p,
- blockX = Math.floor(x/p.blockTileW),
- blockY = Math.floor(y/p.blockTileH);
-
- if(blockX >= 0 && blockY >= 0 &&
- blockX < this.p.cols &&
- blockY < this.p.rows) {
- this.p.tiles[y][x] = tile;
- if(this.blocks[blockY]) {
- this.blocks[blockY][blockX] = null;
- }
- }
- },
-
- tilePresent: function(tileX,tileY) {
- return this.p.tiles[tileY] && this.collidableTile(this.p.tiles[tileY][tileX]);
- },
-
- // Overload this method to draw tiles at frame 0 or not draw
- // tiles at higher number frames
- drawableTile: function(tileNum) {
- return tileNum > 0;
- },
-
- // Overload this method to control which tiles trigger a collision
- // (defaults to all tiles > number 0)
- collidableTile: function(tileNum) {
- return tileNum > 0;
- },
-
- collide: function(obj) {
- var p = this.p,
- tileStartX = Math.floor((obj.p.x - obj.p.cx - p.x) / p.tileW),
- tileStartY = Math.floor((obj.p.y - obj.p.cy - p.y) / p.tileH),
- tileEndX = Math.ceil((obj.p.x - obj.p.cx + obj.p.w - p.x) / p.tileW),
- tileEndY = Math.ceil((obj.p.y - obj.p.cy + obj.p.h - p.y) / p.tileH),
- colObj = this.collisionObject,
- normal = this.collisionNormal,
- col;
-
- normal.collided = false;
-
- for(var tileY = tileStartY; tileY<=tileEndY; tileY++) {
- for(var tileX = tileStartX; tileX<=tileEndX; tileX++) {
- if(this.tilePresent(tileX,tileY)) {
- colObj.p.x = tileX * p.tileW + p.x + p.tileW/2;
- colObj.p.y = tileY * p.tileH + p.y + p.tileH/2;
-
- col = Q.collision(obj,colObj);
- if(col && col.magnitude > 0 &&
- (!normal.collided || normal.magnitude < col.magnitude )) {
- normal.collided = true;
- normal.separate[0] = col.separate[0];
- normal.separate[1] = col.separate[1];
- normal.magnitude = col.magnitude;
- normal.distance = col.distance;
- normal.normalX = col.normalX;
- normal.normalY = col.normalY;
- normal.tileX = tileX;
- normal.tileY = tileY;
- normal.tile = this.getTile(tileX,tileY);
- }
- }
- }
- }
-
- return normal.collided ? normal : false;
- },
-
- prerenderBlock: function(blockX,blockY) {
- var p = this.p,
- tiles = p.tiles,
- sheet = this.sheet(),
- blockOffsetX = blockX*p.blockTileW,
- blockOffsetY = blockY*p.blockTileH;
-
- if(blockOffsetX < 0 || blockOffsetX >= this.p.cols ||
- blockOffsetY < 0 || blockOffsetY >= this.p.rows) {
- return;
- }
-
- var canvas = document.createElement('canvas'),
- ctx = canvas.getContext('2d');
-
- canvas.width = p.blockW;
- canvas.height= p.blockH;
- this.blocks[blockY] = this.blocks[blockY] || {};
- this.blocks[blockY][blockX] = canvas;
-
- for(var y=0;y 0) { p.vy = 0; }
- col.impact = impactY;
- entity.trigger("bump.bottom",col);
- }
- if(col.normalY > 0.3) {
- if(p.vy < 0) { p.vy = 0; }
- col.impact = impactY;
-
- entity.trigger("bump.top",col);
- }
-
- if(col.normalX < -0.3) {
- if(p.vx > 0) { p.vx = 0; }
- col.impact = impactX;
- entity.trigger("bump.right",col);
- }
- if(col.normalX > 0.3) {
- if(p.vx < 0) { p.vx = 0; }
- col.impact = impactX;
-
- entity.trigger("bump.left",col);
- }
- },
-
- step: function(dt) {
- var p = this.entity.p,
- dtStep = dt;
- // TODO: check the entity's magnitude of vx and vy,
- // reduce the max dtStep if necessary to prevent
- // skipping through objects.
- while(dtStep > 0) {
- dt = Math.min(1/30,dtStep);
- // Updated based on the velocity and acceleration
- p.vx += p.ax * dt + (p.gravityX === void 0 ? Q.gravityX : p.gravityX) * dt * p.gravity;
- p.vy += p.ay * dt + (p.gravityY === void 0 ? Q.gravityY : p.gravityY) * dt * p.gravity;
- p.x += p.vx * dt;
- p.y += p.vy * dt;
-
- this.entity.stage.collide(this.entity);
- dtStep -= dt;
- }
- }
- });
-
- Q.component('aiBounce', {
- added: function() {
- this.entity.on("bump.right",this,"goLeft");
- this.entity.on("bump.left",this,"goRight");
- },
-
- goLeft: function(col) {
- this.entity.p.vx = -col.impact;
- if(this.entity.p.defaultDirection === 'right') {
- this.entity.p.flip = 'x';
- }
- else {
- this.entity.p.flip = false;
- }
- },
-
- goRight: function(col) {
- this.entity.p.vx = col.impact;
- if(this.entity.p.defaultDirection === 'left') {
- this.entity.p.flip = 'x';
- }
- else {
- this.entity.p.flip = false;
- }
- }
- });
-
-};
-
diff --git a/lib/quintus_anim.js b/lib/quintus_anim.js
deleted file mode 100644
index f6d44ab..0000000
--- a/lib/quintus_anim.js
+++ /dev/null
@@ -1,267 +0,0 @@
-/*global Quintus:false */
-
-Quintus.Anim = function(Q) {
-
- Q._animations = {};
- Q.animations = function(sprite,animations) {
- if(!Q._animations[sprite]) { Q._animations[sprite] = {}; }
- Q._extend(Q._animations[sprite],animations);
- };
-
- Q.animation = function(sprite,name) {
- return Q._animations[sprite] && Q._animations[sprite][name];
- };
-
- Q.component('animation',{
- added: function() {
- var p = this.entity.p;
- p.animation = null;
- p.animationPriority = -1;
- p.animationFrame = 0;
- p.animationTime = 0;
- this.entity.on("step",this,"step");
- },
- extend: {
- play: function(name,priority) {
- this.animation.play(name,priority);
- }
- },
- step: function(dt) {
- var entity = this.entity,
- p = entity.p;
- if(p.animation) {
- var anim = Q.animation(p.sprite,p.animation),
- rate = anim.rate || p.rate,
- stepped = 0;
- p.animationTime += dt;
- if(p.animationChanged) {
- p.animationChanged = false;
- } else {
- p.animationTime += dt;
- if(p.animationTime > rate) {
- stepped = Math.floor(p.animationTime / rate);
- p.animationTime -= stepped * rate;
- p.animationFrame += stepped;
- }
- }
- if(stepped > 0) {
- if(p.animationFrame >= anim.frames.length) {
- if(anim.loop === false || anim.next) {
- p.animationFrame = anim.frames.length - 1;
- entity.trigger('animEnd');
- entity.trigger('animEnd.' + p.animation);
- p.animation = null;
- p.animationPriority = -1;
- if(anim.trigger) {
- entity.trigger(anim.trigger,anim.triggerData);
- }
- if(anim.next) { this.play(anim.next,anim.nextPriority); }
- return;
- } else {
- entity.trigger('animLoop');
- entity.trigger('animLoop.' + p.animation);
- p.animationFrame = p.animationFrame % anim.frames.length;
- }
- }
- entity.trigger("animFrame");
- }
- p.sheet = anim.sheet || p.sheet;
- p.frame = anim.frames[p.animationFrame];
- }
- },
-
- play: function(name,priority) {
- var entity = this.entity,
- p = entity.p;
- priority = priority || 0;
- if(name !== p.animation && priority >= p.animationPriority) {
- p.animation = name;
- p.animationChanged = true;
- p.animationTime = 0;
- p.animationFrame = 0;
- p.animationPriority = priority;
- entity.trigger('anim');
- entity.trigger('anim.' + p.animation);
- }
- }
-
- });
-
-
- Q.Sprite.extend("Repeater",{
- init: function(props) {
- this._super(Q._defaults(props,{
- speedX: 1,
- speedY: 1,
- repeatY: true,
- repeatX: true,
- type: 0
- }));
- this.p.repeatW = this.p.repeatW || this.p.w;
- this.p.repeatH = this.p.repeatH || this.p.h;
- },
-
- draw: function(ctx) {
- var p = this.p,
- asset = this.asset(),
- sheet = this.sheet(),
- scale = this.stage.viewport ? this.stage.viewport.scale : 1,
- viewX = Math.floor(this.stage.viewport ? this.stage.viewport.x : 0),
- viewY = Math.floor(this.stage.viewport ? this.stage.viewport.y : 0),
- offsetX = Math.floor(p.x + viewX * this.p.speedX),
- offsetY = Math.floor(p.y + viewY * this.p.speedY),
- curX, curY, startX;
- if(p.repeatX) {
- curX = -offsetX % p.repeatW;
- if(curX > 0) { curX -= p.repeatW; }
- } else {
- curX = p.x - viewX;
- }
- if(p.repeatY) {
- curY = -offsetY % p.repeatH;
- if(curY > 0) { curY -= p.repeatH; }
- } else {
- curY = p.y - viewY;
- }
-
- startX = curX;
- while(curY < Q.height / scale) {
- curX = startX;
- while(curX < Q.width / scale) {
- if(sheet) {
- sheet.draw(ctx,curX + viewX,curY + viewY,p.frame);
- } else {
- ctx.drawImage(asset,curX + viewX,curY + viewY);
- }
- curX += p.repeatW;
- if(!p.repeatX) { break; }
- }
- curY += p.repeatH;
- if(!p.repeatY) { break; }
- }
- }
- });
-
- Q.Tween = Q.Class.extend({
- init: function(entity,properties,duration,easing,options) {
- if(Q._isObject(easing)) { options = easing; easing = Q.Easing.Linear; }
- if(Q._isObject(duration)) { options = duration; duration = 1; }
-
- this.entity = entity;
- //this.p = (entity instanceof Q.Stage) ? entity.viewport : entity.p;
- this.duration = duration || 1;
- this.time = 0;
- this.options = options || {};
- this.delay = this.options.delay || 0;
- this.easing = easing || this.options.easing || Q.Easing.Linear;
-
- this.startFrame = Q._loopFrame + 1;
- this.properties = properties;
- this.start = {};
- this.diff = {};
- },
-
- step: function(dt) {
- var property;
-
- if(this.startFrame > Q._loopFrame) { return true; }
- if(this.delay >= dt) {
- this.delay -= dt;
- return true;
- }
-
- if(this.delay > 0) {
- dt -= this.delay;
- this.delay = 0;
- }
-
- if(this.time === 0) {
- // first time running? Initialize the properties to chaining correctly.
- var entity = this.entity, properties = this.properties;
- this.p = (entity instanceof Q.Stage) ? entity.viewport : entity.p;
- for(property in properties) {
- this.start[property] = this.p[property];
- if(!Q._isUndefined(this.start[property])) {
- this.diff[property] = properties[property] - this.start[property];
- }
- }
- }
- this.time += dt;
-
- var progress = Math.min(1,this.time / this.duration),
- location = this.easing(progress);
-
- for(property in this.start) {
- if(!Q._isUndefined(this.p[property])) {
- this.p[property] = this.start[property] + this.diff[property] * location;
- }
- }
-
- if(progress >= 1) {
- if(this.options.callback) {
- this.options.callback.apply(this.entity);
- }
- }
- return progress < 1;
- }
- });
-
- // Code ripped directly from Tween.js
- // https://github.com/sole/tween.js/blob/master/src/Tween.js
- Q.Easing = {
- Linear: function (k) { return k; },
-
- Quadratic: {
- In: function ( k ) { return k * k; },
- Out: function ( k ) {return k * ( 2 - k ); },
- InOut: function ( k ) {
- if ((k *= 2 ) < 1) { return 0.5 * k * k; }
- return -0.5 * (--k * (k - 2) - 1);
- }
- }
- };
-
- Q.component('tween',{
- added: function() {
- this._tweens = [];
- this.entity.on("step",this,"step");
- },
- extend: {
- animate: function(properties,duration,easing,options) {
- this.tween._tweens.push(new Q.Tween(this,properties,duration,easing,options));
- return this;
- },
-
- chain: function(properties,duration,easing,options) {
- if(Q._isObject(easing)) { options = easing; easing = Q.Easing.Linear; }
- // Chain an animation to the end
- var tweenCnt = this.tween._tweens.length;
- if(tweenCnt > 0) {
- var lastTween = this.tween._tweens[tweenCnt - 1];
- options = options || {};
- options['delay'] = lastTween.duration - lastTween.time + lastTween.delay;
- }
-
- this.animate(properties,duration,easing,options);
- return this;
- },
-
- stop: function() {
- this.tween._tweens.length = 0;
- return this;
- }
- },
-
- step: function(dt) {
- for(var i=0; i < this._tweens.length; i++) {
- if(!this._tweens[i].step(dt)) {
- this._tweens.splice(i,1);
- i--;
- }
- }
- }
- });
-
-
-};
-
diff --git a/lib/quintus_audio.js b/lib/quintus_audio.js
deleted file mode 100644
index 66e1e58..0000000
--- a/lib/quintus_audio.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/*global Quintus:false, AudioContext:false, window:false */
-
-Quintus.Audio = function(Q) {
-
- Q.audio = {
- channels: [],
- channelMax: Q.options.channelMax || 10,
- active: {},
- play: function() {}
- };
-
-
- Q.hasWebAudio = (typeof AudioContext !== "undefined") || (typeof webkitAudioContext !== "undefined");
-
- if(Q.hasWebAudio) {
- if(typeof AudioContext !== "undefined") {
- Q.audioContext = new AudioContext();
- } else {
- Q.audioContext = new window.webkitAudioContext();
- }
- }
-
- Q.enableSound = function() {
- var hasTouch = !!('ontouchstart' in window);
-
- if(Q.hasWebAudio) {
- Q.audio.enableWebAudioSound();
- } else {
- Q.audio.enableHTML5Sound();
- }
- return Q;
- };
-
- Q.audio.enableWebAudioSound = function() {
- Q.audio.type = "WebAudio";
-
- Q.audio.soundID = 0;
-
- Q.audio.playingSounds = {};
-
- Q.audio.removeSound = function(soundID) {
- delete Q.audio.playingSounds[soundID];
- };
-
- // Play a single sound, optionally debounced
- // to prevent repeated plays in a short time
- Q.audio.play = function(s,options) {
- var now = new Date().getTime();
-
- // See if this audio file is currently being debounced, if
- // it is, don't do anything and just return
- if(Q.audio.active[s] && Q.audio.active[s] > now) { return; }
-
- // If any options were passed in, check for a debounce,
- // which is the number of milliseconds to debounce this sound
- if(options && options['debounce']) {
- Q.audio.active[s] = now + options['debounce'];
- } else {
- delete Q.audio.active[s];
- }
-
- var soundID = Q.audio.soundID++;
-
- var source = Q.audioContext.createBufferSource();
- source.buffer = Q.asset(s);
- source.connect(Q.audioContext.destination);
- if(options && options['loop']) {
- source.loop = true;
- } else {
- setTimeout(function() {
- Q.audio.removeSound(soundID);
- },source.buffer.duration * 1000);
- }
- source.assetName = s;
- if(source.start) { source.start(0); } else { source.noteOn(0); }
-
- Q.audio.playingSounds[soundID] = source;
-
-
- };
-
- Q.audio.stop = function(s) {
- for(var key in Q.audio.playingSounds) {
- var snd = Q.audio.playingSounds[key];
- if(!s || s === snd.assetName) {
- if(snd.stop) { snd.stop(0); } else { snd.noteOff(0); }
- }
- }
- };
-
- };
-
- Q.audio.enableHTML5Sound = function() {
- Q.audio.type = "HTML5";
-
- for (var i=0;i now) { return; }
-
- // If any options were passed in, check for a debounce,
- // which is the number of milliseconds to debounce this sound
- if(options && options['debounce']) {
- Q.audio.active[s] = now + options['debounce'];
- } else {
- delete Q.audio.active[s];
- }
-
- // Find a free audio channel and play the sound
- for (var i=0;i= tm)) {
- Q.audio.channels[i]['channel'].pause();
- Q.audio.channels[i]['loop'] = false;
- }
- }
- };
-
- };
-
-};
-
diff --git a/lib/quintus_input.js b/lib/quintus_input.js
deleted file mode 100644
index c8edf37..0000000
--- a/lib/quintus_input.js
+++ /dev/null
@@ -1,664 +0,0 @@
-/*global Quintus:false */
-/**
-Quintus HTML5 Game Engine - Input Module
-
-The code in `quintus_input.js` defines the `Quintus.Input` module, which
-concerns itself with game-type (pretty anything besides touchscreen input)
-
-@module Quintus.Input
-*/
-
-/**
- * Quintus Input class
- *
- * @class Quintus.Input
- */
-Quintus.Input = function(Q) {
- var KEY_NAMES = { LEFT: 37, RIGHT: 39, SPACE: 32,
- UP: 38, DOWN: 40,
- Z: 90, X: 88
- };
-
- var DEFAULT_KEYS = { LEFT: 'left', RIGHT: 'right',
- UP: 'up', DOWN: 'down',
- SPACE: 'fire',
- Z: 'fire',
- X: 'action' };
-
- var DEFAULT_TOUCH_CONTROLS = [ ['left','<' ],
- ['right','>' ],
- [],
- ['action','b'],
- ['fire', 'a' ]];
-
- // Clockwise from midnight (a la CSS)
- var DEFAULT_JOYPAD_INPUTS = [ 'up','right','down','left'];
-
- Q.inputs = {};
- Q.joypad = {};
-
- var hasTouch = !!('ontouchstart' in window);
-
-
- /**
- *
- * Convert a canvas point to a stage point, x dimension
- *
- * @method Q.canvasToStageX
- */
- Q.canvasToStageX = function(x,stage) {
- x = x / Q.cssWidth * Q.width;
- if(stage.viewport) {
- x /= stage.viewport.scale;
- x += stage.viewport.x;
- }
-
- return x;
- };
-
- /**
- *
- * Convert a canvas point to a stage point, y dimension
- *
- * @method Q.canvasToStageY
- */
- Q.canvasToStageY = function(y,stage) {
- y = y / Q.cssWidth * Q.width;
- if(stage.viewport) {
- y /= stage.viewport.scale;
- y += stage.viewport.y;
- }
-
- return y;
- };
-
-
-
- /**
- *
- * Button and mouse input subsystem for Quintus.
- * An instance of this class is auto-created as {{#crossLink "Q.input"}}{{/crossLink}}
- *
- * @class InputSystem
- * @extends Evented
- * @for Quintus.Input
- */
- Q.InputSystem = Q.Evented.extend({
- keys: {},
- keypad: {},
- keyboardEnabled: false,
- touchEnabled: false,
- joypadEnabled: false,
-
- bindKey: function(key,name) {
- Q.input.keys[KEY_NAMES[key] || key] = name;
- },
-
- keyboardControls: function(keys) {
- keys = keys || DEFAULT_KEYS;
- Q._each(keys,function(name,key) {
- this.bindKey(key,name);
- },Q.input);
- this.enableKeyboard();
- },
-
- enableKeyboard: function() {
- if(this.keyboardEnabled) { return false; }
-
- // Make selectable and remove an :focus outline
- Q.el.tabIndex = 0;
- Q.el.style.outline = 0;
-
- Q.el.addEventListener("keydown",function(e) {
- if(Q.input.keys[e.keyCode]) {
- var actionName = Q.input.keys[e.keyCode];
- Q.inputs[actionName] = true;
- Q.input.trigger(actionName);
- Q.input.trigger('keydown',e.keyCode);
- }
- e.preventDefault();
- },false);
-
- Q.el.addEventListener("keyup",function(e) {
- if(Q.input.keys[e.keyCode]) {
- var actionName = Q.input.keys[e.keyCode];
- Q.inputs[actionName] = false;
- Q.input.trigger(actionName + "Up");
- Q.input.trigger('keyup',e.keyCode);
- }
- e.preventDefault();
- },false);
-
- Q.el.focus();
- this.keyboardEnabled = true;
- },
-
- _containerOffset: function() {
- Q.input.offsetX = 0;
- Q.input.offsetY = 0;
- var el = Q.el;
- do {
- Q.input.offsetX += el.offsetLeft;
- Q.input.offsetY += el.offsetTop;
- } while(el = el.offsetParent);
- },
-
- touchLocation: function(touch) {
- var el = Q.el,
- posX = touch.offsetX,
- posY = touch.offsetY,
- touchX, touchY;
-
- if(Q._isUndefined(posX) || Q._isUndefined(posY)) {
- posX = touch.layerX;
- posY = touch.layerY;
- }
-
- if(Q._isUndefined(posX) || Q._isUndefined(posY)) {
- if(Q.input.offsetX === void 0) { Q.input._containerOffset(); }
- posX = touch.pageX - Q.input.offsetX;
- posY = touch.pageY - Q.input.offsetY;
- }
-
- touchX = Q.width * posX / Q.cssWidth;
- touchY = Q.height * posY / Q.cssHeight;
-
-
- return { x: touchX, y: touchY };
- },
-
- touchControls: function(opts) {
- if(this.touchEnabled) { return false; }
- if(!hasTouch) { return false; }
-
- Q.input.keypad = opts = Q._extend({
- left: 0,
- gutter:10,
- controls: DEFAULT_TOUCH_CONTROLS,
- width: Q.width,
- bottom: Q.height
- },opts);
-
- opts.unit = (opts.width / opts.controls.length);
- opts.size = opts.unit - 2 * opts.gutter;
-
- function getKey(touch) {
- var pos = Q.input.touchLocation(touch);
- for(var i=0,len=opts.controls.length;i 1) {
- dx /= overage;
- dy /= overage;
- dist /= overage;
- }
-
- var triggers = [
- dy < -joypad.trigger,
- dx > joypad.trigger,
- dy > joypad.trigger,
- dx < -joypad.trigger
- ];
-
- for(var k=0;k 0 && (Q.inputs['up'] || Q.inputs['action'])) {
- p.vy = p.jumpSpeed;
- p.landed = -dt;
- }
- p.landed -= dt;
-
- }
- });
-
-
- Q.component("stepControls", {
-
- added: function() {
- var p = this.entity.p;
-
- if(!p.stepDistance) { p.stepDistance = 32; }
- if(!p.stepDelay) { p.stepDelay = 0.2; }
-
- p.stepWait = 0;
- this.entity.on("step",this,"step");
- this.entity.on("hit", this,"collision");
- },
-
- collision: function(col) {
- var p = this.entity.p;
-
- if(p.stepping) {
- p.stepping = false;
- p.x = p.origX;
- p.y = p.origY;
- }
-
- },
-
- step: function(dt) {
- var p = this.entity.p,
- moved = false;
- p.stepWait -= dt;
-
- if(p.stepping) {
- p.x += p.diffX * dt / p.stepDelay;
- p.y += p.diffY * dt / p.stepDelay;
- }
-
- if(p.stepWait > 0) { return; }
- if(p.stepping) {
- p.x = p.destX;
- p.y = p.destY;
- }
- p.stepping = false;
-
- p.diffX = 0;
- p.diffY = 0;
-
- if(Q.inputs['left']) {
- p.diffX = -p.stepDistance;
- } else if(Q.inputs['right']) {
- p.diffX = p.stepDistance;
- }
-
- if(Q.inputs['up']) {
- p.diffY = -p.stepDistance;
- } else if(Q.inputs['down']) {
- p.diffY = p.stepDistance;
- }
-
- if(p.diffY || p.diffX ) {
- p.stepping = true;
- p.origX = p.x;
- p.origY = p.y;
- p.destX = p.x + p.diffX;
- p.destY = p.y + p.diffY;
- p.stepWait = p.stepDelay;
- }
-
- }
-
- });
-};
-
diff --git a/lib/quintus_scenes.js b/lib/quintus_scenes.js
deleted file mode 100644
index 8ae2f3e..0000000
--- a/lib/quintus_scenes.js
+++ /dev/null
@@ -1,909 +0,0 @@
-/*global Quintus:false */
-
-Quintus.Scenes = function(Q) {
-
- Q.scenes = {};
- Q.stages = [];
-
- Q.Scene = Q.Class.extend({
- init: function(sceneFunc,opts) {
- this.opts = opts || {};
- this.sceneFunc = sceneFunc;
- }
- });
-
- // Set up or return a new scene
- Q.scene = function(name,sceneObj,opts) {
- if(sceneObj === void 0) {
- return Q.scenes[name];
- } else {
- if(Q._isFunction(sceneObj)) {
- sceneObj = new Q.Scene(sceneObj,opts);
- }
- Q.scenes[name] = sceneObj;
- return sceneObj;
- }
- };
-
- Q._nullContainer = {
- c: {
- x: 0,
- y: 0,
- /* cx: 0,
- cy: 0, */
- angle: 0,
- scale: 1
- },
- matrix: Q.matrix2d()
- };
-
-
- // Default to SAT collision between two objects
- // Thanks to doc's at: http://www.sevenson.com.au/actionscript/sat/
- Q.collision = (function() {
- var normalX, normalY,
- offset = [ 0,0 ],
- result1 = { separate: [] },
- result2 = { separate: [] };
-
- function calculateNormal(points,idx) {
- var pt1 = points[idx],
- pt2 = points[idx+1] || points[0];
-
- normalX = -(pt2[1] - pt1[1]);
- normalY = pt2[0] - pt1[0];
-
- var dist = Math.sqrt(normalX*normalX + normalY*normalY);
- if(dist > 0) {
- normalX /= dist;
- normalY /= dist;
- }
- }
-
- function dotProductAgainstNormal(point) {
- return (normalX * point[0]) + (normalY * point[1]);
-
- }
-
- function collide(o1,o2,flip) {
- var min1,max1,
- min2,max2,
- d1, d2,
- offsetLength,
- tmp, i, j,
- minDist, minDistAbs,
- shortestDist = Number.POSITIVE_INFINITY,
- collided = false,
- p1, p2;
-
- var result = flip ? result2 : result1;
-
- offset[0] = 0; //o1.x + o1.cx - o2.x - o2.cx;
- offset[1] = 0; //o1.y + o1.cy - o2.y - o2.cy;
-
- // If we have a position matrix, just use those points,
- if(o1.c) {
- p1 = o1.c.points;
- } else {
- p1 = o1.p.points;
- offset[0] += o1.p.x;
- offset[1] += o1.p.y;
- }
-
- if(o2.c) {
- p2 = o2.c.points;
- } else {
- p2 = o2.p.points;
- offset[0] += -o2.p.x;
- offset[1] += -o2.p.y;
- }
-
- o1 = o1.p;
- o2 = o2.p;
-
-
- for(i = 0;i max1) { max1 = tmp; }
- }
-
- min2 = dotProductAgainstNormal(p2[0]);
- max2 = min2;
-
- for(j = 1;j max2) { max2 = tmp; }
- }
-
- offsetLength = dotProductAgainstNormal(offset);
- min1 += offsetLength;
- max1 += offsetLength;
-
- d1 = min1 - max2;
- d2 = min2 - max1;
-
- if(d1 > 0 || d2 > 0) { return null; }
-
- minDist = (max2 - min1) * -1;
- if(flip) { minDist *= -1; }
-
- minDistAbs = Math.abs(minDist);
-
- if(minDistAbs < shortestDist) {
- result.distance = minDist;
- result.magnitude = minDistAbs;
- result.normalX = normalX;
- result.normalY = normalY;
-
- if(result.distance > 0) {
- result.distance *= -1;
- result.normalX *= -1;
- result.normalY *= -1;
- }
-
- collided = true;
- shortestDist = minDistAbs;
- }
- }
-
- // Do return the actual collision
- return collided ? result : null;
- }
-
- function satCollision(o1,o2) {
- var result1, result2, result;
-
- // Don't compare a square to a square for no reason
- // if(!o1.p.points && !o2.p.points) return true;
-
- if(!o1.p.points) { Q._generatePoints(o1); }
- if(!o2.p.points) { Q._generatePoints(o2); }
-
- Q._generateCollisionPoints(o1);
- Q._generateCollisionPoints(o2);
-
- result1 = collide(o1,o2);
- if(!result1) { return false; }
-
- result2 = collide(o2,o1,true);
- if(!result2) { return false; }
-
- result = (result2.magnitude < result1.magnitude) ? result2 : result1;
-
- if(result.magnitude === 0) { return false; }
- result.separate[0] = result.distance * result.normalX;
- result.separate[1] = result.distance * result.normalY;
-
- return result;
- }
-
- return satCollision;
- }());
-
-
- Q.overlap = function(o1,o2) {
- var c1 = o1.c || o1.p;
- var c2 = o2.c || o2.p;
-
- var o1x = c1.x - c1.cx,
- o1y = c1.y - c1.cy;
- var o2x = c2.x - c2.cx,
- o2y = c2.y - c2.cy;
-
- return !((o1y+c1.ho2y+c2.h) ||
- (o1x+c1.wo2x+c2.w));
- };
-
- Q.Stage = Q.GameObject.extend({
- // Should know whether or not the stage is paused
- defaults: {
- sort: false,
- gridW: 400,
- gridH: 400
- },
-
- init: function(scene,opts) {
- this.scene = scene;
- this.items = [];
- this.lists = {};
- this.index = {};
- this.removeList = [];
- this.grid = {};
-
- this.time = 0;
-
- this.options = Q._extend({},this.defaults);
- if(this.scene) {
- Q._extend(this.options,scene.opts);
- }
- if(opts) { Q._extend(this.options,opts); }
-
-
- if(this.options.sort && !Q._isFunction(this.options.sort)) {
- this.options.sort = function(a,b) { return ((a.p && a.p.z) || -1) - ((b.p && b.p.z) || -1); };
- }
- },
-
- destroyed: function() {
- this.invoke("debind");
- this.trigger("destroyed");
- },
-
- // Needs to be separated out so the current stage can be set
- loadScene: function() {
- if(this.scene) {
- this.scene.sceneFunc(this);
- }
- },
-
- // Load an array of assets of the form:
- // [ [ "Player", { x: 15, y: 54 } ],
- // [ "Enemy", { x: 54, y: 42 } ] ]
- // Either pass in the array or a string of asset name
- loadAssets: function(asset) {
- var assetArray = Q._isArray(asset) ? asset : Q.asset(asset);
- for(var i=0;i= 0; i--) {
- if(func.call(this.items[i],arguments[1],arguments[2],arguments[3])) {
- return this.items[i];
- }
- }
- return false;
- },
-
-
- identify: function(func) {
- var result;
- for(var i = this.items.length-1;i >= 0; i--) {
- if(result = func.call(this.items[i],arguments[1],arguments[2],arguments[3])) {
- return result;
- }
- }
- return false;
- },
-
- addToLists: function(lists,object) {
- for(var i=0;i 0 && (col = this._collisionLayer.collide(obj))) {
- col.obj = this._collisionLayer;
- if(!skipEvents) {
- obj.trigger('hit',col);
- obj.trigger('hit.collision',col);
- }
- this.regrid(obj);
- curCol--;
- }
- }
-
- curCol = maxCol;
- while(curCol > 0 && (col2 = this.gridTest(obj,collisionMask,this._collisionLayer))) {
- obj.trigger('hit',col2);
- obj.trigger('hit.sprite',col2);
-
- // Do the recipricol collision
- // TODO: extract
- if(!skipEvents) {
- var obj2 = col2.obj;
- col2.obj = obj;
- col2.normalX *= -1;
- col2.normalY *= -1;
- col2.distance = 0;
- col2.magnitude = 0;
- col2.separate[0] = 0;
- col2.separate[1] = 0;
-
-
- obj2.trigger('hit',col2);
- obj2.trigger('hit.sprite',col2);
- }
-
- this.regrid(obj);
- curCol--;
- }
-
- return col2 || col;
- },
-
- delGrid: function(item) {
- var grid = item.grid;
-
- for(var y = grid.Y1;y <= grid.Y2;y++) {
- if(this.grid[y]) {
- for(var x = grid.X1;x <= grid.X2;x++) {
- if(this.grid[y][x]) {
- delete this.grid[y][x][item.p.id];
- }
- }
- }
- }
- },
-
- addGrid: function(item) {
- var grid = item.grid;
-
- for(var y = grid.Y1;y <= grid.Y2;y++) {
- if(!this.grid[y]) { this.grid[y] = {}; }
- for(var x = grid.X1;x <= grid.X2;x++) {
- if(!this.grid[y][x]) { this.grid[y][x] = {}; }
- this.grid[y][x][item.p.id] = item.p.type;
- }
- }
-
- },
-
- // Add an item into the collision detection grid,
- // Ignore the collision layer or objects without a type
- regrid: function(item,skipAdd) {
- if(this._collisionLayer && item === this._collisionLayer) { return; }
-
- var c = item.c || item.p;
-
- var gridX1 = Math.floor((c.x - c.cx) / this.options.gridW),
- gridY1 = Math.floor((c.y - c.cy) / this.options.gridH),
- gridX2 = Math.floor((c.x - c.cx + c.w) / this.options.gridW),
- gridY2 = Math.floor((c.y - c.cy + c.h) / this.options.gridH),
- grid = item.grid;
-
- if(grid.X1 !== gridX1 || grid.X2 !== gridX2 ||
- grid.Y1 !== gridY1 || grid.Y2 !== gridY2) {
-
- if(grid.X1 !== void 0) { this.delGrid(item); }
- grid.X1 = gridX1;
- grid.X2 = gridX2;
- grid.Y1 = gridY1;
- grid.Y2 = gridY2;
-
- if(!skipAdd) { this.addGrid(item); }
- }
- },
-
- markSprites: function(items,time) {
- var viewport = this.viewport,
- scale = viewport ? viewport.scale : 1,
- x = viewport ? viewport.x : 0,
- y = viewport ? viewport.y : 0,
- viewW = Q.width / scale,
- viewH = Q.height / scale,
- gridX1 = Math.floor(x / this.options.gridW),
- gridY1 = Math.floor(y / this.options.gridH),
- gridX2 = Math.floor((x + viewW) / this.options.gridW),
- gridY2 = Math.floor((y + viewH) / this.options.gridH),
- gridRow, gridBlock;
-
- for(var iy=gridY1; iy<=gridY2; iy++) {
- if((gridRow = this.grid[iy])) {
- for(var ix=gridX1; ix<=gridX2; ix++) {
- if((gridBlock = gridRow[ix])) {
- for(var id in gridBlock) {
- this.index[id].mark = time;
- if(this.index[id].container) { this.index[id].container.mark = time; }
- }
- }
- }
- }
- }
-
- if(this._collisionLayer) { this._collisionLayer.mark = time; }
- },
-
- updateSprites: function(items,dt,isContainer) {
- var item;
-
- for(var i=0,len=items.length;i 0) {
- for(var i=0,len=this.removeList.length;i= this.time) {
- item.render(ctx);
- }
- }
- this.trigger("render",ctx);
- this.trigger("postrender",ctx);
- }
- });
-
- Q.activeStage = 0;
-
- Q.StageSelector = Q.Class.extend({
- emptyList: [],
-
- init: function(stage,selector) {
- this.stage = stage;
- this.selector = selector;
-
- // Generate an object list from the selector
- // TODO: handle array selectors
- this.items = this.stage.lists[this.selector] || this.emptyList;
- this.length = this.items.length;
- },
-
- each: function(callback) {
- for(var i=0,len=this.items.length;i 1/15) { dt = 1.0/15; }
-
- for(i =0,len=Q.stages.length;i maxX) { maxX = x; }
- if(y < minY) { minY = y; }
- if(y > maxY) { maxY = y; }
- }
-
- if(minX === maxX) { maxX+=1; }
- if(minY === maxY) { maxY+=1; }
-
- c.cx = c.x - minX;
- c.cy = c.y - minY;
-
- c.w = maxX - minX;
- c.h = maxY - minY;
-
- // TODO: Invoke moved on children
- };
-
-
-
-// Properties:
- // x
- // y
- // z - sort order
- // sheet or asset
- // frame
- Q.GameObject.extend("Sprite",{
- init: function(props,defaultProps) {
- this.p = Q._extend({
- x: 0,
- y: 0,
- z: 0,
- opacity: 1,
- angle: 0,
- frame: 0,
- type: Q.SPRITE_DEFAULT | Q.SPRITE_ACTIVE
- },defaultProps);
-
- this.matrix = new Q.Matrix2D();
- this.children = [];
-
- Q._extend(this.p,props);
-
- this.size();
- this.p.id = this.p.id || Q._uniqueId();
-
- this.c = { points: [] };
-
- this.refreshMatrix();
- },
-
- // Resets the width, height and center based on the
- // asset or sprite sheet
- size: function(force) {
- if(force || (!this.p.w || !this.p.h)) {
- if(this.asset()) {
- this.p.w = this.asset().width;
- this.p.h = this.asset().height;
- } else if(this.sheet()) {
- this.p.w = this.sheet().tileW;
- this.p.h = this.sheet().tileH;
- }
- }
-
- this.p.cx = (force || this.p.cx === void 0) ? (this.p.w / 2) : this.p.cx;
- this.p.cy = (force || this.p.cy === void 0) ? (this.p.h / 2) : this.p.cy;
- },
-
- // Get or set the asset associate with this sprite
- asset: function(name,resize) {
- if(!name) { return Q.asset(this.p.asset); }
-
- this.p.asset = name;
- if(resize) {
- this.size(true);
- Q._generatePoints(this,true);
- }
- },
-
- // Get or set the sheet associate with this sprite
- sheet: function(name,resize) {
- if(!name) { return Q.sheet(this.p.sheet); }
-
- this.p.sheet = name;
- if(resize) {
- this.size(true);
- Q._generatePoints(this,true);
- }
- },
-
- hide: function() {
- this.p.hidden = true;
- },
-
- show: function() {
- this.p.hidden = false;
- },
-
- set: function(properties) {
- Q._extend(this.p,properties);
- return this;
- },
-
- _sortChild: function(a,b) {
- return ((a.p && a.p.z) || -1) - ((b.p && b.p.z) || -1);
- },
-
- _flipArgs: {
- "x": [ -1, 1],
- "y": [ 1, -1],
- "xy": [ -1, -1]
- },
-
- render: function(ctx) {
- var p = this.p;
-
- if(p.hidden) { return; }
- if(!ctx) { ctx = Q.ctx; }
-
- this.trigger('predraw',ctx);
-
- ctx.save();
-
- if(this.p.opacity !== void 0 && this.p.opacity !== 1) {
- ctx.globalAlpha = this.p.opacity;
- }
-
- this.matrix.setContextTransform(ctx);
-
- if(this.p.flip) { ctx.scale.apply(ctx,this._flipArgs[this.p.flip]); }
-
- this.trigger('beforedraw',ctx);
- this.draw(ctx);
- this.trigger('draw',ctx);
-
- ctx.restore();
-
- // Children set up their own complete matrix
- // from the base stage matrix
- if(this.p.sort) { this.children.sort(this._sortChild); }
- Q._invoke(this.children,"render",ctx);
-
- this.trigger('postdraw',ctx);
-
- if(Q.debug) { this.debugRender(ctx); }
-
- },
-
- center: function() {
- if(this.container) {
- this.p.x = this.container.p.w / 2;
- this.p.y = this.container.p.h / 2;
- } else {
- this.p.x = Q.width / 2;
- this.p.y = Q.height / 2;
- }
-
- },
-
- draw: function(ctx) {
- var p = this.p;
- if(p.sheet) {
- this.sheet().draw(ctx,-p.cx,-p.cy,p.frame);
- } else if(p.asset) {
- ctx.drawImage(Q.asset(p.asset),-p.cx,-p.cy);
- }
- },
-
- debugRender: function(ctx) {
- if(!this.p.points) {
- Q._generatePoints(this);
- }
- ctx.save();
- this.matrix.setContextTransform(ctx);
- ctx.beginPath();
- ctx.fillStyle = this.p.hit ? "blue" : "red";
- ctx.strokeStyle = "#FF0000";
- ctx.fillStyle = "rgba(0,0,0,0.5)";
-
- ctx.moveTo(this.p.points[0][0],this.p.points[0][1]);
- for(var i=0;i 0) {
- this.stage.updateSprites(this.children,dt,true);
- }
- },
-
- refreshMatrix: function() {
- var p = this.p;
- this.matrix.identity();
-
- if(this.container) { this.matrix.multiply(this.container.matrix); }
-
- this.matrix.translate(p.x,p.y);
-
- if(p.scale) { this.matrix.scale(p.scale,p.scale); }
-
- this.matrix.rotateDeg(p.angle);
- }
- });
-
- Q.Sprite.extend("MovingSprite",{
- init: function(props,defaultProps) {
- this._super(Q._extend({
- vx: 0,
- vy: 0,
- ax: 0,
- ay: 0
- },props),defaultProps);
- },
-
- step: function(dt) {
- var p = this.p;
-
- p.vx += p.ax * dt;
- p.vy += p.ay * dt;
-
- p.x += p.vx * dt;
- p.y += p.vy * dt;
- }
- });
-
-
-
-
- return Q;
-};
-
diff --git a/lib/quintus_touch.js b/lib/quintus_touch.js
deleted file mode 100644
index 9afab4a..0000000
--- a/lib/quintus_touch.js
+++ /dev/null
@@ -1,205 +0,0 @@
-/*global Quintus:false */
-
-Quintus.Touch = function(Q) {
- if(Q._isUndefined(Quintus.Sprites)) {
- throw "Quintus.Touch requires Quintus.Sprites Module";
- }
-
- var hasTouch = !!('ontouchstart' in window);
-
- var touchStage = [0];
- var touchType = 0;
-
- Q.Evented.extend("TouchSystem",{
-
- init: function() {
- var touchSystem = this;
-
- this.boundTouch = function(e) { touchSystem.touch(e); };
- this.boundDrag = function(e) { touchSystem.drag(e); };
- this.boundEnd = function(e) { touchSystem.touchEnd(e); };
-
- Q.el.addEventListener('touchstart',this.boundTouch);
- Q.el.addEventListener('mousedown',this.boundTouch);
-
- Q.el.addEventListener('touchmove',this.boundDrag);
- Q.el.addEventListener('mousemove',this.boundDrag);
-
- Q.el.addEventListener('touchend',this.boundEnd);
- Q.el.addEventListener('mouseup',this.boundEnd);
- Q.el.addEventListener('touchcancel',this.boundEnd);
-
- this.touchPos = new Q.Evented();
- this.touchPos.grid = {};
- this.touchPos.p = { w:1, h:1, cx: 0, cy: 0 };
- this.activeTouches = {};
- this.touchedObjects = {};
- },
-
- destroy: function() {
- Q.el.removeEventListener('touchstart',this.boundTouch);
- Q.el.removeEventListener('mousedown',this.boundTouch);
-
- Q.el.removeEventListener('touchmove',this.boundDrag);
- Q.el.removeEventListener('mousemove',this.boundDrag);
-
- Q.el.removeEventListener('touchend',this.boundEnd);
- Q.el.removeEventListener('mouseup',this.boundEnd);
- Q.el.removeEventListener('touchcancel',this.boundEnd);
- },
-
- normalizeTouch: function(touch,stage) {
- var canvasPosX = touch.offsetX,
- canvasPosY = touch.offsetY;
-
-
- if(Q._isUndefined(canvasPosX) || Q._isUndefined(canvasPosY)) {
- canvasPosX = touch.layerX;
- canvasPosY = touch.layerY;
- }
-
- if(Q._isUndefined(canvasPosX) || Q._isUndefined(canvasPosY)) {
- if(Q.touch.offsetX === void 0) {
- Q.touch.offsetX = 0;
- Q.touch.offsetY = 0;
- var el = Q.el;
- do {
- Q.touch.offsetX += el.offsetLeft;
- Q.touch.offsetY += el.offsetTop;
- } while(el = el.offsetParent);
- }
- canvasPosX = touch.pageX - Q.touch.offsetX;
- canvasPosY = touch.pageY - Q.touch.offsetY;
- }
-
-
- this.touchPos.p.ox = this.touchPos.p.px = canvasPosX / Q.cssWidth * Q.width;
- this.touchPos.p.oy = this.touchPos.p.py = canvasPosY / Q.cssHeight * Q.height;
-
- if(stage.viewport) {
- this.touchPos.p.px /= stage.viewport.scale;
- this.touchPos.p.py /= stage.viewport.scale;
- this.touchPos.p.px += stage.viewport.x;
- this.touchPos.p.py += stage.viewport.y;
- }
-
- this.touchPos.p.x = this.touchPos.p.px;
- this.touchPos.p.y = this.touchPos.p.py;
-
- this.touchPos.obj = null;
- return this.touchPos;
- },
-
- touch: function(e) {
- var touches = e.changedTouches || [ e ];
-
- for(var i=0;i maxX) { maxX = maxObjX; }
- if(maxObjY > maxY) { maxY = maxObjY; }
-
- }
-
- this.p.cx = -minX + paddingX;
- this.p.cy = -minY + paddingY;
- this.p.w = maxX - minX + paddingX * 2;
- this.p.h = maxY - minY + paddingY * 2;
- },
-
- addShadow: function(ctx) {
- if(this.p.shadow) {
- var shadowAmount = Q._isNumber(this.p.shadow) ? this.p.shadow : 5;
- ctx.shadowOffsetX=shadowAmount;
- ctx.shadowOffsetY=shadowAmount;
- ctx.shadowColor = this.p.shadowColor || "rgba(0,0,50,0.1)";
- }
- },
-
- clearShadow: function(ctx) {
- ctx.shadowColor = "transparent";
- },
-
- drawRadius: function(ctx) {
- Q.UI.roundRect(ctx,this.p);
- this.addShadow(ctx);
- ctx.fill();
- if(this.p.border) {
- this.clearShadow(ctx);
- ctx.lineWidth = this.p.border;
- ctx.stroke();
- }
- },
-
- drawSquare: function(ctx) {
- this.addShadow(ctx);
- if(this.p.fill) {
- ctx.fillRect(-this.p.cx,-this.p.cy,
- this.p.w,this.p.h);
- }
-
- if(this.p.border) {
- this.clearShadow(ctx);
- ctx.lineWidth = this.p.border;
- ctx.strokeRect(-this.p.cx,-this.p.cy,
- this.p.w,this.p.h);
- }
- },
-
- draw: function(ctx) {
- if(this.p.hidden) { return false; }
- if(!this.p.border && !this.p.fill) { return; }
-
- ctx.globalAlpha = this.p.opacity;
- if(this.p.frame === 1 && this.p.highlight) {
- ctx.fillStyle = this.p.highlight;
- } else {
- ctx.fillStyle = this.p.fill;
- }
- ctx.strokeStyle = this.p.stroke;
-
- if(this.p.radius > 0) {
- this.drawRadius(ctx);
- } else {
- this.drawSquare(ctx);
- }
-
- }
- });
-
-
- Q.UI.Text = Q.Sprite.extend("UI.Text", {
- init: function(p,defaultProps) {
- this._super(Q._defaults(p||{},defaultProps),{
- type: Q.SPRITE_UI,
- size: 24
- });
-
- //this.el = document.createElement("canvas");
- //this.ctx = this.el.getContext("2d");
-
- if(this.p.label) {
- this.calcSize();
- }
-
- //this.prerender();
- },
-
- calcSize: function() {
- this.setFont(Q.ctx);
- this.splitLabel = this.p.label.split("\n");
- var maxLabel = "";
- for(var i = 0;i < this.splitLabel.length;i++) {
- if(this.splitLabel[i].length > maxLabel.length) {
- maxLabel = this.splitLabel[i];
- }
- }
-
- var metrics = Q.ctx.measureText(maxLabel);
- this.p.h = (this.p.size || 24) * this.splitLabel.length * 1.2;
- this.p.w = metrics.width;
- this.p.cx = this.p.w / 2;
- this.p.cy = this.p.h / 2;
- },
-
- prerender: function() {
- if(this.p.oldLabel === this.p.label) { return; }
- this.p.oldLabel = this.p.label;
- this.calcSize();
- this.el.width = this.p.w;
- this.el.height = this.p.h * 4;
- this.ctx.clearRect(0,0,this.p.w,this.p.h);
-
- this.ctx.fillStyle = "#FF0";
- this.ctx.fillRect(0,0,this.p.w,this.p.h/2);
- this.setFont(this.ctx);
-
- this.ctx.fillText(this.p.label,0,0);
- },
-
- draw: function(ctx) {
- //this.prerender();
- if(this.p.opacity === 0) { return; }
-
- if(this.p.oldLabel !== this.p.label) { this.calcSize(); }
-
- this.setFont(ctx);
- if(this.p.opacity !== void 0) { ctx.globalAlpha = this.p.opacity; }
- for(var i =0;i 1) {
- this.p.frame = 1;
- }
- },
-
- push: function() {
- this.p.frame = 0;
- if(this.callback) { this.callback(); }
- this.trigger('click');
- },
-
- draw: function(ctx) {
- this._super(ctx);
-
- if(this.p.asset || this.p.sheet) {
- Q.Sprite.prototype.draw.call(this,ctx);
- }
-
- if(this.p.label) {
- ctx.save();
- this.setFont(ctx);
- ctx.fillText(this.p.label,0,0);
- ctx.restore();
- }
- },
-
- setFont: function(ctx) {
- ctx.textBaseline = "middle";
- ctx.font = this.p.font || "400 24px arial";
- ctx.fillStyle = this.p.fontColor || "black";
- ctx.textAlign = "center";
- }
-
- });
-
- Q.UI.IFrame = Q.Sprite.extend("UI.IFrame", {
- init: function(p) {
- this._super(p, { opacity: 1, type: Q.SPRITE_UI | Q.SPRITE_DEFAULT });
-
- Q.wrapper.style.overflow = "hidden";
-
- this.iframe = document.createElement("IFRAME");
- this.iframe.setAttribute("src",this.p.url);
- this.iframe.style.position = "absolute";
- this.iframe.style.zIndex = 500;
- this.iframe.setAttribute("width",this.p.w);
- this.iframe.setAttribute("height",this.p.h);
- this.iframe.setAttribute("frameborder",0);
-
- if(this.p.background) {
- this.iframe.style.backgroundColor = this.p.background;
-
- }
-
-
- Q.wrapper.appendChild(this.iframe);
- this.on("inserted",function(parent) {
- this.positionIFrame();
- parent.on("destroyed",this,"remove");
- });
- },
-
- positionIFrame: function() {
- var x = this.p.x;
- var y = this.p.y;
- if(this.stage.viewport) {
- x -= this.stage.viewport.x;
- y -= this.stage.viewport.y;
- }
-
- if(this.oldX !== x || this.oldY !== y || this.oldOpacity !== this.p.opacity) {
-
- this.iframe.style.top = (y - this.p.cy) + "px";
- this.iframe.style.left = (x - this.p.cx) + "px";
- this.iframe.style.opacity = this.p.opacity;
-
- this.oldX = x;
- this.oldY = y;
- this.oldOpacity = this.p.opacity;
- }
- },
-
- step: function(dt) {
- this._super(dt);
- this.positionIFrame();
- },
-
- remove: function() {
- if(this.iframe) {
- Q.wrapper.removeChild(this.iframe);
- this.iframe = null;
- }
- }
- });
-
- Q.UI.HTMLElement = Q.Sprite.extend("UI.HTMLElement", {
- init: function(p) {
- this._super(p, { opacity: 1, type: Q.SPRITE_UI });
-
- Q.wrapper.style.overflow = "hidden";
-
- this.el = document.createElement("div");
- this.el.innerHTML = this.p.html;
-
- Q.wrapper.appendChild(this.el);
- this.on("inserted",function(parent) {
- this.position();
- parent.on("destroyed",this,"remove");
- parent.on("clear",this,"remove");
- });
- },
-
- position: function() {
- },
-
- step: function(dt) {
- this._super(dt);
- this.position();
- },
-
- remove: function() {
- if(this.el) {
- Q.wrapper.removeChild(this.el);
- this.el= null;
- }
- }
- });
-
- Q.UI.VerticalLayout = Q.Sprite.extend("UI.VerticalLayout",{
-
-
- init: function(p) {
- this.children = [];
- this._super(p, { type: 0 });
- },
-
- insert: function(sprite) {
- this.stage.insert(sprite,this);
- this.relayout();
- // Bind to destroy
- return sprite;
- },
-
- relayout: function() {
- var totalHeight = 0;
- for(var i=0;i