首页 > 代码库 > Chrome自带恐龙小游戏的源码研究(二)

Chrome自带恐龙小游戏的源码研究(二)

  在上一篇《Chrome自带恐龙小游戏的源码研究(一)》中实现了地面的绘制和运动,这一篇主要研究云朵的绘制。

  云朵的绘制通过Cloud构造函数完成。Cloud实现代码如下:

 1 Cloud.config = { 2     HEIGHT:14,  //云朵sprite的高度 3     MAX_CLOUD_GAP:400,  //两朵云之间的最大间隙 4     MAX_SKY_LEVEL:30,   //云朵的最大高度 5     MIN_CLOUD_GAP:100,  //两朵云之间的最小间隙 6     MIN_SKY_LEVEL:71,   //云朵的最小高度 7     WIDTH:46,    //云朵sprite的宽度 8     MAX_CLOUDS:6,//最大云朵数量 9     CLOUD_FREQUENCY:.5 //云朵出现频率10 };11 12 //用于存储云朵13 Cloud.clouds = [];14 15 16 17 /**18 * canvas 用于绘制的画布19 * spritePos 在雪碧图中的坐标20 * containerWidth 容器宽度21 */22 23 function Cloud(canvas,spritePos,containerWidth) {24     this.canvas = canvas;25     this.ctx = canvas.getContext("2d");26     this.spritePos = spritePos;27     this.containerWidth = containerWidth;28     this.xPos = containerWidth; //云朵初始x坐标在屏幕外29     this.yPos = 0;  //云朵初始高度30     this.remove = false;    //是否移除31 32     //云朵之间的间隙400~10033     this.cloudGap = getRandomNum(Cloud.config.MIN_CLOUD_GAP,Cloud.config.MAX_CLOUD_GAP);34     this.init();35 }

主要的逻辑代码在Cloud的原型链中:

 1 Cloud.prototype = { 2     init:function () { 3         //设置云朵的高度为随机30~71 4         this.yPos = getRandomNum(Cloud.config.MAX_SKY_LEVEL,Cloud.config.MIN_SKY_LEVEL); 5         this.draw(); 6     }, 7     draw:function () { 8         this.ctx.save(); 9         var sourceWidth = Cloud.config.WIDTH,10             sourceHeight = Cloud.config.HEIGHT;11 12         this.ctx.drawImage(imgSprite,13             this.spritePos.x,this.spritePos.y,14             sourceWidth,sourceHeight,15             this.xPos,this.yPos,16             sourceWidth,sourceHeight);17         this.ctx.restore();18     },19     //添加云朵并控制其移动20     updateClouds:function(speed) {21         var numClouds = Cloud.clouds.length;22         if(numClouds) {23             for(var i = numClouds - 1; i >= 0; i--) {24                 Cloud.clouds[i].update(speed);25             }26 27             var lastCloud = Cloud.clouds[numClouds - 1];28 29             //若当前存在的云朵数量小于最大云朵数量30 31             //并且云朵位置大于间隙时32 33             //随机添加云朵34             if(numClouds < Cloud.config.MAX_CLOUDS &&35                 (DEFAULT_WIDTH - lastCloud.xPos) > lastCloud.cloudGap &&36                 Cloud.config.CLOUD_FREQUENCY > Math.random()) {37                 this.addCloud();38             }39 40             //过滤掉已经移出屏幕外的云朵41             Cloud.clouds = Cloud.clouds.filter(function(obj){42                 return !obj.remove;43             });44         } else {45             this.addCloud();46         }47     },48     update:function(speed) {49         //仅绘制符合条件的云朵50         if(!this.remove) {51             //向左移动52             this.xPos -= Math.ceil(speed);53             this.draw();54 55             if(!this.isVisible()) {56                 this.remove = true;57             }58         }59     },60     //判断云朵是否移出屏幕外61     isVisible:function() {62         return this.xPos + Cloud.config.WIDTH > 0;63     },64     //将云朵添加至数组65     addCloud:function () {66         var cloud = new Cloud(this.canvas,spriteDefinition.CLOUD,DEFAULT_WIDTH);67         Cloud.clouds.push(cloud);68     }69 };

最后测试一下这个方法:

 1 window.onload = function () { 2     var h = new HorizonLine(c,spriteDefinition.HORIZON); 3     var cloud = new Cloud(c,spriteDefinition.CLOUD,DEFAULT_WIDTH); 4     var startTime = 0; 5     (function draw(time) { 6         ctx.clearRect(0,0,600,150); 7         time = time || 0; 8         h.update(time - startTime,3); 9         cloud.updateClouds(0.2);10         startTime = time;11         window.requestAnimationFrame(draw,c);12     })();13 };

效果如下:

 

<script type="text/javascript">// this.bumpThreshold ? this.dimensions.WIDTH : 0; }, draw:function() { this.ctx.drawImage(imgSprite, this.sourceXPos[0], this.spritePos.y, this.dimensions.WIDTH, this.dimensions.HEIGHT, this.xPos[0],this.yPos, this.dimensions.WIDTH,this.dimensions.HEIGHT); this.ctx.drawImage(imgSprite, this.sourceXPos[1], this.spritePos.y, this.dimensions.WIDTH, this.dimensions.HEIGHT, this.xPos[1],this.yPos, this.dimensions.WIDTH,this.dimensions.HEIGHT); }, updateXPos:function(pos,increment) { var line1 = pos, line2 = pos === 0 ? 1 : 0; this.xPos[line1] -= increment; this.xPos[line2] = this.xPos[line1] + this.dimensions.WIDTH; if(this.xPos[line1] <= -this.dimensions.WIDTH) { this.xPos[line1] += this.dimensions.WIDTH * 2; this.xPos[line2] = this.xPos[line1] - this.dimensions.WIDTH; this.sourceXPos[line1] = this.getRandomType() + this.spritePos.x; } }, update:function(deltaTime,speed) { var increment = Math.floor(speed * (FPS / 1000) * deltaTime); if(this.xPos[0] <= 0) { this.updateXPos(0, increment); } else { this.updateXPos(1, increment); } this.draw(); }, reset:function() { this.xPos[0] = 0; this.xPos[1] = this.dimensions.WIDTH; } }; //endregion //region utils function getRandomNum(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function getTimeStamp() { return performance.now(); } //endregion Cloud.config = { HEIGHT:14, //云朵sprite的高度 MAX_CLOUD_GAP:400, //两朵云之间的最大间隙 MAX_SKY_LEVEL:30, //云朵的最大高度 MIN_CLOUD_GAP:100, //两朵云之间的最小间隙 MIN_SKY_LEVEL:71, //云朵的最小高度 WIDTH:46, //云朵sprite的宽度 MAX_CLOUDS:6,//最大云朵数量 CLOUD_FREQUENCY:.5 //云朵出现频率 }; Cloud.clouds = []; function Cloud(canvas,spritePos,containerWidth) { this.canvas = canvas; this.ctx = canvas.getContext("2d"); this.spritePos = spritePos; this.containerWidth = containerWidth; this.xPos = containerWidth; //云朵初始x坐标在屏幕外 this.yPos = 0; //云朵初始高度 this.remove = false; //是否移除 //云间隙 this.cloudGap = getRandomNum(Cloud.config.MIN_CLOUD_GAP,Cloud.config.MAX_CLOUD_GAP); this.init(); } 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, sourceHeight = Cloud.config.HEIGHT; this.ctx.drawImage(imgSprite, this.spritePos.x,this.spritePos.y, sourceWidth,sourceHeight, this.xPos,this.yPos, sourceWidth,sourceHeight); this.ctx.restore(); }, updateClouds:function(speed) { var numClouds = Cloud.clouds.length; if(numClouds) { for(var i = numClouds - 1; i >= 0; i--) { Cloud.clouds[i].update(speed); } var lastCloud = Cloud.clouds[numClouds - 1]; if(numClouds < Cloud.config.MAX_CLOUDS && (DEFAULT_WIDTH - lastCloud.xPos) > lastCloud.cloudGap && Cloud.config.CLOUD_FREQUENCY > Math.random()) { this.addCloud(); } Cloud.clouds = Cloud.clouds.filter(function(obj){ return !obj.remove; }); } else { this.addCloud(); } }, update:function(speed) { if(!this.remove) { //向左移动 this.xPos -= Math.ceil(speed); this.draw(); if(!this.isVisible()) { this.remove = true; } } }, //判断云朵是否移出屏幕外 isVisible:function() { return this.xPos + Cloud.config.WIDTH > 0; }, addCloud:function () { var cloud = new Cloud(this.canvas,spriteDefinition.CLOUD,DEFAULT_WIDTH); Cloud.clouds.push(cloud); } }; window.onload = function () { var h = new HorizonLine(c,spriteDefinition.HORIZON); var cloud = new Cloud(c,spriteDefinition.CLOUD,DEFAULT_WIDTH); var startTime = 0; (function draw(time) { ctx.clearRect(0,0,600,150); time = time || 0; h.update(time - startTime,3); cloud.updateClouds(0.2); startTime = time; window.requestAnimationFrame(draw,c); })(); };// ]]></script>

这样云朵就绘制好了。

Chrome自带恐龙小游戏的源码研究(二)