<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      【CSON原創】HTML5游戲框架cnGameJS開發實錄(動畫篇)

      返回目錄 

       在游戲中,游戲角色的動畫效果是一個游戲必不可少的一部分。這節我們以構造超級馬里奧的角色為例,講解cnGameJS里動畫的實現。

      1.原理:

        一個動畫如果要實現一連串動作,我們可以把每個動作的快照保留起來,并放在一個大圖上面,然后每次幀更新的時候,就在每個動作的快照之間循環顯示,最終得出一個動畫。因此我們首先要準備一個類似下面的這種圖片:

        看到不?把每個動作放在圖片的不同位置上,之后就可以通過改變顯示位置實現動畫效果了。

        當cnGameJS調用start方法開始游戲后,將會調用傳入的gameObj的initialize方法進行初始化,并且生成一個游戲循環,循環里每次調用gameObj的update和draw方法。(詳見(HTML5游戲框架cnGameJS開發實錄(資源加載篇)和 HTML5游戲框架cnGameJS開發實錄(游戲循環篇)))因此我們可以把動畫的初始化放在gameObj的initialize中,update和draw分別放在gameObj的update和draw中,實現動畫播放。

      效果:

       


      代碼:

      <body>
      <canvas id="gameCanvas">請使用支持canvas的瀏覽器查看</canvas>
      </body>
      <script src="https://files.cnblogs.com/Cson/cnGame_v1.0.js"></script>
      <script>
      var Src="http://pic002.cnblogs.com/images/2012/273330/2012021312050269.png";
      /* 初始化 */
      cnGame.init(
      'gameCanvas',{width:50,height:60});
      var gameObj={
      initialize:
      function(){
      this.marie=cnGame.SpriteSheet("marie",Src,{frameSize:[50,60],width:150,height:60,loop:true});
      },
      update:
      function(){
      this.marie.update();
      },
      draw:
      function(){
      this.marie.draw();
      }

      }
      cnGame.loader.start([Src],gameObj);
      </script>
       
      2.實現
        正如上面看到的,我們只需要用很少的代碼量,就可以實現一個幀動畫的播放,接下來將介紹cnGameJS里的幀動畫是怎樣封裝的。
        大家很容易可以發現,cnGameJS都遵循一個特定的模式,把對象的階段分為三個:initialize(初始化),update(幀更新)和draw(繪制)。這樣我們可以很方便地把不同功能的代碼寫在對應的階段內。spriteSheet幀動畫也不例外,同樣按照這種模式來寫。
       
        初始化:用戶對一些必要的信息進行設定。
          spriteSheet.prototype={
      /**
      *初始化
      *
      */
      init:function(id,src,options){

      /**
      *默認對象
      *
      */
      var defaultObj={
      x:0,
      y:0,
      width:120,
      height:40,
      frameSize:[40,40],
      frameDuration:100,
      direction:"right", //從左到右
      beginX:0,
      beginY:0,
      loop:false,
      bounce:false
      };
      options=options||{};
      options=cg.core.extend(defaultObj,options);
      this.id=id; //spriteSheet的id
      this.src=src; //圖片地址
      this.x=options.x; //動畫X位置
      this.y=options.y; //動畫Y位置
      this.width=options.width; //圖片的寬度
      this.height=options.height; //圖片的高度
      this.image=cg.loader.loadedImgs[this.src]; //圖片對象
      this.frameSize=options.frameSize; //每幀尺寸
      this.frameDuration=options.frameDuration; //每幀持續時間
      this.direction=options.direction; //讀取幀的方向(從做到右或從上到下)
      this.currentIndex=0; //目前幀索引
      this.beginX=options.beginX; //截取圖片的起始位置X
      this.beginY=options.beginY; //截圖圖片的起始位置Y
      this.loop=options.loop; //是否循環播放
      this.bounce=options.bounce; //是否往返播放
      this.onFinsh=options.onFinsh; //播放完畢后的回調函數
      this.frames=caculateFrames(options); //幀信息集合
      this.now=new Date().getTime(); //當前時間
      this.last=new Date().getTime(); //上一幀開始時間
      },
        
        上面的參數比較多,都是一些對幀動畫屬性的預設置。需要注意的是我們調用了私有方法caculateFrames來計算每個幀的信息,并保存到frames內,為幀繪制做準備。
       
        幀更新:
        在每一幀的更新過程中,我們首先獲取當前時間作為幀的開始時間,并且和上一次幀的開始時間相減,就得出上一次幀的用時。如果用時超過之前設置的每幀的用時,則可以進行幀更新。然后判斷是否循環或者往返播放動畫,按情況更新對應的幀索引。在最終確定幀的索引后,就可以從frames數組中獲取該幀的信息,并返回。
              /**
      *更新幀
      *
      */
      update:function(){

      this.now=new Date().getTime();
      var frames=this.frames;
      if((this.now-this.last)>this.frameDuration){//如果間隔大于幀間間隔,則update
      var currentIndex=this.currentIndex;
      var length=this.frames.length;
      this.last=this.now;

      if(currentIndex>=length-1){
      if(this.loop){ //循環
      return frames[this.currentIndex=0];
      }
      else if(!this.bounce){//沒有循環并且沒有往返滾動,則停止在最后一幀
      this.onFinsh&&this.onFinsh();
      this.onFinsh=undefined;
      return frames[currentIndex];
      }
      }
      if((this.bounce)&&((currentIndex>=length-1&&path>0)||(currentIndex<=0&&path<0))){ //往返
      path*=(-1);
      }
      this.currentIndex+=path;

      }
      return frames[this.currentIndex];
      },

        幀繪制:

        在幀更新后,已經獲取到當前幀的索引,因此draw方法就可以從保存所有幀信息的frames獲取到當前幀的信息(包括圖像截取的起始位置等),從而在指定位置截取大圖片,并畫出該圖片區域的圖像:

              /**
      *在特定位置繪制該幀
      *
      */
      draw:function(){

      var currentFrame=this.getCurrentFrame();
      var width=this.frameSize[0];
      var height=this.frameSize[1];
      cg.context.drawImage(this.image,currentFrame.x,currentFrame.y,width,height,this.x,this.y,width,height);
      }

       

      最后,還提供跳到特定幀等方法。


      動畫模塊所有源碼:

          /**
      *包含多幀圖像的大圖片
      *
      */
      spriteSheet=function(id,src,options){
      if(!(this instanceof arguments.callee)){
      return new arguments.callee(id,src,options);
      }
      this.init(id,src,options);
      }
      spriteSheet.prototype={
      /**
      *初始化
      *
      */
      init:function(id,src,options){

      /**
      *默認對象
      *
      */
      var defaultObj={
      x:0,
      y:0,
      width:120,
      height:40,
      frameSize:[40,40],
      frameDuration:100,
      direction:"right", //從左到右
      beginX:0,
      beginY:0,
      loop:false,
      bounce:false
      };
      options=options||{};
      options=cg.core.extend(defaultObj,options);
      this.id=id; //spriteSheet的id
      this.src=src; //圖片地址
      this.x=options.x; //動畫X位置
      this.y=options.y; //動畫Y位置
      this.width=options.width; //圖片的寬度
      this.height=options.height; //圖片的高度
      this.image=cg.loader.loadedImgs[this.src]; //圖片對象
      this.frameSize=options.frameSize; //每幀尺寸
      this.frameDuration=options.frameDuration; //每幀持續時間
      this.direction=options.direction; //讀取幀的方向(從做到右或從上到下)
      this.currentIndex=0; //目前幀索引
      this.beginX=options.beginX; //截取圖片的起始位置X
      this.beginY=options.beginY; //截圖圖片的起始位置Y
      this.loop=options.loop; //是否循環播放
      this.bounce=options.bounce; //是否往返播放
      this.onFinsh=options.onFinsh; //播放完畢后的回調函數
      this.frames=caculateFrames(options); //幀信息集合
      this.now=new Date().getTime(); //當前時間
      this.last=new Date().getTime(); //上一幀開始時間
      },
      /**
      *更新幀
      *
      */
      update:function(){

      this.now=new Date().getTime();
      var frames=this.frames;
      if((this.now-this.last)>this.frameDuration){//如果間隔大于幀間間隔,則update
      var currentIndex=this.currentIndex;
      var length=this.frames.length;
      this.last=this.now;

      if(currentIndex>=length-1){
      if(this.loop){ //循環
      return frames[this.currentIndex=0];
      }
      else if(!this.bounce){//沒有循環并且沒有往返滾動,則停止在最后一幀
      this.onFinsh&&this.onFinsh();
      this.onFinsh=undefined;
      return frames[currentIndex];
      }
      }
      if((this.bounce)&&((currentIndex>=length-1&&path>0)||(currentIndex<=0&&path<0))){ //往返
      path*=(-1);
      }
      this.currentIndex+=path;

      }
      return frames[this.currentIndex];
      },
      /**
      *跳到特定幀
      *
      */
      index:function(index){
      this.currentIndex=index;
      return this.frames[this.currentIndex];
      },
      /**
      *獲取現時幀
      *
      */
      getCurrentFrame:function(){
      return this.frames[this.currentIndex];
      },
      /**
      *在特定位置繪制該幀
      *
      */
      draw:function(){

      var currentFrame=this.getCurrentFrame();
      var width=this.frameSize[0];
      var height=this.frameSize[1];
      cg.context.drawImage(this.image,currentFrame.x,currentFrame.y,width,height,this.x,this.y,width,height);
      }

      }
      this.SpriteSheet=spriteSheet;

      });



       
        
       

      posted @ 2012-02-14 12:42  Cson  閱讀(5271)  評論(8)    收藏  舉報
      主站蜘蛛池模板: 欧美色欧美亚洲高清在线观看| 久久99九九精品久久久久蜜桃 | 亚洲AV高清一区二区三区尤物| 熟妇人妻一区二区三区四区| 亚洲av色香蕉一区二区| 久久五月丁香激情综合| 日本中文字幕有码在线视频 | 日韩av裸体在线播放| 人妻少妇无码精品专区| 在线高清免费不卡全码| 日本亚洲一区二区精品久久| yyyy在线在片| 日本熟妇XXXX潮喷视频| 亚洲一区二区av在线| 亚洲AV日韩AV综合在线观看| 久女女热精品视频在线观看| 久久精品道一区二区三区| 久久久无码精品午夜| 亚洲精品成人区在线观看| 国内不卡一区二区三区| 洛浦县| 亚洲av色在线播放一区| 亚洲欧美日韩综合久久久| 平顶山市| 国产亚洲另类无码专区| 国产91丝袜在线观看| 92自拍视频爽啪在线观看| 高潮潮喷奶水飞溅视频无码| 久久精品高清一区二区三区| 成人精品一区二区三区四| 精品国产人妻一区二区三区久久 | 国产91麻豆视频免费看| 日本伊人色综合网| 亚洲国产一区二区三区| 国产午夜福利在线视频| 敖汉旗| 亚洲中文字幕人成影院| 亚洲精品成人片在线观看精品字幕| 2019久久久高清日本道| 国产一区二区黄色在线观看| 久久99热成人精品国产|