成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Chrome 小恐龍游戲源碼探究二 -- 讓地面動(dòng)起來(lái)

siberiawolf / 3433人閱讀

摘要:文章首發(fā)于我的博客前言上一篇文章小恐龍游戲源碼探究一繪制靜態(tài)地面中定義了游戲的主體類,并實(shí)現(xiàn)了靜態(tài)地面的繪制。

文章首發(fā)于我的 GitHub 博客
前言

上一篇文章:《Chrome 小恐龍游戲源碼探究一 -- 繪制靜態(tài)地面》 中定義了游戲的主體類 Runner,并實(shí)現(xiàn)了靜態(tài)地面的繪制。這一篇文章中,將實(shí)現(xiàn)效果:1、地面無(wú)限滾動(dòng)。2、剛開(kāi)始地面不動(dòng),按下空格后地面滾動(dòng)。

地面無(wú)限滾動(dòng)

要實(shí)現(xiàn)地面的移動(dòng)就要不斷更新地面的 x 坐標(biāo)。定義如下方法:

HorizonLine.prototype = {
  /**
   * 更新地面的 x 坐標(biāo)
   * @param {Number} pos 地面的位置
   * @param {Number} incre 移動(dòng)距離
   */
  updateXPos: function (pos, incre) {
    var line1 = pos;
    var line2 = pos === 0 ? 1 : 0;

    // 第一段地面向左移動(dòng),第二段地面隨之
    this.xPos[line1] -= incre;
    this.xPos[line2] = this.xPos[line1] + this.dimensions.WIDTH;

    // 第一段地面移出了 canvas
    if (this.xPos[line1] <= -this.dimensions.WIDTH) {
      // 將第一段地面放到 canvas 右側(cè)
      this.xPos[line1] += this.dimensions.WIDTH * 2;
      // 此時(shí)第二段地面的 x 坐標(biāo)剛好和 canvas 的 x 坐標(biāo)對(duì)齊
      this.xPos[line2] = this.xPos[line1] - this.dimensions.WIDTH;
      // 給放到 canvas 后面的地面隨機(jī)地形
      this.sourceXPos[line1] = this.getRandomType() + this.spritePos.x;
    }
  },
  // 獲取隨機(jī)的地形
  getRandomType: function () {
    return Math.random() > this.bumpThreshold ? this.dimensions.WIDTH : 0;
  },
};

其中 updateXPos 實(shí)現(xiàn)了地面 x 坐標(biāo)的更新。當(dāng)?shù)谝欢蔚孛嬉瞥?canvas 時(shí),會(huì)將第一段地面 x 坐標(biāo)乘 2 放到 canvas 后面,然后為其隨機(jī)地形。這時(shí),原來(lái)的第二段地面就變成了第一段地面繼續(xù)向前移動(dòng),以此類推。這樣就實(shí)現(xiàn)了地面的不斷移動(dòng)和更新。

上面的函數(shù)只是實(shí)現(xiàn)了地面移動(dòng)相關(guān)的邏輯,真正讓地面動(dòng)起來(lái)還需要調(diào)用這個(gè)函數(shù)。添加方法:

HorizonLine.prototype = {
  /**
   * 更新地面
   * @param {Number} deltaTime 間隔時(shí)間
   * @param {Number} speed 速度
   */
  update: function (deltaTime, speed) {
    // 計(jì)算地面每次移動(dòng)的距離(距離 = 速度 x 時(shí)間)時(shí)間由幀率和間隔時(shí)間共同決定
    var incre = Math.floor(speed * (FPS / 1000) * deltaTime);

    if (this.xPos[0] <= 0) {
      this.updateXPos(0, incre);
    } else {
      this.updateXPos(1, incre);
    }
    this.draw();
  },
};

然后需要通過(guò) Horizon 上的 update 方法來(lái)調(diào)用 HorizonLine 上的 update 方法:

Horizon.prototype = {
  // 更新背景
  update: function (deltaTime, currentSpeed) {
    this.horizonLine.update(deltaTime, currentSpeed);
  },
};

同理,按照上面的邏輯,現(xiàn)在應(yīng)該在 Runner 上定義 update 方法來(lái)調(diào)用 Horizon 上的 update 方法:

Runner.prototype = {
  // 更新游戲幀并進(jìn)行下一次更新
  update: function () {
    this.updatePending = false; // 等待更新

    var now = getTimeStamp();
    var deltaTime = now - (this.time || now);

    this.time = now;

    this.clearCanvas();
    this.horizon.update(deltaTime, this.currentSpeed);

    // 進(jìn)行下一次更新
    this.scheduleNextUpdate();
  },
  // 清空 canvas
  clearCanvas: function () {
    this.ctx.clearRect(0, 0, this.dimensions.WIDTH,
      this.dimensions.HEIGHT);
  },
  // 進(jìn)行下一次更新
  scheduleNextUpdate: function () {
    if (!this.updatePending) {
      this.updatePending = true;
      this.raqId = requestAnimationFrame(this.update.bind(this));
    }
  },
};

