use quintus from the cdn, less bugs
This commit is contained in:
		
							parent
							
								
									392af1b01f
								
							
						
					
					
						commit
						65a79b70af
					
				
					 10 changed files with 9 additions and 5137 deletions
				
			
		
							
								
								
									
										24
									
								
								index.html
									
										
									
									
									
								
							
							
						
						
									
										24
									
								
								index.html
									
										
									
									
									
								
							| 
						 | 
					@ -1,23 +1,17 @@
 | 
				
			||||||
<!DOCTYPE HTML>
 | 
					<!DOCTYPE HTML>
 | 
				
			||||||
<html lang="en">
 | 
					<html lang="en">
 | 
				
			||||||
<head>
 | 
					<head>
 | 
				
			||||||
<meta charset="UTF-8">
 | 
					  <meta charset="UTF-8">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<meta name="viewport" content="width=device-width, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"/>
 | 
					  <meta name="viewport" content="width=device-width, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"/>
 | 
				
			||||||
<title>genossen! am 30.11. laden neingeist und starbug ein zu einem cosmonautischen fest!</title>
 | 
					  <title>genossen! am 30.11. laden neingeist und starbug ein zu einem cosmonautischen fest!</title>
 | 
				
			||||||
<script src='lib/quintus.js'></script>
 | 
					 | 
				
			||||||
<script src='lib/quintus_sprites.js'></script>
 | 
					 | 
				
			||||||
<script src='lib/quintus_scenes.js'></script>
 | 
					 | 
				
			||||||
<script src='lib/quintus_input.js'></script>
 | 
					 | 
				
			||||||
<script src='lib/quintus_anim.js'></script>
 | 
					 | 
				
			||||||
<script src='lib/quintus_2d.js'></script>
 | 
					 | 
				
			||||||
<script src='lib/quintus_touch.js'></script>
 | 
					 | 
				
			||||||
<script src='lib/quintus_ui.js'></script>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script src='platformer.js'></script>
 | 
					  <script src='http://cdn.html5quintus.com/v0.1.5/quintus-all.js'></script>
 | 
				
			||||||
<style> 
 | 
					  <script src='platformer.js'></script>
 | 
				
			||||||
  body { padding:0px; margin:0px; } 
 | 
					
 | 
				
			||||||
