文章首发于我的
GitHub 博客
媒介
上一篇文章:《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.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
类挪用 Cloud
类。首先在 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);
// ...
},
};
增加天生云朵的要领,将天生的云朵存入数组 clouds
:
Horizon.prototype = {
// 增加新的云朵
addCloud: function () {
this.clouds.push(new Cloud(this.canvas, this.spritePos.CLOUD,
this.dimensions.WIDTH));
},
};
挪用 addCloud
要领来初始化云朵:
Horizon.prototype = {
init: function () {
+ this.addCloud();
this.horizonLine = new HorizonLine(this.canvas, this.spritePos.HORIZON);
},
};
增加更新云朵的要领:
Horizon.prototype = {
// 更新 canvas 上的云朵
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();
}
},
};
挪用 updateCloud
要领,来完成对云朵的更新:
Horizon.prototype = {
update: function (deltaTime, currentSpeed) {
this.horizonLine.update(deltaTime, currentSpeed);
+ this.updateCloud(deltaTime, currentSpeed);
},
};
运转结果以下:
检察增加或修正的代码:
戳这里
Demo 体验地点:https://liuyib.github.io/blog/demo/game/google-dino/add-cloud/
上一篇 | 下一篇 |
Chrome 小恐龙游戏源码探讨三 — 进入街机形式 | Chrome 小恐龙游戏源码探讨五 — 随机绘制停滞 |