/*更为复杂的请参考6.3.2滚动的小球例子和6.10节炸弹的例子,精灵动画需要很好的结合下面的三个方法:
    【1】update:精灵对象的方法
    【2】advance:精灵表绘制器的方法
    【3】requestNextAnimationFrame:调用
*/
var spritesheet = new Image(),
    runnerCells = [
      { left: 0,   top: 0, width: 47, height: 64 },
      { left: 55,  top: 0, width: 44, height: 64 },
      { left: 107, top: 0, width: 39, height: 64 },
      { left: 152, top: 0, width: 46, height: 64 },
      { left: 208, top: 0, width: 49, height: 64 },
      { left: 265, top: 0, width: 46, height: 64 },
      { left: 320, top: 0, width: 42, height: 64 },
      { left: 380, top: 0, width: 35, height: 64 },
      { left: 425, top: 0, width: 35, height: 64 },
    ];

    // Behaviors.................................................
    runInPlace = {
       lastAdvance: 0,
       PAGEFLIP_INTERVAL: 100,

       execute: function (sprite, context, time) {
          if (time - this.lastAdvance > this.PAGEFLIP_INTERVAL) {
             sprite.painter.advance();
             this.lastAdvance = time;
          }
       }
    },

    moveLeftToRight = {
       lastMove: 0,
       
       execute: function (sprite, context, time) {
         if (this.lastMove !== 0) {
           sprite.left -= sprite.velocityX *
                          ((time - this.lastMove) / 1000); 

           if (sprite.left < 0) {
              sprite.left = canvas.width;
           }
         }
         this.lastMove = time;
       }
    },

    // Sprite....................................................

    sprite = new Sprite('runner',
                        new SpriteSheetPainter(runnerCells),
                        [ runInPlace, moveLeftToRight ]);//这个动作可以有多个,也可以添加用户键盘行为
    sprite.velocityX = 50;  // pixels/second                    
                        
function animate(time) {
   context.clearRect(0,0,canvas.width,canvas.height);
   sprite.update(context, time);
   sprite.paint(context); 
   //一般精灵的状态等的变化都要放在此条语句的上面,防止发生不一致的情况
   window.requestNextAnimationFrame(animate);
}
window.requestNextAnimationFrame(animate);



//..................................................................................................
    ANIMATION_DURATION = 100,
    pushTimer = new AnimationTimer(ANIMATION_DURATION),

    // Move ball behavior............触发一次动作后,借用AnimationTimer对象来判断其执行时间是否完成............................

    moveBall = {
      lastTime: undefined,
       
      resetBall: function () {
         ball.left = LEDGE_LEFT + LEDGE_WIDTH/2 - BALL_RADIUS;
         ball.top  = LEDGE_TOP - BALL_RADIUS*2;
      },

      execute: function (sprite, context, time) {
         var timerElapsed = pushTimer.getElapsedTime(),
             frameElapsed;
         
         if (pushTimer.isRunning() && this.lastTime !== undefined) {
            frameElapsed = timerElapsed - this.lastTime;
            
            if (arrow === LEFT) ball.left -= ball.velocityX * (frameElapsed/1000);
            else                ball.left += ball.velocityX * (frameElapsed/1000);

            if ((isBallOnLedge() && pushTimer.isOver()) || ! isBallOnLedge()) 
                  pushTimer.stop();

            if ( ! isBallOnLedge())
               this.resetBall();
         }
         this.lastTime = timerElapsed;
      }
    },