摘要:文章首發(fā)于我的博客前言上一篇文章小恐龍游戲源碼探究一繪制靜態(tài)地面中定義了游戲的主體類,并實現(xiàn)了靜態(tài)地面的繪制。
文章首發(fā)于我的 GitHub 博客前言
上一篇文章:《Chrome 小恐龍游戲源碼探究一 -- 繪制靜態(tài)地面》 中定義了游戲的主體類 Runner,并實現(xiàn)了靜態(tài)地面的繪制。這一篇文章中,將實現(xiàn)效果:1、地面無限滾動。2、剛開始地面不動,按下空格后地面滾動。
地面無限滾動要實現(xiàn)地面的移動就要不斷更新地面的 x 坐標(biāo)。定義如下方法:
HorizonLine.prototype = { /** * 更新地面的 x 坐標(biāo) * @param {Number} pos 地面的位置 * @param {Number} incre 移動距離 */ updateXPos: function (pos, incre) { var line1 = pos; var line2 = pos === 0 ? 1 : 0; // 第一段地面向左移動,第二段地面隨之 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; // 此時第二段地面的 x 坐標(biāo)剛好和 canvas 的 x 坐標(biāo)對齊 this.xPos[line2] = this.xPos[line1] - this.dimensions.WIDTH; // 給放到 canvas 后面的地面隨機地形 this.sourceXPos[line1] = this.getRandomType() + this.spritePos.x; } }, // 獲取隨機的地形 getRandomType: function () { return Math.random() > this.bumpThreshold ? this.dimensions.WIDTH : 0; }, };
其中 updateXPos 實現(xiàn)了地面 x 坐標(biāo)的更新。當(dāng)?shù)谝欢蔚孛嬉瞥?canvas 時,會將第一段地面 x 坐標(biāo)乘 2 放到 canvas 后面,然后為其隨機地形。這時,原來的第二段地面就變成了第一段地面繼續(xù)向前移動,以此類推。這樣就實現(xiàn)了地面的不斷移動和更新。
上面的函數(shù)只是實現(xiàn)了地面移動相關(guān)的邏輯,真正讓地面動起來還需要調(diào)用這個函數(shù)。添加方法:
HorizonLine.prototype = { /** * 更新地面 * @param {Number} deltaTime 間隔時間 * @param {Number} speed 速度 */ update: function (deltaTime, speed) { // 計算地面每次移動的距離(距離 = 速度 x 時間)時間由幀率和間隔時間共同決定 var incre = Math.floor(speed * (FPS / 1000) * deltaTime); if (this.xPos[0] <= 0) { this.updateXPos(0, incre); } else { this.updateXPos(1, incre); } this.draw(); }, };
然后需要通過 Horizon 上的 update 方法來調(diào)用 HorizonLine 上的 update 方法:
Horizon.prototype = { // 更新背景 update: function (deltaTime, currentSpeed) { this.horizonLine.update(deltaTime, currentSpeed); }, };
同理,按照上面的邏輯,現(xiàn)在應(yīng)該在 Runner 上定義 update 方法來調(diào)用 Horizon 上的 update 方法:
Runner.prototype = { // 更新游戲幀并進行下一次更新 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); // 進行下一次更新 this.scheduleNextUpdate(); }, // 清空 canvas clearCanvas: function () { this.ctx.clearRect(0, 0, this.dimensions.WIDTH, this.dimensions.HEIGHT); }, // 進行下一次更新 scheduleNextUpdate: function () { if (!this.updatePending) { this.updatePending = true; this.raqId = requestAnimationFrame(this.update.bind(this)); } }, }; // 獲取時間戳 function getTimeStamp() { return performance.now(); }
最后在 Runner 的 init 方法中調(diào)用它的 update 方法:
Runner.prototype = { init: function () { // ... + // 更新 canvas + this.update(); }, };
由于類層層抽象的原因,方法的也需要層層調(diào)用。
現(xiàn)在地面就可以進行無限滾動了,效果如下:
你可以通過查看我的 commit 信息,來查看添加或修改的代碼:戳這里響應(yīng)空格鍵
下面來實現(xiàn)地面對空格鍵的響應(yī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) { // 進行下一次更新 this.scheduleNextUpdate(); + } }, };
監(jiā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", };
然后在 Runner 的 init 方法中調(diào)用 startListening 方法,來監(jiān)聽鍵盤的 keydown 和 keyup 事件:
Runner.prototype = { init: function () { // ... + // 開始監(jiān)聽用戶動作 + this.startListening(); }, };
當(dāng)瀏覽器監(jiān)聽到用戶按下鍵盤時,會執(zhí)行 handleEvent 方法來處理鍵盤事件:
Runner.prototype = { // 用來處理 EventTarget(這里就是 Runner 類) 上發(fā)生的事件 // 當(dāng)事件被發(fā)送到 EventListener 時,瀏覽器就會自動調(diào)用這個方法 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è)置游戲是否為進行狀態(tài) setPlayStatus: function (isPlaying) { this.playing = isPlaying; }, };
這里需要提一下,當(dāng)按下空格鍵后, 為什么瀏覽器會執(zhí)行 handleEvent 事件:原因是當(dāng)使用 addEventListener 監(jiān)聽某個對象上的事件時,只要被監(jiān)聽的事件觸發(fā)了,就會執(zhí)行該對象上名字為 handleEvent 的方法(如果有)。MDN 上有對 handleEvent 事件的解釋。
到這里,就實現(xiàn)了地面對空格鍵的響應(yīng),效果如下:
查看添加或修改的代碼,戳這里
Demo 體驗地址:https://liuyib.github.io/blog/demo/game/google-dino/horizonline-move/
上一篇 | 下一篇 | Chrome 小恐龍游戲源碼探究一 -- 繪制靜態(tài)地面 | Chrome 小恐龍游戲源碼探究三 -- 進入街機模式 |
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/103885.html
摘要:首先是繪制靜態(tài)的地面。上一篇下一篇無小恐龍游戲源碼探究二讓地面動起來 文章首發(fā)于我的 GitHub 博客 目錄 Chrome 小恐龍游戲源碼探究一 -- 繪制靜態(tài)地面 Chrome 小恐龍游戲源碼探究二 -- 讓地面動起來 Chrome 小恐龍游戲源碼探究三 -- 進入街機模式 Chrome 小恐龍游戲源碼探究四 -- 隨機繪制云朵 Chrome 小恐龍游戲源碼探究五 -- 隨機繪...
摘要:文章首發(fā)于我的博客前言上一篇文章小恐龍游戲源碼探究二讓地面動起來實現(xiàn)了地面的移動。街機模式的效果就是游戲開始后,進入全屏模式。例如可以看到,進入街機模式之前,有一段開場動畫。 文章首發(fā)于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究二 -- 讓地面動起來》 實現(xiàn)了地面的移動。這一篇文章中,將實現(xiàn)效果:1、瀏覽器失焦時游戲暫停,聚焦游戲繼續(xù)。 2、開場動...
摘要:例如,將函數(shù)修改為小恐龍眨眼這樣小恐龍會不停的眨眼睛。小恐龍的開場動畫下面來實現(xiàn)小恐龍對鍵盤按鍵的響應(yīng)。接下來還需要更新動畫幀才能實現(xiàn)小恐龍的奔跑動畫。 文章首發(fā)于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究七 -- 晝夜模式交替》實現(xiàn)了游戲晝夜模式的交替,這一篇文章中,將實現(xiàn):1、小恐龍的繪制 2、鍵盤對小恐龍的控制 3、頁面失焦后,重新聚焦會重置...
摘要:文章首發(fā)于我的博客前言上一篇文章小恐龍游戲源碼探究四隨機繪制云朵實現(xiàn)了云朵的隨機繪制,這一篇文章中將實現(xiàn)仙人掌翼龍障礙物的繪制游戲速度的改變障礙物的類型有兩種仙人掌和翼龍。 文章首發(fā)于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究四 -- 隨機繪制云朵》 實現(xiàn)了云朵的隨機繪制,這一篇文章中將實現(xiàn):1、仙人掌、翼龍障礙物的繪制 2、游戲速度的改變 障礙物...
摘要:文章首發(fā)于我的博客前言上一篇文章小恐龍游戲源碼探究三進入街機模式實現(xiàn)了開場動畫和街機模式。 文章首發(fā)于我的 GitHub 博客 前言 上一篇文章:《Chrome 小恐龍游戲源碼探究三 -- 進入街機模式》 實現(xiàn)了開場動畫和街機模式。這一篇文章中,將實現(xiàn)云朵的隨機繪制。 云朵類 Cloud 定義云朵類 Cloud: /** * 云朵類 * @param {HTMLCanvasEle...
閱讀 2863·2021-09-24 10:34
閱讀 1945·2021-09-22 10:02
閱讀 2344·2021-09-09 09:33
閱讀 1520·2021-08-13 15:02
閱讀 3354·2020-12-03 17:10
閱讀 1253·2019-08-30 15:44
閱讀 2206·2019-08-30 12:58
閱讀 3295·2019-08-26 13:40