//  獲取時(shí)間戳
function getTimeStamp() {
  return performance.now();
}

最后在 Runnerinit 方法中調(diào)用它的 update 方法:

Runner.prototype = {
  init: function () {
    // ...

+   // 更新 canvas
+   this.update();
  },
};

由于類層層抽象的原因,方法的也需要層層調(diào)用。

現(xiàn)在地面就可以進(jìn)行無(wú)限滾動(dòng)了,效果如下:

你可以通過(guò)查看我的 commit 信息,來(lái)查看添加或修改的代碼:戳這里
響應(yīng)空格鍵

下面來(lái)實(shí)現(xiàn)地面對(duì)空格鍵的響應(yīng),具體效果就是,初始地面不動(dòng),按下空格鍵后地面移動(dòng)。

修改 Runner 原型鏈中的 update 方法:

Runner.prototype = {
  update: function () {
    var now = getTimeStamp();
    var deltaTime = now - (this.time || now);

    this.time = now;

+   if (this.playing) {
      this.clearCanvas();
      this.horizon.update(deltaTime, this.currentSpeed);
+   }

+   if (this.playing) {
      // 進(jìn)行下一次更新
      this.scheduleNextUpdate();
+   }
  },
};

監(jiān)聽(tīng)鍵盤(pán)事件:

Runner.prototype = {
  startListening: function () {
    document.addEventListener(Runner.events.KEYDOWN, this);
    document.addEventListener(Runner.events.KEYUP, this);
  },
  stopListening: function () {
    document.removeEventListener(Runner.events.KEYDOWN, this);
    document.removeEventListener(Runner.events.KEYUP, this);
  },
};

添加數(shù)據(jù):

Runner.events = {
  // ...

+ KEYDOWN: "keydown",
+ KEYUP: "keyup",
};

然后在 Runnerinit 方法中調(diào)用 startListening 方法,來(lái)監(jiān)聽(tīng)鍵盤(pán)的 keydownkeyup 事件:

Runner.prototype = {
  init: function () {
    // ...
    
+   // 開(kāi)始監(jiān)聽(tīng)用戶動(dòng)作
+   this.startListening();
  },
};

當(dāng)瀏覽器監(jiān)聽(tīng)到用戶按下鍵盤(pán)時(shí),會(huì)執(zhí)行 handleEvent 方法來(lái)處理鍵盤(pán)事件:

Runner.prototype = {
  // 用來(lái)處理 EventTarget(這里就是 Runner 類) 上發(fā)生的事件
  // 當(dāng)事件被發(fā)送到 EventListener 時(shí),瀏覽器就會(huì)自動(dòng)調(diào)用這個(gè)方法
  handleEvent: function (e) {
    return (function (eType, events) {
      switch (eType) {
        case events.KEYDOWN:
          this.onKeyDown(e);
          break;
        default:
          break;
      }
    }.bind(this))(e.type, Runner.events);
  },
};

上面用到的 onKeyDown 方法定義如下:

Runner.prototype = {
  onKeyDown: function (e) {
    if (!this.crashed && !this.paused) {
      if (Runner.keyCodes.JUMP[e.keyCode]) {
        e.preventDefault();

        if (!this.playing) {
          this.setPlayStatus(true);
          this.update();
        }
      }
    }      
  },
  // 設(shè)置游戲是否為進(jìn)行狀態(tài)
  setPlayStatus: function (isPlaying) {
    this.playing = isPlaying;
  },
};

這里需要提一下,當(dāng)按下空格鍵后, 為什么瀏覽器會(huì)執(zhí)行 handleEvent 事件:原因是當(dāng)使用 addEventListener 監(jiān)聽(tīng)某個(gè)對(duì)象上的事件時(shí),只要被監(jiān)聽(tīng)的事件觸發(fā)了,就會(huì)執(zhí)行該對(duì)象上名字為 handleEvent 的方法(如果有)。MDN 上有對(duì) handleEvent 事件的解釋。

到這里,就實(shí)現(xiàn)了地面對(duì)空格鍵的響應(yīng),效果如下:

查看添加或修改的代碼,戳這里

Demo 體驗(yàn)地址:https://liuyib.github.io/blog/demo/game/google-dino/horizonline-move/

