docs: function() {
                  var drawTimeStart,
                      dt,
                      lastFrameTime,
                      loops = 0;
  
                  var currentTime = Date.now();
                  if (endTime > 0)
                      Crafty.trigger("MeasureWaitTime", currentTime - endTime);
  
                  // If we're currently ahead of the current time, we need to wait until we're not!
                  if (gameTime + timeSlip >= currentTime) {
                      endTime = currentTime;
                      return;
                  }
  
                  var netTimeStep = currentTime - (gameTime + timeSlip);
                  // We try to keep up with the target FPS by processing multiple frames per render
                  // If we're hopelessly behind, stop trying to catch up.
                  if (netTimeStep > milliSecPerFrame * 20) {
                      //gameTime = currentTime - milliSecPerFrame;
                      timeSlip += netTimeStep - milliSecPerFrame;
                      netTimeStep = milliSecPerFrame;
                  }
  
                  // Set up how time is incremented
                  if (mode === "fixed") {
                      loops = Math.ceil(netTimeStep / milliSecPerFrame);
                      // maxFramesPerStep adjusts how willing we are to delay drawing in order to keep at the target FPS
                      loops = Math.min(loops, maxFramesPerStep);
                      dt = milliSecPerFrame;
                  } else if (mode === "variable") {
                      loops = 1;
                      dt = netTimeStep;
                      // maxTimestep is the maximum time to be processed in a frame.  (Large dt => unstable physics)
                      dt = Math.min(dt, maxTimestep);
                  } else if (mode === "semifixed") {
                      loops = Math.ceil(netTimeStep / maxTimestep);
                      dt = netTimeStep / loops;
                  }
  
                  // Process frames, incrementing the game clock with each frame.
                  // dt is determined by the mode
                  for (var i = 0; i < loops; i++) {
                      lastFrameTime = currentTime;
  
                      var frameData = {
                          frame: frame++,
                          dt: dt,
                          gameTime: gameTime
                      };
  
                      // Event that happens before "UpdateFrame",
                      // e.g. for setting-up movement in response to user input for the next "UpdateFrame" event
                      Crafty.trigger("EnterFrame", frameData);
                      // Everything that changes over time hooks into this event
                      Crafty.trigger("UpdateFrame", frameData);
                      // Event that happens after "UpdateFrame",
                      // e.g. for resolivng collisions applied through movement during "UpdateFrame" events
                      Crafty.trigger("ExitFrame", frameData);
                      gameTime += dt;
  
                      currentTime = Date.now();
                      Crafty.trigger(
                          "MeasureFrameTime",
                          currentTime - lastFrameTime
                      );
                  }
  
                  //If any frames were processed, render the results
                  if (loops > 0) {
                      drawTimeStart = currentTime;
                      Crafty.trigger("PreRender"); // Pre-render setup opportunity
                      Crafty.trigger("RenderScene");
                      Crafty.trigger("PostRender"); // Post-render cleanup opportunity
                      currentTime = Date.now();
                      Crafty.trigger(
                          "MeasureRenderTime",
                          currentTime - drawTimeStart
                      );
                  }
  
                  endTime = currentTime;
              }