欢迎光临
我们一直在努力

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

在上一篇《Chrome自带恐龙小游戏的源码研究(二)》中实现了云朵的绘制和移动,这一篇主要研究如何让游戏实现昼夜交替。

昼夜交替的效果主要是通过样式来完成,但改变样式的时机则由脚本控制。 首先对游戏容器使用transition创建一个贝塞尔渐变:

1 .game-body{ 2  transition:filter 1.5s cubic-bezier(0.65, 0.05, 0.36, 1), 3  background-color 1.5s cubic-bezier(0.65, 0.05, 0.36, 1); 4 5 /*告诉浏览器即将对某元素执行什么动画,这样浏览器可以提前进行准备来优化动画效果,使动画更为流畅*/ 6  will-change: filter,background-color; 7 }

渐变作用于两个属性:filter及background-color。

1 .inverted{ 2  filter: invert(100%); /*反色*/ 3  background-color: #000; /*改变背景为黑色(入夜效果)*/ 4 }

当符合条件时,游戏容器将添加inverted样式,以达到昼夜交替效果。

接下来看一下代码实现:

 1 nightmode.config = {  2 FADE_speed: 0.035, //淡入淡出速度  3 HEIGHT: 40, //月亮高度  4 MOON_SPEED: 0.25, //月亮移动速度  5 NUM_STARS: 2, //星星数量  6 STAR_SIZE: 9, //星星宽度  7 STAR_SPEED: 0.3,//星星速度  8 STAR_MAX_Y: 70, //星星在画布上出现的位置  9 WIDTH: 20 //半个月度宽度 10 }; 11 //月亮在不同时期有不同的位置 12 NightMode.phases = [140,120,100,60,40,20,0]; 13 14 //时间记录 15 NightMode.invertTimer = 0; 16 //是否可以进行昼夜交替 17 NightMode.inverted = false; 18 //用于控制样式切换 19 NightMode.invertTrigger = false; 20 //黑夜持续时间 21 NightMode.INVERT_FADE_DURATION = 5000;

 1 function NightMode(canvas,spritePos,containerWidth) {  2 this.spritePos = spritePos;  3 this.canvas = canvas;  4 this.ctx = canvas.getContext("2d");  5 this.containerWidth = containerWidth;  6 this.xPos = containerWidth - 50; //月亮的x坐标  7 this.yPos = 30; //月亮的y坐标  8 this.currentPhase = 0;  9 this.opacity = 0;  10 this.stars = []; //用于存储星星  11 this.drawStars = false; //是否绘制星星  12 this.placeStars(); //放置星星  13 }  14  15 NightMode.prototype = {  16 update:function(activated) {  17 //若夜晚模式处于激活状态且opacity为0时  18 //对月亮周期进行更新  19 if(activated && this.opacity == 0) {  20 this.currentPhase++;  21 if(this.currentPhase >= NightMode.phases.length) {  22 this.currentPhase = 0;  23  }  24  }  25  26 //淡入  27 if(activated && (this.opacity < 1 || this.opacity == 0)) {  28 this.opacity += NightMode.config.FADE_SPEED;  29 } else if(this.opacity > 0) {//淡出  30 this.opacity -= NightMode.config.FADE_SPEED;  31  }  32  33 //当opacity大于0时移动月亮位置  34 if(this.opacity > 0) {  35 this.xPos = this.updateXPos(this.xPos, NightMode.config.MOON_SPEED);  36  37 //移动星星  38 if(this.drawStars) {  39 for (var i = 0; i < NightMode.config.NUM_STARS; i++) {  40 this.stars[i].x = this.updateXPos(this.stars[i].x,NightMode.config.STAR_SPEED);  41  }  42  }  43 this.draw();  44 } else {  45 this.opacity = 0;  46 this.placeStars();  47  }  48 this.drawStars = true;  49  },  50 updateXPos: function(currentPos, speed) {  51 if (currentPos < -NightMode.config.WIDTH) {  52 currentPos = this.containerWidth;  53 } else {  54 currentPos -= speed;  55  }  56 return currentPos;  57  },  58 draw:function() {  59 //周期为3时画满月  60 var moonSourceWidth = this.currentPhase == 3 ? NightMode.config.WIDTH * 2 :  61  NightMode.config.WIDTH;  62 var moonSourceHeight = NightMode.config.HEIGHT;  63 //从雪碧图上获取月亮正确的形状  64 var moonSourceX = this.spritePos.x + NightMode.phases[this.currentPhase];  65 var moonOutputWidth = moonSourceWidth;  66 var starSize = NightMode.config.STAR_SIZE;  67 var starSourceX = spriteDefinition.STAR.x;  68  69 this.ctx.save();  70 //画布透明度也随之变化  71 this.ctx.globalAlpha = this.opacity;  72  73 if (this.drawStars) {  74 for (var i = 0; i < NightMode.config.NUM_STARS; i++) {  75 this.ctx.drawImage(imgSprite,  76 starSourceX, this.stars[i].sourceY,  77  starSize, starSize,  78 Math.round(this.stars[i].x), this.stars[i].y,  79  NightMode.config.STAR_SIZE, NightMode.config.STAR_SIZE);  80  }  81  }  82  83 this.ctx.drawImage(imgSprite,  84 moonSourceX, this.spritePos.y,  85  moonSourceWidth, moonSourceHeight,  86 Math.round(this.xPos), this.yPos,  87  moonOutputWidth, NightMode.config.HEIGHT);  88  89 this.ctx.globalAlpha = 1;  90 this.ctx.restore();  91  },  92 placeStars:function() {  93 //将画布分为若干组  94 var segmentSize = Math.round(this.containerWidth /NightMode.config.NUM_STARS);  95 for (var i = 0; i < NightMode.config.NUM_STARS; i++) {  96 this.stars[i] = {};  97 //每组星星位置随机  98 this.stars[i].x = getRandomNum(segmentSize * i, segmentSize * (i + 1));  99 this.stars[i].y = getRandomNum(0, NightMode.config.STAR_MAX_Y); 100 this.stars[i].sourceY = spriteDefinition.STAR.y + NightMode.config.STAR_SIZE * i; 101  } 102  }, 103 invert:function(deltaTime) { 104 this.update(NightMode.inverted); 105 106 //黑夜持续时间5秒 107 if(NightMode.invertTimer > NightMode.INVERT_FADE_DURATION) { 108 NightMode.invertTimer = 0; 109 NightMode.invertTrigger = false; 110 NightMode.inverted = document.body.classList.toggle('inverted',NightMode.invertTrigger); 111 } else if(NightMode.invertTimer) { 112 NightMode.invertTimer += deltaTime; 113 } else { 114 //每500帧触发黑夜,这里只是为了模拟效果,完整游戏中是每700米触发一次黑夜 115 NightMode.invertTrigger = !(gameFrame % 500); 116 if(NightMode.invertTrigger && NightMode.invertTimer === 0) { 117 NightMode.invertTimer += deltaTime; 118 NightMode.inverted = document.body.classList.toggle('inverted',NightMode.invertTrigger); 119  } 120  } 121  }, 122 reset: function() { 123 this.currentPhase = 0; 124 this.opacity = 0; 125 this.update(false); 126  } 127 };

最后添加测试代码:

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

下面是运行效果(每500帧切换一次):

 

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

  • 海报
海报图正在生成中...
赞(0) 打赏
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
文章名称:《Chrome自带恐龙小游戏的源码研究(三)》
文章链接:https://www.456zj.com/37588.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址