上一篇 下一篇
Chrome 小恐龍游戲源碼探究一 -- 繪制靜態(tài)地面 Chrome 小恐龍游戲源碼探究三 -- 進(jìn)入街機(jī)模式

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/103885.html

相關(guān)文章

  • Chrome 恐龍游戲源碼探究一 -- 繪制靜態(tài)地面

    摘要:首先是繪制靜態(tài)的地面。上一篇下一篇無(wú)小恐龍游戲源碼探究二讓地面動(dòng)起來(lái) 文章首發(fā)于我的 GitHub 博客 目錄 Chrome 小恐龍游戲源碼探究一 -- 繪制靜態(tài)地面 Chrome 小恐龍游戲源碼探究二 -- 讓地面動(dòng)起來(lái) Chrome 小恐龍游戲源碼探究三 -- 進(jìn)入街機(jī)模式 Chrome 小恐龍游戲源碼探究四 -- 隨機(jī)繪制云朵 Chrome 小恐龍游戲源碼探究五 -- 隨機(jī)繪...

    lixiang 評(píng)論0 收藏0
  • Chrome 恐龍游戲源碼探究三 -- 進(jìn)入街機(jī)模式

    摘要:文章首發(fā)于我的博客前言上一篇文章小恐龍游戲源碼探究二讓地面動(dòng)起來(lái)實(shí)現(xiàn)了地面的移動(dòng)。街機(jī)模式的效果就是游戲開(kāi)始后,進(jìn)入全屏模式。例如可以看到,進(jìn)入街機(jī)模式之前,有一段開(kāi)場(chǎng)動(dòng)畫(huà)。 文章首發(fā)于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究二 -- 讓地面動(dòng)起來(lái)》 實(shí)現(xiàn)了地面的移動(dòng)。這一篇文章中,將實(shí)現(xiàn)效果:1、瀏覽器失焦時(shí)游戲暫停,聚焦游戲繼續(xù)。 2、開(kāi)場(chǎng)動(dòng)...

    yeooo 評(píng)論0 收藏0
  • Chrome 恐龍游戲源碼探究八 -- 奔跑的恐龍

    摘要:例如,將函數(shù)修改為小恐龍眨眼這樣小恐龍會(huì)不停的眨眼睛。小恐龍的開(kāi)場(chǎng)動(dòng)畫(huà)下面來(lái)實(shí)現(xiàn)小恐龍對(duì)鍵盤(pán)按鍵的響應(yīng)。接下來(lái)還需要更新動(dòng)畫(huà)幀才能實(shí)現(xiàn)小恐龍的奔跑動(dòng)畫(huà)。 文章首發(fā)于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究七 -- 晝夜模式交替》實(shí)現(xiàn)了游戲晝夜模式的交替,這一篇文章中,將實(shí)現(xiàn):1、小恐龍的繪制 2、鍵盤(pán)對(duì)小恐龍的控制 3、頁(yè)面失焦后,重新聚焦會(huì)重置...

    paulquei 評(píng)論0 收藏0
  • Chrome 恐龍游戲源碼探究五 -- 隨機(jī)繪制障礙

    摘要:文章首發(fā)于我的博客前言上一篇文章小恐龍游戲源碼探究四隨機(jī)繪制云朵實(shí)現(xiàn)了云朵的隨機(jī)繪制,這一篇文章中將實(shí)現(xiàn)仙人掌翼龍障礙物的繪制游戲速度的改變障礙物的類型有兩種仙人掌和翼龍。 文章首發(fā)于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究四 -- 隨機(jī)繪制云朵》 實(shí)現(xiàn)了云朵的隨機(jī)繪制,這一篇文章中將實(shí)現(xiàn):1、仙人掌、翼龍障礙物的繪制 2、游戲速度的改變 障礙物...

    tomorrowwu 評(píng)論0 收藏0
  • Chrome 恐龍游戲源碼探究四 -- 隨機(jī)繪制云朵

    摘要:文章首發(fā)于我的博客前言上一篇文章小恐龍游戲源碼探究三進(jìn)入街機(jī)模式實(shí)現(xiàn)了開(kāi)場(chǎng)動(dòng)畫(huà)和街機(jī)模式。 文章首發(fā)于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究三 -- 進(jìn)入街機(jī)模式》 實(shí)現(xiàn)了開(kāi)場(chǎng)動(dòng)畫(huà)和街機(jī)模式。這一篇文章中,將實(shí)現(xiàn)云朵的隨機(jī)繪制。 云朵類 Cloud 定義云朵類 Cloud: /** * 云朵類 * @param {HTMLCanvasEle...

    svtter 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<