</style>
 | 
					  <style>
 | 
				
			||||||
 | 
					    body { padding:0px; margin:0px; }
 | 
				
			||||||
 | 
					  </style>
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body>
 | 
					<body>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1599
									
								
								lib/quintus.js
									
										
									
									
									
								
							
							
						
						
									
										1599
									
								
								lib/quintus.js
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -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<p.blockTileH;y++) {
 | 
					 | 
				
			||||||
        if(tiles[y+blockOffsetY]) {
 | 
					 | 
				
			||||||
          for(var x=0;x<p.blockTileW;x++) {
 | 
					 | 
				
			||||||
            if(this.drawableTile(tiles[y+blockOffsetY][x+blockOffsetX])) {
 | 
					 | 
				
			||||||
              sheet.draw(ctx,
 | 
					 | 
				
			||||||
                         x*p.tileW,
 | 
					 | 
				
			||||||
                         y*p.tileH,
 | 
					 | 
				
			||||||
                         tiles[y+blockOffsetY][x+blockOffsetX]);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    drawBlock: function(ctx, blockX, blockY) {
 | 
					 | 
				
			||||||
      var p = this.p,
 | 
					 | 
				
			||||||
          startX = Math.floor(blockX * p.blockW + p.x),
 | 
					 | 
				
			||||||
          startY = Math.floor(blockY * p.blockH + p.y);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(!this.blocks[blockY] || !this.blocks[blockY][blockX]) {
 | 
					 | 
				
			||||||
        this.prerenderBlock(blockX,blockY);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(this.blocks[blockY]  && this.blocks[blockY][blockX]) {
 | 
					 | 
				
			||||||
        ctx.drawImage(this.blocks[blockY][blockX],startX,startY);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    draw: function(ctx) {
 | 
					 | 
				
			||||||
      var p = this.p,
 | 
					 | 
				
			||||||
          viewport = this.stage.viewport,
 | 
					 | 
				
			||||||
          scale = viewport ? viewport.scale : 1,
 | 
					 | 
				
			||||||
          x = viewport ? viewport.x : 0,
 | 
					 | 
				
			||||||
          y = viewport ? viewport.y : 0,
 | 
					 | 
				
			||||||
          viewW = Q.width / scale,
 | 
					 | 
				
			||||||
          viewH = Q.height / scale,
 | 
					 | 
				
			||||||
          startBlockX = Math.floor((x - p.x) / p.blockW),
 | 
					 | 
				
			||||||
          startBlockY = Math.floor((y - p.y) / p.blockH),
 | 
					 | 
				
			||||||
          endBlockX = Math.floor((x + viewW - p.x) / p.blockW),
 | 
					 | 
				
			||||||
          endBlockY = Math.floor((y + viewH - p.y) / p.blockH);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for(var iy=startBlockY;iy<=endBlockY;iy++) {
 | 
					 | 
				
			||||||
        for(var ix=startBlockX;ix<=endBlockX;ix++) {
 | 
					 | 
				
			||||||
          this.drawBlock(ctx,ix,iy);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.gravityY = 9.8*100;
 | 
					 | 
				
			||||||
  Q.gravityX = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.component('2d',{
 | 
					 | 
				
			||||||
    added: function() {
 | 
					 | 
				
			||||||
      var entity = this.entity;
 | 
					 | 
				
			||||||
      Q._defaults(entity.p,{
 | 
					 | 
				
			||||||
        vx: 0,
 | 
					 | 
				
			||||||
        vy: 0,
 | 
					 | 
				
			||||||
        ax: 0,
 | 
					 | 
				
			||||||
        ay: 0,
 | 
					 | 
				
			||||||
        gravity: 1,
 | 
					 | 
				
			||||||
        collisionMask: Q.SPRITE_DEFAULT
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      entity.on('step',this,"step");
 | 
					 | 
				
			||||||
      entity.on('hit',this,'collision');
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    collision: function(col,last) {
 | 
					 | 
				
			||||||
      var entity = this.entity,
 | 
					 | 
				
			||||||
          p = entity.p,
 | 
					 | 
				
			||||||
          magnitude = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(col.obj.p && col.obj.p.sensor) {
 | 
					 | 
				
			||||||
        col.obj.trigger("sensor",entity);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      col.impact = 0;
 | 
					 | 
				
			||||||
      var impactX = Math.abs(p.vx);
 | 
					 | 
				
			||||||
      var impactY = Math.abs(p.vy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      p.x -= col.separate[0];
 | 
					 | 
				
			||||||
      p.y -= col.separate[1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Top collision
 | 
					 | 
				
			||||||
      if(col.normalY < -0.3) { 
 | 
					 | 
				
			||||||
        if(p.vy > 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;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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--;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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<Q.audio.channelMax;i++) {	
 | 
					 | 
				
			||||||
      Q.audio.channels[i] = {};
 | 
					 | 
				
			||||||
      Q.audio.channels[i]['channel'] = new Audio(); 
 | 
					 | 
				
			||||||
      Q.audio.channels[i]['finished'] = -1;	
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 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];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Find a free audio channel and play the sound
 | 
					 | 
				
			||||||
      for (var i=0;i<Q.audio.channels.length;i++) {
 | 
					 | 
				
			||||||
        // Check the channel is either finished or not looping
 | 
					 | 
				
			||||||
        if (!Q.audio.channels[i]['loop'] && Q.audio.channels[i]['finished'] < now) {	
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          Q.audio.channels[i]['channel'].src = Q.asset(s).src;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          // If we're looping - just set loop to true to prevent this channcel
 | 
					 | 
				
			||||||
          // from being used.
 | 
					 | 
				
			||||||
          if(options && options['loop']) { 
 | 
					 | 
				
			||||||
            Q.audio.channels[i]['loop'] = true;
 | 
					 | 
				
			||||||
            Q.audio.channels[i]['channel'].loop = true;
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            Q.audio.channels[i]['finished'] = now + Q.asset(s).duration*1000;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          Q.audio.channels[i]['channel'].load();
 | 
					 | 
				
			||||||
          Q.audio.channels[i]['channel'].play();
 | 
					 | 
				
			||||||
          break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Stop a single sound asset or stop all sounds currently playing
 | 
					 | 
				
			||||||
    Q.audio.stop = function(s) {
 | 
					 | 
				
			||||||
      var src = s ? Q.asset(s).src : null;
 | 
					 | 
				
			||||||
      var tm = new Date().getTime();
 | 
					 | 
				
			||||||
      for (var i=0;i<Q.audio.channels.length;i++) {
 | 
					 | 
				
			||||||
        if ((!src || Q.audio.channels[i]['channel'].src === src) && 
 | 
					 | 
				
			||||||
            (Q.audio.channels[i]['loop'] || Q.audio.channels[i]['finished'] >= tm)) {
 | 
					 | 
				
			||||||
          Q.audio.channels[i]['channel'].pause();
 | 
					 | 
				
			||||||
          Q.audio.channels[i]['loop'] = false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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<len;i++) {
 | 
					 | 
				
			||||||
          if(pos.x < opts.unit * (i+1)) {
 | 
					 | 
				
			||||||
            return opts.controls[i][0];
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      function touchDispatch(event) {
 | 
					 | 
				
			||||||
        var wasOn = {},
 | 
					 | 
				
			||||||
            i, len, tch, key, actionName;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Reset all the actions bound to controls
 | 
					 | 
				
			||||||
        // but keep track of all the actions that were on
 | 
					 | 
				
			||||||
        for(i=0,len = opts.controls.length;i<len;i++) {
 | 
					 | 
				
			||||||
          actionName = opts.controls[i][0];
 | 
					 | 
				
			||||||
          if(Q.inputs[actionName]) { wasOn[actionName] = true; }
 | 
					 | 
				
			||||||
          Q.inputs[actionName] = false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var touches = event.touches ? event.touches : [ event ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(i=0,len=touches.length;i<len;i++) {
 | 
					 | 
				
			||||||
          tch = touches[i];
 | 
					 | 
				
			||||||
          key = getKey(tch);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if(key) {
 | 
					 | 
				
			||||||
            // Mark this input as on
 | 
					 | 
				
			||||||
            Q.inputs[key] = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Either trigger a new action
 | 
					 | 
				
			||||||
            // or remove from wasOn list
 | 
					 | 
				
			||||||
            if(!wasOn[key]) {
 | 
					 | 
				
			||||||
              Q.input.trigger(key);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
              delete wasOn[key];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Any remaining were on the last frame
 | 
					 | 
				
			||||||
        // and need to trigger an up action
 | 
					 | 
				
			||||||
        for(actionName in wasOn) {
 | 
					 | 
				
			||||||
          Q.input.trigger(actionName + "Up");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.touchDispatchHandler = function(e) {
 | 
					 | 
				
			||||||
        touchDispatch(e);
 | 
					 | 
				
			||||||
        e.preventDefault();
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Q._each(["touchstart","touchend","touchmove","touchcancel"],function(evt) {
 | 
					 | 
				
			||||||
        Q.el.addEventListener(evt,this.touchDispatchHandler);
 | 
					 | 
				
			||||||
      },this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.touchEnabled = true;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    disableTouchControls: function() {
 | 
					 | 
				
			||||||
      Q._each(["touchstart","touchend","touchmove","touchcancel"],function(evt) {
 | 
					 | 
				
			||||||
        Q.el.removeEventListener(evt,this.touchDispatchHandler);
 | 
					 | 
				
			||||||
      },this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Q.el.removeEventListener('touchstart',this.joypadStart);
 | 
					 | 
				
			||||||
      Q.el.removeEventListener('touchmove',this.joypadMove);
 | 
					 | 
				
			||||||
      Q.el.removeEventListener('touchend',this.joypadEnd);
 | 
					 | 
				
			||||||
      Q.el.removeEventListener('touchcancel',this.joypadEnd);
 | 
					 | 
				
			||||||
      this.touchEnabled = false;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   joypadControls: function(opts) {
 | 
					 | 
				
			||||||
      if(this.joypadEnabled) { return false; }
 | 
					 | 
				
			||||||
      if(!hasTouch) { return false; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      var joypad = Q.joypad = Q._defaults(opts || {},{
 | 
					 | 
				
			||||||
        size: 50,
 | 
					 | 
				
			||||||
        trigger: 20,
 | 
					 | 
				
			||||||
        center: 25,
 | 
					 | 
				
			||||||
        color: "#CCC",
 | 
					 | 
				
			||||||
        background: "#000",
 | 
					 | 
				
			||||||
        alpha: 0.5,
 | 
					 | 
				
			||||||
        zone: Q.width / 2,
 | 
					 | 
				
			||||||
        joypadTouch: null,
 | 
					 | 
				
			||||||
        inputs: DEFAULT_JOYPAD_INPUTS,
 | 
					 | 
				
			||||||
        triggers: []
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.joypadStart = function(evt) {
 | 
					 | 
				
			||||||
        if(joypad.joypadTouch === null) {
 | 
					 | 
				
			||||||
          var touch = evt.changedTouches[0],
 | 
					 | 
				
			||||||
              loc = Q.input.touchLocation(touch);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if(loc.x < joypad.zone) {
 | 
					 | 
				
			||||||
            joypad.joypadTouch = touch.identifier;
 | 
					 | 
				
			||||||
            joypad.centerX = loc.x;
 | 
					 | 
				
			||||||
            joypad.centerY = loc.y; 
 | 
					 | 
				
			||||||
            joypad.x = null;
 | 
					 | 
				
			||||||
            joypad.y = null;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      this.joypadMove = function(e) {
 | 
					 | 
				
			||||||
        if(joypad.joypadTouch !== null) {
 | 
					 | 
				
			||||||
          var evt = e;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          for(var i=0,len=evt.changedTouches.length;i<len;i++) {
 | 
					 | 
				
			||||||
            var touch = evt.changedTouches[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(touch.identifier === joypad.joypadTouch) {
 | 
					 | 
				
			||||||
              var loc = Q.input.touchLocation(touch),
 | 
					 | 
				
			||||||
                  dx = loc.x - joypad.centerX,
 | 
					 | 
				
			||||||
                  dy = loc.y - joypad.centerY,
 | 
					 | 
				
			||||||
                  dist = Math.sqrt(dx * dx + dy * dy),
 | 
					 | 
				
			||||||
                  overage = Math.max(1,dist / joypad.size),
 | 
					 | 
				
			||||||
                  ang =  Math.atan2(dx,dy);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              if(overage > 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<triggers.length;k++) {
 | 
					 | 
				
			||||||
                var actionName = joypad.inputs[k];
 | 
					 | 
				
			||||||
                if(triggers[k]) {
 | 
					 | 
				
			||||||
                  Q.inputs[actionName] = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                  if(!joypad.triggers[k]) { 
 | 
					 | 
				
			||||||
                    Q.input.trigger(actionName);
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                  Q.inputs[actionName] = false;
 | 
					 | 
				
			||||||
                  if(joypad.triggers[k]) { 
 | 
					 | 
				
			||||||
                    Q.input.trigger(actionName + "Up");
 | 
					 | 
				
			||||||
                  }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              Q._extend(joypad, {
 | 
					 | 
				
			||||||
                dx: dx, dy: dy,
 | 
					 | 
				
			||||||
                x: joypad.centerX + dx,
 | 
					 | 
				
			||||||
                y: joypad.centerY + dy,
 | 
					 | 
				
			||||||
                dist: dist,
 | 
					 | 
				
			||||||
                ang: ang,
 | 
					 | 
				
			||||||
                triggers: triggers
 | 
					 | 
				
			||||||
              });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        e.preventDefault();
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.joypadEnd = function(e) { 
 | 
					 | 
				
			||||||
          var evt = e;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if(joypad.joypadTouch !== null) {
 | 
					 | 
				
			||||||
            for(var i=0,len=evt.changedTouches.length;i<len;i++) { 
 | 
					 | 
				
			||||||
            var touch = evt.changedTouches[i];
 | 
					 | 
				
			||||||
              if(touch.identifier === joypad.joypadTouch) {
 | 
					 | 
				
			||||||
                for(var k=0;k<joypad.triggers.length;k++) {
 | 
					 | 
				
			||||||
                  var actionName = joypad.inputs[k];
 | 
					 | 
				
			||||||
                  Q.inputs[actionName] = false;
 | 
					 | 
				
			||||||
                    if(joypad.triggers[k]) {
 | 
					 | 
				
			||||||
                        Q.input.trigger(actionName + "Up");
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                joypad.joypadTouch = null;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          e.preventDefault();
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Q.el.addEventListener("touchstart",this.joypadStart);
 | 
					 | 
				
			||||||
      Q.el.addEventListener("touchmove",this.joypadMove);
 | 
					 | 
				
			||||||
      Q.el.addEventListener("touchend",this.joypadEnd);
 | 
					 | 
				
			||||||
      Q.el.addEventListener("touchcancel",this.joypadEnd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.joypadEnabled = true;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    mouseControls: function(options) {
 | 
					 | 
				
			||||||
      options = options || {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      var stageNum = options.stageNum || 0;
 | 
					 | 
				
			||||||
      var mouseInputX = options.mouseX || "mouseX";
 | 
					 | 
				
			||||||
      var mouseInputY = options.mouseY || "mouseY";
 | 
					 | 
				
			||||||
      var cursor = options.cursor || "off";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      var mouseMoveObj = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(cursor !== "on") {
 | 
					 | 
				
			||||||
          if(cursor === "off") {
 | 
					 | 
				
			||||||
              Q.el.style.cursor = 'none';
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          else {
 | 
					 | 
				
			||||||
              Q.el.style.cursor = cursor;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Q.inputs[mouseInputX] = 0;
 | 
					 | 
				
			||||||
      Q.inputs[mouseInputY] = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Q._mouseMove = function(e) {
 | 
					 | 
				
			||||||
        e.preventDefault();
 | 
					 | 
				
			||||||
        var touch = e.touches ? e.touches[0] : e;
 | 
					 | 
				
			||||||
        var el = Q.el, 
 | 
					 | 
				
			||||||
            posX = touch.offsetX,
 | 
					 | 
				
			||||||
            posY = touch.offsetY,
 | 
					 | 
				
			||||||
            eX, eY,
 | 
					 | 
				
			||||||
            stage = Q.stage(stageNum);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(stage) {
 | 
					 | 
				
			||||||
          mouseMoveObj.x= Q.canvasToStageX(posX,stage);
 | 
					 | 
				
			||||||
          mouseMoveObj.y= Q.canvasToStageY(posY,stage);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          Q.inputs[mouseInputX] = mouseMoveObj.x;
 | 
					 | 
				
			||||||
          Q.inputs[mouseInputY] = mouseMoveObj.y;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          Q.input.trigger('mouseMove',mouseMoveObj);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Q.el.addEventListener('mousemove',Q._mouseMove,true);
 | 
					 | 
				
			||||||
      Q.el.addEventListener('touchstart',Q._mouseMove,true);
 | 
					 | 
				
			||||||
      Q.el.addEventListener('touchmove',Q._mouseMove,true);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    disableMouseControls: function() {
 | 
					 | 
				
			||||||
      if(Q._mouseMove) {
 | 
					 | 
				
			||||||
        Q.el.removeEventListener("mousemove",Q._mouseMove, true);
 | 
					 | 
				
			||||||
        Q.el.style.cursor = 'inherit';
 | 
					 | 
				
			||||||
        Q._mouseMove = null;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    drawButtons: function() {
 | 
					 | 
				
			||||||
      var keypad = Q.input.keypad,
 | 
					 | 
				
			||||||
          ctx = Q.ctx;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      ctx.save();
 | 
					 | 
				
			||||||
      ctx.textAlign = "center"; 
 | 
					 | 
				
			||||||
      ctx.textBaseline = "middle";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for(var i=0;i<keypad.controls.length;i++) {
 | 
					 | 
				
			||||||
        var control = keypad.controls[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(control[0]) {
 | 
					 | 
				
			||||||
          ctx.font = "bold " + (keypad.size/2) + "px arial";
 | 
					 | 
				
			||||||
          var x = i * keypad.unit + keypad.gutter,
 | 
					 | 
				
			||||||
              y = keypad.bottom - keypad.unit,
 | 
					 | 
				
			||||||
              key = Q.inputs[control[0]];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          ctx.fillStyle = keypad.color || "#FFFFFF";
 | 
					 | 
				
			||||||
          ctx.globalAlpha = key ? 1.0 : 0.5;
 | 
					 | 
				
			||||||
          ctx.fillRect(x,y,keypad.size,keypad.size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          ctx.fillStyle = keypad.text || "#000000";
 | 
					 | 
				
			||||||
          ctx.fillText(control[1],
 | 
					 | 
				
			||||||
                       x+keypad.size/2,
 | 
					 | 
				
			||||||
                       y+keypad.size/2);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      ctx.restore();
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    drawCircle: function(x,y,color,size) {
 | 
					 | 
				
			||||||
      var ctx = Q.ctx,
 | 
					 | 
				
			||||||
          joypad = Q.joypad;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      ctx.save();
 | 
					 | 
				
			||||||
      ctx.beginPath();
 | 
					 | 
				
			||||||
      ctx.globalAlpha=joypad.alpha;
 | 
					 | 
				
			||||||
      ctx.fillStyle = color;
 | 
					 | 
				
			||||||
      ctx.arc(x, y, size, 0, Math.PI*2, true); 
 | 
					 | 
				
			||||||
      ctx.closePath();
 | 
					 | 
				
			||||||
      ctx.fill();
 | 
					 | 
				
			||||||
      ctx.restore();
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    drawJoypad: function() {
 | 
					 | 
				
			||||||
      var joypad = Q.joypad;
 | 
					 | 
				
			||||||
      if(joypad.joypadTouch !== null) {
 | 
					 | 
				
			||||||
        Q.input.drawCircle(joypad.centerX,
 | 
					 | 
				
			||||||
                           joypad.centerY,
 | 
					 | 
				
			||||||
                           joypad.background,
 | 
					 | 
				
			||||||
                           joypad.size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(joypad.x !== null) {
 | 
					 | 
				
			||||||
          Q.input.drawCircle(joypad.x,
 | 
					 | 
				
			||||||
                           joypad.y,
 | 
					 | 
				
			||||||
                           joypad.color,
 | 
					 | 
				
			||||||
                           joypad.center);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    drawCanvas: function() {
 | 
					 | 
				
			||||||
      if(this.touchEnabled) {
 | 
					 | 
				
			||||||
        this.drawButtons();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(this.joypadEnabled) {
 | 
					 | 
				
			||||||
        this.drawJoypad();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * Instance of the input subsytem that is actually used during development
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
   * @property Q.input
 | 
					 | 
				
			||||||
   * @for Quintus.Input
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  Q.input = new Q.InputSystem();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.controls = function(joypad) {
 | 
					 | 
				
			||||||
    Q.input.keyboardControls();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(joypad) {
 | 
					 | 
				
			||||||
      Q.input.touchControls({
 | 
					 | 
				
			||||||
        controls: [ [],[],[],['action','b'],['fire','a']]
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
      Q.input.joypadControls();
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      Q.input.touchControls();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return Q;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.component("platformerControls", {
 | 
					 | 
				
			||||||
    defaults: {
 | 
					 | 
				
			||||||
      speed: 200,
 | 
					 | 
				
			||||||
      jumpSpeed: -300
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    added: function() {
 | 
					 | 
				
			||||||
      var p = this.entity.p;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      Q._defaults(p,this.defaults);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.entity.on("step",this,"step");
 | 
					 | 
				
			||||||
      this.entity.on("bump.bottom",this,"landed");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      p.landed = 0;
 | 
					 | 
				
			||||||
      p.direction ='right';
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    landed: function(col) {
 | 
					 | 
				
			||||||
      var p = this.entity.p;
 | 
					 | 
				
			||||||
      p.landed = 1/5;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    step: function(dt) {
 | 
					 | 
				
			||||||
      var p = this.entity.p;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(Q.inputs['left']) {
 | 
					 | 
				
			||||||
        p.vx = -p.speed;
 | 
					 | 
				
			||||||
        p.direction = 'left';
 | 
					 | 
				
			||||||
      } else if(Q.inputs['right']) {
 | 
					 | 
				
			||||||
        p.direction = 'right';
 | 
					 | 
				
			||||||
        p.vx = p.speed;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        p.vx = 0;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(p.landed > 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; 
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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<p1.length;i++) {
 | 
					 | 
				
			||||||
        calculateNormal(p1,i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        min1 = dotProductAgainstNormal(p1[0]);
 | 
					 | 
				
			||||||
        max1 = min1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(j = 1; j<p1.length;j++) {
 | 
					 | 
				
			||||||
          tmp = dotProductAgainstNormal(p1[j]);
 | 
					 | 
				
			||||||
          if(tmp < min1) { min1 = tmp; }
 | 
					 | 
				
			||||||
          if(tmp > max1) { max1 = tmp; }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        min2 = dotProductAgainstNormal(p2[0]);
 | 
					 | 
				
			||||||
        max2 = min2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(j = 1;j<p2.length;j++) {
 | 
					 | 
				
			||||||
          tmp = dotProductAgainstNormal(p2[j]);
 | 
					 | 
				
			||||||
          if(tmp < min2) { min2 = tmp; }
 | 
					 | 
				
			||||||
          if(tmp > 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.h<o2y) || (o1y>o2y+c2.h) ||
 | 
					 | 
				
			||||||
             (o1x+c1.w<o2x) || (o1x>o2x+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<assetArray.length;i++) {
 | 
					 | 
				
			||||||
        var spriteClass = assetArray[i][0];
 | 
					 | 
				
			||||||
        var spriteProps = assetArray[i][1];
 | 
					 | 
				
			||||||
        this.insert(new Q[spriteClass](spriteProps));
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    each: function(callback) {
 | 
					 | 
				
			||||||
      for(var i=0,len=this.items.length;i<len;i++) {
 | 
					 | 
				
			||||||
        callback.call(this.items[i],arguments[1],arguments[2]);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    invoke: function(funcName) {
 | 
					 | 
				
			||||||
      for(var i=0,len=this.items.length;i<len;i++) {              
 | 
					 | 
				
			||||||
        this.items[i][funcName].call(
 | 
					 | 
				
			||||||
          this.items[i],arguments[1],arguments[2]
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect: function(func) {
 | 
					 | 
				
			||||||
      for(var i = this.items.length-1;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<lists.length;i++) {
 | 
					 | 
				
			||||||
        this.addToList(lists[i],object);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    addToList: function(list, itm) {
 | 
					 | 
				
			||||||
      if(!this.lists[list]) { this.lists[list] = []; }
 | 
					 | 
				
			||||||
      this.lists[list].push(itm);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    removeFromLists: function(lists, itm) {
 | 
					 | 
				
			||||||
      for(var i=0;i<lists.length;i++) {
 | 
					 | 
				
			||||||
        this.removeFromList(lists[i],itm);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    removeFromList: function(list, itm) {
 | 
					 | 
				
			||||||
      var listIndex = this.lists[list].indexOf(itm);
 | 
					 | 
				
			||||||
      if(listIndex !== -1) { 
 | 
					 | 
				
			||||||
        this.lists[list].splice(listIndex,1);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    insert: function(itm,container) {
 | 
					 | 
				
			||||||
      this.items.push(itm);
 | 
					 | 
				
			||||||
      itm.stage = this;
 | 
					 | 
				
			||||||
      itm.container = container;
 | 
					 | 
				
			||||||
      if(container) {
 | 
					 | 
				
			||||||
        container.children.push(itm);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      itm.grid = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Make sure we have a square of collision points
 | 
					 | 
				
			||||||
      Q._generatePoints(itm);
 | 
					 | 
				
			||||||
      Q._generateCollisionPoints(itm);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      if(itm.className) { this.addToList(itm.className, itm); }
 | 
					 | 
				
			||||||
      if(itm.activeComponents) { this.addToLists(itm.activeComponents, itm); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(itm.p) {
 | 
					 | 
				
			||||||
        this.index[itm.p.id] = itm;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      this.trigger('inserted',itm);
 | 
					 | 
				
			||||||
      itm.trigger('inserted',this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.regrid(itm);
 | 
					 | 
				
			||||||
      return itm;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    remove: function(itm) {
 | 
					 | 
				
			||||||
      this.delGrid(itm);
 | 
					 | 
				
			||||||
      this.removeList.push(itm);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    forceRemove: function(itm) {
 | 
					 | 
				
			||||||
      var idx =  this.items.indexOf(itm);
 | 
					 | 
				
			||||||
      if(idx !== -1) { 
 | 
					 | 
				
			||||||
        this.items.splice(idx,1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(itm.className) { this.removeFromList(itm.className,itm); }
 | 
					 | 
				
			||||||
        if(itm.activeComponents) { this.removeFromLists(itm.activeComponents,itm); }
 | 
					 | 
				
			||||||
        if(itm.container) {
 | 
					 | 
				
			||||||
          var containerIdx = itm.container.children.indexOf(itm);
 | 
					 | 
				
			||||||
          if(containerIdx !== -1) {
 | 
					 | 
				
			||||||
            itm.container.children.splice(containerIdx,1);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(itm.destroy) { itm.destroy(); }
 | 
					 | 
				
			||||||
        if(itm.p.id) {
 | 
					 | 
				
			||||||
          delete this.index[itm.p.id];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.trigger('removed',itm);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pause: function() {
 | 
					 | 
				
			||||||
      this.paused = true;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    unpause: function() {
 | 
					 | 
				
			||||||
      this.paused = false;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _gridCellCheck: function(type,id,obj,collisionMask) {
 | 
					 | 
				
			||||||
      if(!collisionMask || collisionMask & type) {
 | 
					 | 
				
			||||||
        var obj2 = this.index[id];
 | 
					 | 
				
			||||||
        if(obj2 && obj2 !== obj && Q.overlap(obj,obj2)) {
 | 
					 | 
				
			||||||
          var col= Q.collision(obj,obj2);
 | 
					 | 
				
			||||||
          if(col) {
 | 
					 | 
				
			||||||
            col.obj = obj2;
 | 
					 | 
				
			||||||
            return col;
 | 
					 | 
				
			||||||
          } else {
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    gridTest: function(obj,collisionMask,collisionLayer) {
 | 
					 | 
				
			||||||
      var grid = obj.grid, gridCell, col;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for(var y = grid.Y1;y <= grid.Y2;y++) {
 | 
					 | 
				
			||||||
        if(this.grid[y]) {
 | 
					 | 
				
			||||||
          for(var x = grid.X1;x <= grid.X2;x++) {
 | 
					 | 
				
			||||||
            gridCell = this.grid[y][x];
 | 
					 | 
				
			||||||
            if(gridCell) { 
 | 
					 | 
				
			||||||
              col = Q._detect(gridCell,this._gridCellCheck,this,obj,collisionMask);
 | 
					 | 
				
			||||||
              if(col) { return col; }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    collisionLayer: function(layer) {
 | 
					 | 
				
			||||||
      this._collisionLayer = layer;
 | 
					 | 
				
			||||||
      return this.insert(layer);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    search: function(obj,collisionMask) {
 | 
					 | 
				
			||||||
      var col;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      collisionMask = collisionMask || (obj.p && obj.p.collisionMask);
 | 
					 | 
				
			||||||
      if(this._collisionLayer && (this._collisionLayer.p.type & collisionMask)) {
 | 
					 | 
				
			||||||
        col = this._collisionLayer.collide(obj);
 | 
					 | 
				
			||||||
        if(col) { return col; }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      col = this.gridTest(obj,collisionMask,this._collisionLayer);
 | 
					 | 
				
			||||||
      return col;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _locateObj: {
 | 
					 | 
				
			||||||
      p: { 
 | 
					 | 
				
			||||||
        x: 0,
 | 
					 | 
				
			||||||
        y: 0,
 | 
					 | 
				
			||||||
				cx: 0,
 | 
					 | 
				
			||||||
				cy: 0,
 | 
					 | 
				
			||||||
        w: 1,
 | 
					 | 
				
			||||||
        h: 1
 | 
					 | 
				
			||||||
      }, grid: {}
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    locate: function(x,y,collisionMask) {
 | 
					 | 
				
			||||||
      var col = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this._locateObj.p.x = x;
 | 
					 | 
				
			||||||
      this._locateObj.p.y = y;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.regrid(this._locateObj,true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(this._collisionLayer && (this._collisionLayer.p.type & collisionMask)) {
 | 
					 | 
				
			||||||
        col = this._collisionLayer.collide(this._locateObj);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(!col) { 
 | 
					 | 
				
			||||||
        col = this.gridTest(this._locateObj,collisionMask,this._collisionLayer);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(col && col.obj) {
 | 
					 | 
				
			||||||
        return col.obj;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    collide: function(obj,options) {
 | 
					 | 
				
			||||||
      var col, col2, collisionMask, 
 | 
					 | 
				
			||||||
          maxCol, curCol, skipEvents;
 | 
					 | 
				
			||||||
      if(Q._isObject(options)) {
 | 
					 | 
				
			||||||
        collisionMask = options.collisionMask;
 | 
					 | 
				
			||||||
        maxCol = options.maxCol;
 | 
					 | 
				
			||||||
        skipEvents = options.skipEvents;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        collisionMask = options;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      collisionMask = collisionMask  || (obj.p && obj.p.collisionMask);
 | 
					 | 
				
			||||||
      maxCol = maxCol || 3;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      curCol = maxCol;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.regrid(obj);
 | 
					 | 
				
			||||||
      if(this._collisionLayer && (this._collisionLayer.p.type & collisionMask)) {
 | 
					 | 
				
			||||||
        while(curCol > 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<len;i++) {              
 | 
					 | 
				
			||||||
        item = items[i];
 | 
					 | 
				
			||||||
        // If set to visible only, don't step if set to visibleOnly
 | 
					 | 
				
			||||||
        if(!isContainer && (item.p.visibleOnly && item.mark < this.time)) { continue; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(isContainer || !item.container) { 
 | 
					 | 
				
			||||||
          item.update(dt);
 | 
					 | 
				
			||||||
          Q._generateCollisionPoints(item);
 | 
					 | 
				
			||||||
          this.regrid(item);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    step:function(dt) {
 | 
					 | 
				
			||||||
      if(this.paused) { return false; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.time += dt;
 | 
					 | 
				
			||||||
      this.markSprites(this.items,this.time);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.trigger("prestep",dt);
 | 
					 | 
				
			||||||
      this.updateSprites(this.items,dt);
 | 
					 | 
				
			||||||
      this.trigger("step",dt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(this.removeList.length > 0) {
 | 
					 | 
				
			||||||
        for(var i=0,len=this.removeList.length;i<len;i++) {
 | 
					 | 
				
			||||||
          this.forceRemove(this.removeList[i]);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.removeList.length = 0;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.trigger('poststep',dt);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    hide: function() {
 | 
					 | 
				
			||||||
      this.hidden = true;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    show: function() {
 | 
					 | 
				
			||||||
      this.hidden = false;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    stop: function() {
 | 
					 | 
				
			||||||
      this.hide();
 | 
					 | 
				
			||||||
      this.pause();
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    start: function() {
 | 
					 | 
				
			||||||
      this.show();
 | 
					 | 
				
			||||||
      this.unpause();
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    render: function(ctx) {
 | 
					 | 
				
			||||||
      if(this.hidden) { return false; }
 | 
					 | 
				
			||||||
      if(this.options.sort) {
 | 
					 | 
				
			||||||
        this.items.sort(this.options.sort);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      this.trigger("prerender",ctx);
 | 
					 | 
				
			||||||
      this.trigger("beforerender",ctx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for(var i=0,len=this.items.length;i<len;i++) {              
 | 
					 | 
				
			||||||
        var item = this.items[i];
 | 
					 | 
				
			||||||
        // Don't render sprites with containers (sprites do that themselves)
 | 
					 | 
				
			||||||
        // Also don't render if not onscreen
 | 
					 | 
				
			||||||
        if(!item.container && item.mark >= 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<len;i++) {
 | 
					 | 
				
			||||||
        callback.call(this.items[i],arguments[1],arguments[2]);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return this;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    invoke: function(funcName) {
 | 
					 | 
				
			||||||
      for(var i=0,len=this.items.length;i<len;i++) {              
 | 
					 | 
				
			||||||
        this.items[i][funcName].call(
 | 
					 | 
				
			||||||
          this.items[i],arguments[1],arguments[2]
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return this;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    trigger: function(name,params) {
 | 
					 | 
				
			||||||
      this.invoke("trigger",name,params);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    destroy: function() {
 | 
					 | 
				
			||||||
      this.invoke("destroy");
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect: function(func) {
 | 
					 | 
				
			||||||
      for(var i = 0,val=null, len=this.items.length; i < len; i++) {
 | 
					 | 
				
			||||||
        if(func.call(this.items[i],arguments[1],arguments[2])) {
 | 
					 | 
				
			||||||
          return this.items[i];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    identify: function(func) {
 | 
					 | 
				
			||||||
      var result = null;
 | 
					 | 
				
			||||||
      for(var i = 0,val=null, len=this.items.length; i < len; i++) {
 | 
					 | 
				
			||||||
        if(result = func.call(this.items[i],arguments[1],arguments[2])) {
 | 
					 | 
				
			||||||
          return result;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // This hidden utility method extends
 | 
					 | 
				
			||||||
    // and object's properties with a source object.
 | 
					 | 
				
			||||||
    // Used by the p method to set properties.
 | 
					 | 
				
			||||||
    _pObject: function(source) {
 | 
					 | 
				
			||||||
      Q._extend(this.p,source);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _pSingle: function(property,value) {
 | 
					 | 
				
			||||||
      this.p[property] = value;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    set: function(property, value) {
 | 
					 | 
				
			||||||
      // Is value undefined
 | 
					 | 
				
			||||||
      if(value === void 0) {
 | 
					 | 
				
			||||||
        this.each(this._pObject,property);
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        this.each(this._pSingle,property,value);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      return this;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    at: function(idx) {
 | 
					 | 
				
			||||||
      return this.items[idx];
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    first: function() {
 | 
					 | 
				
			||||||
      return this.items[0];
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    last: function() {
 | 
					 | 
				
			||||||
      return this.items[this.items.length-1];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Maybe add support for different types
 | 
					 | 
				
			||||||
  // entity - active collision detection
 | 
					 | 
				
			||||||
  //  particle - no collision detection, no adding components to lists / etc
 | 
					 | 
				
			||||||
  //
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Q("Player").invoke("shimmer); - needs to return a selector
 | 
					 | 
				
			||||||
  // Q(".happy").invoke("sasdfa",'fdsafas',"fasdfas");
 | 
					 | 
				
			||||||
  // Q("Enemy").p({ a: "asdfasf"  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.select = function(selector,scope) {
 | 
					 | 
				
			||||||
    scope = (scope === void 0) ? Q.activeStage : scope;
 | 
					 | 
				
			||||||
    scope = Q.stage(scope);
 | 
					 | 
				
			||||||
    if(Q._isNumber(selector)) {
 | 
					 | 
				
			||||||
      return scope.index[selector];
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      return new Q.StageSelector(scope,selector);
 | 
					 | 
				
			||||||
      // check if is array
 | 
					 | 
				
			||||||
      // check is has any commas
 | 
					 | 
				
			||||||
         // split into arrays
 | 
					 | 
				
			||||||
      // find each of the classes
 | 
					 | 
				
			||||||
      // find all the instances of a specific class
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.stage = function(num) {
 | 
					 | 
				
			||||||
    // Use activeStage is num is undefined
 | 
					 | 
				
			||||||
    num = (num === void 0) ? Q.activeStage : num;
 | 
					 | 
				
			||||||
    return Q.stages[num];
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.stageScene = function(scene,num,options) {
 | 
					 | 
				
			||||||
    // If it's a string, find a registered scene by that name
 | 
					 | 
				
			||||||
    if(Q._isString(scene)) {
 | 
					 | 
				
			||||||
      scene = Q.scene(scene);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // If the user skipped the num arg and went straight to options,
 | 
					 | 
				
			||||||
    // swap the two and grab a default for num
 | 
					 | 
				
			||||||
    if(Q._isObject(num)) {
 | 
					 | 
				
			||||||
      options = num;
 | 
					 | 
				
			||||||
      num = Q._popProperty(options,"stage") || (scene && scene.opts.stage) || 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Clone the options arg to prevent modification
 | 
					 | 
				
			||||||
    options = Q._clone(options);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Grab the stage class, pulling from options, the scene default, or use
 | 
					 | 
				
			||||||
    // the default stage
 | 
					 | 
				
			||||||
    var StageClass = (Q._popProperty(options,"stageClass")) || 
 | 
					 | 
				
			||||||
                     (scene && scene.opts.stageClass) || Q.Stage;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Figure out which stage to use
 | 
					 | 
				
			||||||
    num = Q._isUndefined(num) ? ((scene && scene.opts.stage) || 0) : num;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Clean up an existing stage if necessary
 | 
					 | 
				
			||||||
    if(Q.stages[num]) {
 | 
					 | 
				
			||||||
      Q.stages[num].destroy();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Make this this the active stage and initialize the stage,
 | 
					 | 
				
			||||||
    // calling loadScene to popuplate the stage if we have a scene.
 | 
					 | 
				
			||||||
    Q.activeStage = num;
 | 
					 | 
				
			||||||
    var stage = Q.stages[num] = new StageClass(scene,options);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Load an assets object array
 | 
					 | 
				
			||||||
    if(stage.options.asset) {
 | 
					 | 
				
			||||||
      stage.loadAssets(stage.options.asset);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(scene) {
 | 
					 | 
				
			||||||
      stage.loadScene();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    Q.activeStage = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // If there's no loop active, run the default stageGameLoop
 | 
					 | 
				
			||||||
    if(!Q.loop) {
 | 
					 | 
				
			||||||
      Q.gameLoop(Q.stageGameLoop);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Finally return the stage to the user for use if needed
 | 
					 | 
				
			||||||
    return stage;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.stageGameLoop = function(dt) {
 | 
					 | 
				
			||||||
    var i,len,stage;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(dt < 0) { dt = 1.0/60; }
 | 
					 | 
				
			||||||
    if(dt > 1/15) { dt  = 1.0/15; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for(i =0,len=Q.stages.length;i<len;i++) {
 | 
					 | 
				
			||||||
      Q.activeStage = i;
 | 
					 | 
				
			||||||
      stage = Q.stage();
 | 
					 | 
				
			||||||
      if(stage) {
 | 
					 | 
				
			||||||
        stage.step(dt);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(Q.ctx) { Q.clear(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for(i =0,len=Q.stages.length;i<len;i++) {
 | 
					 | 
				
			||||||
      Q.activeStage = i;
 | 
					 | 
				
			||||||
      stage = Q.stage();
 | 
					 | 
				
			||||||
      if(stage) {
 | 
					 | 
				
			||||||
        stage.render(Q.ctx);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Q.activeStage = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(Q.input && Q.ctx) { Q.input.drawCanvas(Q.ctx); }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.clearStage = function(num) {
 | 
					 | 
				
			||||||
    if(Q.stages[num]) { 
 | 
					 | 
				
			||||||
      Q.stages[num].destroy(); 
 | 
					 | 
				
			||||||
      Q.stages[num] = null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.clearStages = function() {
 | 
					 | 
				
			||||||
    for(var i=0,len=Q.stages.length;i<len;i++) {
 | 
					 | 
				
			||||||
      if(Q.stages[i]) { Q.stages[i].destroy(); }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    Q.stages.length = 0;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,434 +0,0 @@
 | 
				
			||||||
/*global Quintus:false */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
Quintus HTML5 Game Engine - Sprites Module
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
The code in `quintus_sprites.js` defines the `Quintus.Sprites` module, which
 | 
					 | 
				
			||||||
add support for sprite sheets and the base sprite class.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Most games will include at a minimum `Quintus.Sprites` and `Quintus.Scenes`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@module Quintus.Sprites
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Quintus Sprites Module Class
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @class Quintus.Sprites
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
Quintus.Sprites = function(Q) {
 | 
					 | 
				
			||||||
 
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   *
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Create a new sprite sheet
 | 
					 | 
				
			||||||
   Options:
 | 
					 | 
				
			||||||
    tileW - tile width
 | 
					 | 
				
			||||||
    tileH - tile height
 | 
					 | 
				
			||||||
    w     - width of the sprite block
 | 
					 | 
				
			||||||
    h     - height of the sprite block
 | 
					 | 
				
			||||||
    sx    - start x
 | 
					 | 
				
			||||||
    sy    - start y
 | 
					 | 
				
			||||||
    cols  - number of columns per row
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @class SpriteSheet
 | 
					 | 
				
			||||||
  @for Quintus.Sprites
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
  Q.Class.extend("SpriteSheet",{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     @constructor
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
    init: function(name, asset,options) {
 | 
					 | 
				
			||||||
      if(!Q.asset(asset)) { throw "Invalid Asset:" + asset; }
 | 
					 | 
				
			||||||
      Q._extend(this,{
 | 
					 | 
				
			||||||
        name: name,
 | 
					 | 
				
			||||||
        asset: asset,
 | 
					 | 
				
			||||||
        w: Q.asset(asset).width,
 | 
					 | 
				
			||||||
        h: Q.asset(asset).height,
 | 
					 | 
				
			||||||
        tileW: 64,
 | 
					 | 
				
			||||||
        tileH: 64,
 | 
					 | 
				
			||||||
        sx: 0,
 | 
					 | 
				
			||||||
        sy: 0
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      if(options) { Q._extend(this,options); }
 | 
					 | 
				
			||||||
      // fix for old tilew instead of tileW
 | 
					 | 
				
			||||||
      if(this.tilew) { 
 | 
					 | 
				
			||||||
        this.tileW = this.tilew; 
 | 
					 | 
				
			||||||
        delete this['tilew']; 
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if(this.tileh) { 
 | 
					 | 
				
			||||||
        this.tileH = this.tileh; 
 | 
					 | 
				
			||||||
        delete this['tileh']; 
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.cols = this.cols || 
 | 
					 | 
				
			||||||
                  Math.floor(this.w / this.tileW);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.frames = this.cols * (Math.ceil(this.h/this.tileH));
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fx: function(frame) {
 | 
					 | 
				
			||||||
      return Math.floor((frame % this.cols) * this.tileW + this.sx);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fy: function(frame) {
 | 
					 | 
				
			||||||
      return Math.floor(Math.floor(frame / this.cols) * this.tileH + this.sy);
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    draw: function(ctx, x, y, frame) {
 | 
					 | 
				
			||||||
      if(!ctx) { ctx = Q.ctx; }
 | 
					 | 
				
			||||||
      ctx.drawImage(Q.asset(this.asset),
 | 
					 | 
				
			||||||
                    this.fx(frame),this.fy(frame),
 | 
					 | 
				
			||||||
                    this.tileW, this.tileH,
 | 
					 | 
				
			||||||
                    Math.floor(x),Math.floor(y),
 | 
					 | 
				
			||||||
                    this.tileW, this.tileH);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.sheets = {};
 | 
					 | 
				
			||||||
  Q.sheet = function(name,asset,options) {
 | 
					 | 
				
			||||||
    if(asset) {
 | 
					 | 
				
			||||||
      Q.sheets[name] = new Q.SpriteSheet(name,asset,options);
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      return Q.sheets[name];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.compileSheets = function(imageAsset,spriteDataAsset) {
 | 
					 | 
				
			||||||
    var data = Q.asset(spriteDataAsset);
 | 
					 | 
				
			||||||
    Q._each(data,function(spriteData,name) {
 | 
					 | 
				
			||||||
      Q.sheet(name,imageAsset,spriteData);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.SPRITE_NONE     = 0;
 | 
					 | 
				
			||||||
  Q.SPRITE_DEFAULT  = 1;
 | 
					 | 
				
			||||||
  Q.SPRITE_PARTICLE = 2;
 | 
					 | 
				
			||||||
  Q.SPRITE_ACTIVE   = 4;
 | 
					 | 
				
			||||||
  Q.SPRITE_FRIENDLY = 8;
 | 
					 | 
				
			||||||
  Q.SPRITE_ENEMY    = 16;
 | 
					 | 
				
			||||||
  Q.SPRITE_POWERUP  = 32;
 | 
					 | 
				
			||||||
  Q.SPRITE_UI       = 64;
 | 
					 | 
				
			||||||
  Q.SPRITE_ALL   = 0xFFFF;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q._generatePoints = function(obj,force) {
 | 
					 | 
				
			||||||
    if(obj.p.points && !force) { return; }
 | 
					 | 
				
			||||||
    var p = obj.p,
 | 
					 | 
				
			||||||
        halfW = p.w/2,
 | 
					 | 
				
			||||||
        halfH = p.h/2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    p.points = [ 
 | 
					 | 
				
			||||||
      [ -halfW, -halfH ],
 | 
					 | 
				
			||||||
      [  halfW, -halfH ],
 | 
					 | 
				
			||||||
      [  halfW,  halfH ],
 | 
					 | 
				
			||||||
      [ -halfW,  halfH ]
 | 
					 | 
				
			||||||
      ];
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 Q._generateCollisionPoints = function(obj) {
 | 
					 | 
				
			||||||
    if(!obj.matrix && !obj.refreshMatrix) { return; }
 | 
					 | 
				
			||||||
    if(!obj.c) { obj.c = { points: [] }; }
 | 
					 | 
				
			||||||
    var p = obj.p, c = obj.c;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(!p.moved && 
 | 
					 | 
				
			||||||
       c.origX === p.x &&
 | 
					 | 
				
			||||||
       c.origY === p.y &&
 | 
					 | 
				
			||||||
       c.origScale === p.scale &&
 | 
					 | 
				
			||||||
       c.origScale === p.angle) { 
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    c.origX = p.x;
 | 
					 | 
				
			||||||
    c.origY = p.y;
 | 
					 | 
				
			||||||
    c.origScale = p.scale;
 | 
					 | 
				
			||||||
    c.origAngle = p.angle;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    obj.refreshMatrix();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var container = obj.container || Q._nullContainer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // TODO: see if we care or if it's more 
 | 
					 | 
				
			||||||
    // efficient just to do the calc each time
 | 
					 | 
				
			||||||
    c.x = container.matrix.transformX(p.x,p.y);
 | 
					 | 
				
			||||||
    c.y = container.matrix.transformY(p.x,p.y);
 | 
					 | 
				
			||||||
    c.angle = p.angle + container.c.angle;
 | 
					 | 
				
			||||||
    c.scale = (container.c.scale || 1) * (p.scale || 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var minX = Infinity,
 | 
					 | 
				
			||||||
        minY = Infinity,
 | 
					 | 
				
			||||||
        maxX = -Infinity,
 | 
					 | 
				
			||||||
        maxY = -Infinity;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for(var i=0;i<obj.p.points.length;i++) {
 | 
					 | 
				
			||||||
      if(!obj.c.points[i]) {
 | 
					 | 
				
			||||||
        obj.c.points[i] = [];
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      obj.matrix.transformArr(obj.p.points[i],obj.c.points[i]);
 | 
					 | 
				
			||||||
      var x = obj.c.points[i][0],
 | 
					 | 
				
			||||||
          y = obj.c.points[i][1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if(x < minX) { minX = x; }
 | 
					 | 
				
			||||||
          if(x > 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<this.p.points.length;i++) {
 | 
					 | 
				
			||||||
        ctx.lineTo(this.p.points[i][0],this.p.points[i][1]);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      ctx.lineTo(this.p.points[0][0],this.p.points[0][1]);
 | 
					 | 
				
			||||||
      ctx.stroke();
 | 
					 | 
				
			||||||
      if(Q.debugFill) { ctx.fill(); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      ctx.restore();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(this.c) { 
 | 
					 | 
				
			||||||
        var c = this.c;
 | 
					 | 
				
			||||||
        ctx.save();
 | 
					 | 
				
			||||||
          ctx.globalAlpha = 1;
 | 
					 | 
				
			||||||
          ctx.lineWidth = 2;
 | 
					 | 
				
			||||||
          ctx.strokeStyle = "#FF00FF";
 | 
					 | 
				
			||||||
          ctx.beginPath();
 | 
					 | 
				
			||||||
          ctx.moveTo(c.x - c.cx,       c.y - c.cy);
 | 
					 | 
				
			||||||
          ctx.lineTo(c.x - c.cx + c.w, c.y - c.cy);
 | 
					 | 
				
			||||||
          ctx.lineTo(c.x - c.cx + c.w, c.y - c.cy + c.h);
 | 
					 | 
				
			||||||
          ctx.lineTo(c.x - c.cx      , c.y - c.cy + c.h);
 | 
					 | 
				
			||||||
          ctx.lineTo(c.x - c.cx,       c.y - c.cy);
 | 
					 | 
				
			||||||
          ctx.stroke();
 | 
					 | 
				
			||||||
        ctx.restore();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    update: function(dt) {
 | 
					 | 
				
			||||||
      this.trigger('prestep',dt);
 | 
					 | 
				
			||||||
      if(this.step) { this.step(dt); }
 | 
					 | 
				
			||||||
      this.trigger('step',dt);
 | 
					 | 
				
			||||||
      this.refreshMatrix();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Ugly coupling to stage - workaround?
 | 
					 | 
				
			||||||
      if(this.stage && this.children.length > 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;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -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<touches.length;i++) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(var stageIdx=0;stageIdx < touchStage.length;stageIdx++) {
 | 
					 | 
				
			||||||
          var touch = touches[i],
 | 
					 | 
				
			||||||
              stage = Q.stage(touchStage[stageIdx]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if(!stage) { continue; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          touch.identifier = touch.identifier || 0;
 | 
					 | 
				
			||||||
          var pos = this.normalizeTouch(touch,stage);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          stage.regrid(pos,true);
 | 
					 | 
				
			||||||
          var col = stage.search(pos,touchType), obj;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if(col || stageIdx === touchStage.length - 1) {
 | 
					 | 
				
			||||||
            obj = col && col.obj;
 | 
					 | 
				
			||||||
            pos.obj = obj;
 | 
					 | 
				
			||||||
            this.trigger("touch",pos);
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          if(obj && !this.touchedObjects[obj]) {
 | 
					 | 
				
			||||||
            this.activeTouches[touch.identifier] = {
 | 
					 | 
				
			||||||
              x: pos.p.px,
 | 
					 | 
				
			||||||
              y: pos.p.py,
 | 
					 | 
				
			||||||
              origX: obj.p.x,
 | 
					 | 
				
			||||||
              origY: obj.p.y,
 | 
					 | 
				
			||||||
              sx: pos.p.ox,
 | 
					 | 
				
			||||||
              sy: pos.p.oy,
 | 
					 | 
				
			||||||
              identifier: touch.identifier,
 | 
					 | 
				
			||||||
              obj: obj,
 | 
					 | 
				
			||||||
              stage: stage
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            this.touchedObjects[obj.p.id] = true;
 | 
					 | 
				
			||||||
            obj.trigger('touch', this.activeTouches[touch.identifier]);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      //e.preventDefault();
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    drag: function(e) {
 | 
					 | 
				
			||||||
      var touches = e.changedTouches || [ e ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for(var i=0;i<touches.length;i++) {
 | 
					 | 
				
			||||||
        var touch = touches[i];
 | 
					 | 
				
			||||||
        touch.identifier = touch.identifier || 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var active = this.activeTouches[touch.identifier],
 | 
					 | 
				
			||||||
            stage = active && active.stage;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(active) {
 | 
					 | 
				
			||||||
          var pos = this.normalizeTouch(touch,stage);
 | 
					 | 
				
			||||||
          active.x = pos.p.px;
 | 
					 | 
				
			||||||
          active.y = pos.p.py;
 | 
					 | 
				
			||||||
          active.dx = pos.p.ox - active.sx;
 | 
					 | 
				
			||||||
          active.dy = pos.p.oy - active.sy;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          active.obj.trigger('drag', active);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      e.preventDefault();
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    touchEnd: function(e) {
 | 
					 | 
				
			||||||
      var touches = e.changedTouches || [ e ];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for(var i=0;i<touches.length;i++) {
 | 
					 | 
				
			||||||
        var touch = touches[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        touch.identifier = touch.identifier || 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        var active = this.activeTouches[touch.identifier];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(active) {
 | 
					 | 
				
			||||||
          active.obj.trigger('touchEnd', active);
 | 
					 | 
				
			||||||
          delete this.touchedObjects[active.obj.p.id];
 | 
					 | 
				
			||||||
          this.activeTouches[touch.identifier] = null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      e.preventDefault();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.touch = function(type,stage) {
 | 
					 | 
				
			||||||
    Q.untouch();
 | 
					 | 
				
			||||||
    touchType = type || Q.SPRITE_UI;
 | 
					 | 
				
			||||||
    touchStage = stage || [2,1,0];
 | 
					 | 
				
			||||||
    if(!Q._isArray(touchStage)) {
 | 
					 | 
				
			||||||
      touchStage = [touchStage];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(!Q._touch) {
 | 
					 | 
				
			||||||
      Q.touchInput = new Q.TouchSystem();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return Q;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.untouch = function() {
 | 
					 | 
				
			||||||
    if(Q.touchInput) {
 | 
					 | 
				
			||||||
      Q.touchInput.destroy();
 | 
					 | 
				
			||||||
      delete Q['touchInput'];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return Q;
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,430 +0,0 @@
 | 
				
			||||||
/*global Quintus:false */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Quintus.UI = function(Q) {
 | 
					 | 
				
			||||||
  if(Q._isUndefined(Quintus.Touch)) {
 | 
					 | 
				
			||||||
    throw "Quintus.UI requires Quintus.Touch Module";
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.UI = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Draw a rounded rectangle centered on 0,0
 | 
					 | 
				
			||||||
  Q.UI.roundRect = function(ctx, rect) {
 | 
					 | 
				
			||||||
    ctx.beginPath();
 | 
					 | 
				
			||||||
    ctx.moveTo(-rect.cx + rect.radius, -rect.cy);
 | 
					 | 
				
			||||||
    ctx.lineTo(-rect.cx + rect.w - rect.radius, -rect.cy);
 | 
					 | 
				
			||||||
    ctx.quadraticCurveTo(-rect.cx + rect.w, -rect.cy, -rect.cx + rect.w, -rect.cy + rect.radius);
 | 
					 | 
				
			||||||
    ctx.lineTo(-rect.cx + rect.w, -rect.cy + rect.h - rect.radius);
 | 
					 | 
				
			||||||
    ctx.quadraticCurveTo(-rect.cx + rect.w, 
 | 
					 | 
				
			||||||
                         -rect.cy + rect.h, 
 | 
					 | 
				
			||||||
                         -rect.cx + rect.w - rect.radius, 
 | 
					 | 
				
			||||||
                         -rect.cy + rect.h);
 | 
					 | 
				
			||||||
    ctx.lineTo(-rect.cx + rect.radius, -rect.cy + rect.h);
 | 
					 | 
				
			||||||
    ctx.quadraticCurveTo(-rect.cx, -rect.cy + rect.h, -rect.cx, -rect.cy + rect.h - rect.radius);
 | 
					 | 
				
			||||||
    ctx.lineTo(-rect.cx, -rect.cy + rect.radius);
 | 
					 | 
				
			||||||
    ctx.quadraticCurveTo(-rect.cx, -rect.cy, -rect.cx + rect.radius, -rect.cy);
 | 
					 | 
				
			||||||
    ctx.closePath();
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.UI.Container = Q.Sprite.extend("UI.Container", {
 | 
					 | 
				
			||||||
    init: function(p,defaults) {
 | 
					 | 
				
			||||||
      var adjustedP = Q._clone(p||{}),
 | 
					 | 
				
			||||||
          match;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(p && Q._isString(p.w) && (match = p.w.match(/^[0-9]+%$/))) {
 | 
					 | 
				
			||||||
        adjustedP.w = parseInt(p.w,10) * Q.width / 100;         
 | 
					 | 
				
			||||||
        adjustedP.x = Q.width/2 - adjustedP.w/2;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(p && Q._isString(p.h) && (match = p.h.match(/^[0-9]+%$/))) {
 | 
					 | 
				
			||||||
        adjustedP.h = parseInt(p.h,10) * Q.height / 100;         
 | 
					 | 
				
			||||||
        adjustedP.y = Q.height /2 - adjustedP.h/2;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this._super(Q._defaults(adjustedP,defaults),{
 | 
					 | 
				
			||||||
        opacity: 1,
 | 
					 | 
				
			||||||
        hidden: false, // Set to true to not show the container
 | 
					 | 
				
			||||||
        fill:   null, // Set to color to add background
 | 
					 | 
				
			||||||
        highlight:   null, // Set to color to for button
 | 
					 | 
				
			||||||
        radius: 5, // Border radius
 | 
					 | 
				
			||||||
        stroke: "#000", 
 | 
					 | 
				
			||||||
        border: false, // Set to a width to show a border
 | 
					 | 
				
			||||||
        shadow: false, // Set to true or a shadow offest
 | 
					 | 
				
			||||||
        shadowColor: false, // Set to a rgba value for the shadow
 | 
					 | 
				
			||||||
        type: Q.SPRITE_NONE
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    insert: function(obj) {
 | 
					 | 
				
			||||||
      this.stage.insert(obj,this);
 | 
					 | 
				
			||||||
      return obj;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fit: function(paddingY,paddingX) {
 | 
					 | 
				
			||||||
      if(this.children.length === 0) { return; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(paddingY === void 0) { paddingY = 0; }
 | 
					 | 
				
			||||||
      if(paddingX === void 0) { paddingX = paddingY; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      var minX = Infinity,
 | 
					 | 
				
			||||||
          minY = Infinity,
 | 
					 | 
				
			||||||
          maxX = -Infinity,
 | 
					 | 
				
			||||||
          maxY = -Infinity;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      for(var i =0;i < this.children.length;i++) {
 | 
					 | 
				
			||||||
        var obj = this.children[i];
 | 
					 | 
				
			||||||
        var minObjX = obj.p.x - obj.p.cx,
 | 
					 | 
				
			||||||
            minObjY = obj.p.y - obj.p.cy,
 | 
					 | 
				
			||||||
            maxObjX = obj.p.x - obj.p.cx + obj.p.w,
 | 
					 | 
				
			||||||
            maxObjY = obj.p.y - obj.p.cy + obj.p.h;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(minObjX < minX) { minX = minObjX; }
 | 
					 | 
				
			||||||
        if(minObjY < minY) { minY = minObjY; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(maxObjX > 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<this.splitLabel.length;i++) {
 | 
					 | 
				
			||||||
        if(this.p.align === 'center') { 
 | 
					 | 
				
			||||||
          ctx.fillText(this.splitLabel[i],0,-this.p.cy + i * this.p.size * 1.2);
 | 
					 | 
				
			||||||
        } else if(this.p.align === 'right') {
 | 
					 | 
				
			||||||
          ctx.fillText(this.splitLabel[i],this.p.cx,-this.p.cy + i * this.p.size * 1.2);
 | 
					 | 
				
			||||||
        } else { 
 | 
					 | 
				
			||||||
          ctx.fillText(this.splitLabel[i],-this.p.cx,-this.p.cy +i * this.p.size * 1.2);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    asset: function() {
 | 
					 | 
				
			||||||
      return this.el;
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    setFont: function(ctx) {
 | 
					 | 
				
			||||||
      ctx.textBaseline = "top";
 | 
					 | 
				
			||||||
      ctx.font= this.font();
 | 
					 | 
				
			||||||
      ctx.fillStyle = this.p.color || "black";
 | 
					 | 
				
			||||||
      ctx.textAlign = this.p.align || "left";
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    font: function() {
 | 
					 | 
				
			||||||
      if(this.fontString) { return this.fontString; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      this.fontString = (this.p.weight || "800") + " " +
 | 
					 | 
				
			||||||
                        (this.p.size || 24) + "px " +
 | 
					 | 
				
			||||||
                        (this.p.family || "Arial");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      return this.fontString;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Q.UI.Button = Q.UI.Container.extend("UI.Button", {
 | 
					 | 
				
			||||||
    init: function(p,callback) {
 | 
					 | 
				
			||||||
      this._super(Q._defaults(p,{
 | 
					 | 
				
			||||||
        type: Q.SPRITE_UI | Q.SPRITE_DEFAULT
 | 
					 | 
				
			||||||
      }));
 | 
					 | 
				
			||||||
      if(this.p.label && (!this.p.w || !this.p.h)) {
 | 
					 | 
				
			||||||
        Q.ctx.save();
 | 
					 | 
				
			||||||
        this.setFont(Q.ctx);
 | 
					 | 
				
			||||||
        var metrics = Q.ctx.measureText(this.p.label);
 | 
					 | 
				
			||||||
        Q.ctx.restore();
 | 
					 | 
				
			||||||
        if(!this.p.h) {  this.p.h = 24 + 20; }
 | 
					 | 
				
			||||||
        if(!this.p.w) { this.p.w = metrics.width + 20; }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if(isNaN(this.p.cx)) { this.p.cx = this.p.w / 2; }
 | 
					 | 
				
			||||||
      if(isNaN(this.p.cy)) { this.p.cy = this.p.h / 2; }
 | 
					 | 
				
			||||||
      this.callback = callback;
 | 
					 | 
				
			||||||
      this.on('touch',this,"highlight");
 | 
					 | 
				
			||||||
      this.on('touchEnd',this,"push");
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    highlight: function() {
 | 
					 | 
				
			||||||
      if(!this.sheet() || this.sheet().frames > 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<this.children.length;i++) {
 | 
					 | 
				
			||||||
        totalHeight += this.children[i].p.h || 0;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Center?
 | 
					 | 
				
			||||||
      var totalSepartion = this.p.h - totalHeight;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Make sure all elements have the same space between them
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
		Reference in a new issue