文章首发于个人 GitHub 博客
上一篇文章:《Chrome 小恐龙游戏源码探究三 -- 进入街机模式》 实现了开场动画和街机模式。这一篇文章中,将实现云朵的随机绘制。git
定义云朵类 Cloud
:github
/** * 云朵类 * @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(); }
相关的配置参数:canvas
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 // 云的最大数量 };
补充本篇文章中会用到的数据:segmentfault
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
类中添加与云朵相关的属性:dom
- 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
:this
Horizon.prototype = { // 添加新的云朵 addCloud: function () { this.clouds.push(new Cloud(this.canvas, this.spritePos.CLOUD, this.dimensions.WIDTH)); }, };
调用 addCloud
方法来初始化云朵:google
Horizon.prototype = { init: function () { + this.addCloud(); this.horizonLine = new HorizonLine(this.canvas, this.spritePos.HORIZON); }, };
添加更新云朵的方法:spa
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 小恐龙游戏源码探究五 -- 随机绘制障碍 |