docs: function draw() {
  			//if no objects have been changed, stop
  			if (!changed_objs.length && !dom.length) return;
  
  			var i = 0, l = changed_objs.length, k = dom.length, rect, q,
  				j, len, obj, ent, ctx = Crafty.canvas.context;
  
  			//loop over all DOM elements needing updating
  			for (; i < k; ++i) {
  				dom[i].draw()._changed = false;
  			}
  			//reset DOM array
              dom.length = 0;
  
  			//again, stop if no canvas components have changed
  			if (!l) { return; }
  
  			//if the amount of changed objects is over 60% of the total objects
  			//do the naive method redrawing
  			// TODO: I'm not sure this condition really makes that much sense!
  			if (l / this.total2D > 0.6 ) {
  				this.drawAll();
  				rectManager.clean()
  				return;
  			}
  
  			// Calculate dirty_rects from all changed objects, then merge some overlapping regions together
  			for  (i=0; i<l; i++){
  				rectManager.createDirty(changed_objs[i])
  			}
  			dirty_rects = this.mergeSet(dirty_rects);
  
  			
  			l = dirty_rects.length;
  			var dupes = [], objs = []
  			// For each dirty rectangle, find entities near it, and draw the overlapping ones
  			for (i = 0; i < l; ++i) { //loop over every dirty rect
  				rect = dirty_rects[i];
  				dupes.length=0;
  				objs.length=0;
  				if (!rect) continue;
  
  				//search for ents under dirty rect
  				q = Crafty.map.search(rect, false); 
  
  				//clear the rect from the main canvas
  				ctx.clearRect(rect._x, rect._y, rect._w, rect._h);
  
  				//Then clip drawing region to dirty rectangle
  				ctx.save();
  				ctx.beginPath();
  				ctx.rect(rect._x, rect._y, rect._w, rect._h);
  				ctx.clip();
  
  				// Loop over found objects removing dupes and adding visible canvas objects to array
  				for (j = 0, len = q.length; j < len; ++j) {
  					obj = q[j];
        
  					if (dupes[obj[0]] || !obj._visible || !obj.__c.Canvas)
  						continue;
  					dupes[obj[0]] = true;
  					objs.push(obj);
  				}
  
  				// Sort objects by z level
  				objs.sort(zsort)
  				
  				// Then draw each object in that order
  				for (j = 0, len = objs.length; j < len; ++j) {
  					obj = objs[j]
  					var area = obj._mbr || obj;
  					if (rectManager.overlap(area, rect))
  						obj.draw()
  					obj._changed = false
  				}
  
  				
  				// Close rectangle clipping
  				ctx.closePath();
  				ctx.restore();
  
  			}
  
  			// Draw dirty rectangles for debugging, if that flag is set
  			if (Crafty.DrawManager.debugDirty === true){
  				ctx.strokeStyle = 'red';
  		        for (i = 0, l=dirty_rects.length; i < l; ++i) { 
  		            rect = dirty_rects[i];
  		            ctx.strokeRect(rect._x,rect._y,rect._w,rect._h)
  		        } 
          	}
              //Clean up lists etc
              rectManager.clean()
  
  		}