Chrome 小恐龍遊戲原始碼探究四 -- 隨機繪製雲朵
前言
上一篇文章:《 Chrome 小恐龍遊戲原始碼探究三 -- 進入街機模式 》 實現了開場動畫和街機模式。這一篇文章中,將實現雲朵的隨機繪製。
雲朵類 Cloud
定義雲朵類 Cloud:
/** * 雲朵類 * @param {HTMLCanvasElement} canvas 畫布 * @param {Object} spritePos 圖片在雪碧圖中的位置資訊 * @param {Number} containerWidth 容器的寬度 */ function Cloud(canvas, spritePos, containerWidth) { this.canvas = canvas; this.ctx = canvas.getContext('2d'); this.spritePos = spritePos; this.containerWidth = containerWidth; // 座標 this.xPos = containerWidth; this.yPos = 0; // 該雲朵是否需要刪除 this.remove = false; // 隨機雲朵之間的間隙 this.cloudGap = getRandomNum(Cloud.config.MIN_CLOUD_GAP, Cloud.config.MAX_CLOUD_GAP); this.init(); }
相關的配置引數:
Cloud.config = { WIDTH: 46, HEIGHT: 14, MIN_CLOUD_GAP: 100,// 雲之間的最小間隙 MAX_CLOUD_GAP: 400,// 雲之間的最大間隙 MIN_SKY_LEVEL: 71,// 雲的最小高度 MAX_SKY_LEVEL: 30,// 雲的最大高度 BG_CLOUD_SPEED: 0.2,// 雲的速度 CLOUD_FREQUENCY: 0.5, // 雲的頻率 MAX_CLOUDS: 6// 雲的最大數量 };
補充本篇文章中會用到的一些資料:
Runner.spriteDefinition = { LDPI: { // ... +CLOUD: {x: 86, y: 2}, }, };
在 Cloud 原型鏈上新增方法:
Cloud.prototype = { init: function () { this.yPos = getRandomNum(Cloud.config.MAX_SKY_LEVEL, Cloud.config.MIN_SKY_LEVEL); this.draw(); }, draw: function () { this.ctx.save(); var sourceWidth = Cloud.config.WIDTH; var sourceHeight = Cloud.config.HEIGHT; var outputWidth = sourceWidth; var outputHeight = sourceHeight; this.ctx.drawImage( Runner.imageSprite, this.spritePos.x, this.spritePos.y, sourceWidth, sourceHeight, this.xPos, this.yPos, outputWidth, outputHeight ); this.ctx.restore(); }, update: function (speed) { if (!this.remove) { this.xPos -= speed; this.draw(); // 雲朵移出 canvas,將其刪除 if (!this.isVisible()) { this.remove = true; } } }, // 雲朵是否移出 canvas isVisible: function () { return this.xPos + Cloud.config.WIDTH > 0; }, }; /** * 獲取 [min, max] 之間的隨機數 * @param {Number} min 最小值 * @param {Number} max 最大值 * @return {Number} */ function getRandomNum(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
在 Horizon 類中新增與雲朵相關的屬性:
- function Horizon(canvas, spritePos) { + function Horizon(canvas, spritePos, dimensions) { this.canvas = canvas; this.ctx = this.canvas.getContext('2d'); this.spritePos = spritePos; +this.dimensions = dimensions; // 雲的頻率 +this.cloudFrequency = Cloud.config.CLOUD_FREQUENCY; // 雲 +this.clouds = []; +this.cloudSpeed = Cloud.config.BG_CLOUD_SPEED; // 地面 this.horizonLine = null; this.init(); }
修改在 Runner 中呼叫 Horizon 類時傳入的引數:
Runner.prototype = { init: function () { // ... // 載入背景類 Horizon -this.horizon = new Horizon(this.canvas, this.spriteDef); +this.horizon = new Horizon(this.canvas, this.spriteDef, +this.dimensions); // ... }, };
生成雲朵並存入陣列,新增方法:
Horizon.prototype = { addCloud: function () { this.clouds.push(new Cloud(this.canvas, this.spritePos.CLOUD, this.dimensions.WIDTH)); }, };
通過 Horizon 的 init
方法呼叫 addCloud
來初始生成雲朵:
Horizon.prototype = { init: function () { +this.addCloud(); this.horizonLine = new HorizonLine(this.canvas, this.spritePos.HORIZON); }, };
更新雲朵:
Horizon.prototype = { updateCloud: function (deltaTime, speed) { var cloudSpeed = Math.ceil(deltaTime * this.cloudSpeed * speed / 1000); var numClouds = this.clouds.length; if (numClouds) { for (var i = numClouds - 1; i >= 0; i--) { this.clouds[i].update(cloudSpeed); } var lastCloud = this.clouds[numClouds - 1]; // 檢查是否需要新增新的雲朵 // 新增雲朵的條件:雲朵數量少於最大數量、 // 最後一個雲朵後面的空間大於它的間隙、 // 雲朵出現頻率符合要求 if (numClouds < Cloud.config.MAX_CLOUDS && (this.dimensions.WIDTH - lastCloud.xPos) > lastCloud.cloudGap && this.cloudFrequency > Math.random()) { this.addCloud(); } // 刪除 remove 屬性為 true 的雲朵 this.clouds = this.clouds.filter(function (item) { return !item.remove; }); } else { this.addCloud(); } }, };
然後通過 Horizon 的 update
方法呼叫上面的 updateCloud
方法:
Horizon.prototype = { update: function (deltaTime, currentSpeed) { this.horizonLine.update(deltaTime, currentSpeed); +this.updateCloud(deltaTime, currentSpeed); }, };
這樣就實現了雲朵的繪製:
檢視新增的程式碼: 戳這裡
Demo 體驗地址: https://liuyib.github.io/pages/demo/games/google-dino/add-cloud/
上一篇 | 下一篇 | Chrome 小恐龍遊戲原始碼探究三 -- 進入街機模式 | Chrome 小恐龍遊戲原始碼探究五 -- 隨機繪製障礙 |