本系列文章对应游戏代码已开源 Sinuous gamejavascript
到这里咱们已经讲了游戏的总体设计和实现。一个游戏要完整,还须要给它制定一个评分机制,它是整个游戏的关键所在。就比如一部电影,特效再好看,若是剧情狗血,那也是一部烂片。java
相信你们都玩过一些简单但很吸引人的小游戏。好比好久之前微信上的打飞机,围住神经猫,还有前段时间大火的slither.io。他们都简单易玩,但却能让人肾上腺素飙升,百玩不腻。git
因此一款好玩的小游戏必须具有了这样的特色,简单易玩,却能给人制造紧张感,有时还能利用一些攀比心理。本游戏也基本具有了这样的特色。github
游戏以秒数做为计分,随着时间的增长,Enemy粒子的运动速度会愈来愈快,躲避难度也就愈来愈大。游戏中的计秒实现比较简单,就是用setTimeout来实现,这里不使用setInterval,缘由在第一章已经大体讲过了,就是考虑到准确性的问题。canvas
//index.js function initTimer() { holdingTime = 0; holdingLevel = 0; clearTimeout(timer); let time = function() { timer = setTimeout(function() { holdingTime = +timeEle.innerText + 1; timeEle.innerText = holdingTime; //每隔10秒加速一次 if (holdingTime % 10 === 0) { holdingLevel++; levelEle.innerText = holdingLevel; for (let i = 0; i < enemys.length; i++) { //Enemy粒子速度增长 enemys[i].speedUp(); } } clearTimeout(timer); time(); }, 1000) }; time(); }
每隔10s, Enemy粒子的速度增长一次,Enemy中封装了speedUp
方法。微信
//Enemy.js speedUp(speed) { this.speed += speed || 0.2; }
在技能粒子中,有一个护盾粒子。吃了护盾后,撞击Enemy粒子能增长分数。实现起来也很简单,直接修改计分板上的分数就好了。框架
//Player.js let score = document.getElementById('time').innerText; document.getElementById('time').innerText = (+score + REDSCORE);
粒子的初始生命值有三条,每次撞击到Enemy粒子都会减小一条,而若是撞击到视界的边界则会直接狗带。这里咱们须要增长一个游戏结束的画面。给出最后的分数。学习
开始和结束画面都是经过DOM实现的,这部分比较简单,就不作具体介绍了。this
其实在游戏的评分机制上还能够作不少改进,好比增长排行榜,或记录本身的最优成绩,并可分享到朋友圈等。这部分能够极大增长游戏的热度。 读者能够本身展开想象,对玩法进行扩展。spa
当我在微信打开游戏的时候,发现开始画面和结束画面的图片加载很慢。致使DOM结构出来了,图片却迟迟没看到,无法给玩家准确的提示。因此须要增长一个图片预加载的功能。固然这也是每个网页游戏框架必备的功能。
这部分功能直接参考了阿里的一个游戏框架Hilo,并把它抽象到loader.js
。读者可自行查阅实现细节。
抽象后在入口处预加载所需的图片:
//index.js let loader = new Loader(); let source = [ {src: 'assets/images/number.png'}, {src: 'assets/images/over.png'}, {src: 'assets/images/sprites.png'} ]; loader.load(source, function() { start(); //开始游戏 });
预加载的时候还须要有个提示画面来告知加载进度。
进度条的实现也独立成一个文件loading.js
,并暴露一个外部API给游戏使用。
咱们还须要将预加载插件和进度条结合起来,每一个图片加载完成后,loader会触发一次load
事件,用一个计数器统计加载的图片数,除以总数获得一个进度比例。而后将这个比例barRatio
传给进度条。让其渲染出相应的进度。
//根据加载进度渲染进度条 let loaded = 0; loader.on('load', e => { ++loaded; barRatio = loaded / source.length; }); //进度条渲染 (function loading() { drawLoading(barRatio); if (!loadingFinish) { raf(loading); } })();
须要注意的一点是,进度条是经过canvas画布实现的。因此进度canvas的draw方法是在不停运行的。若是每张图片加载完的时候才改变进度条的位置,就会形成进度跳跃式地前进,没法连续顺滑加载的效果。
这个逻辑在loading中经过一个判断来解决。
//loading.js let currentBarWidth = bar.total * ratio; if (bar.width < currentBarWidth) { bar.width += 2; }
保证进度条每次增长只能是2。而不是直接让bar.width = currentBarWidth;
至此整个游戏的开发就介绍到这了,主要仍是讲游戏的实现思路。 游戏中仍是有挺多细节处理的,这些真的要亲自动手写一下才能了解。
本教程的初衷就是想让读者能对H5游戏开发有个宏观的了解,知道怎么入手。想起几周前本身要写这个游戏的时候还无从下手,现在也完成开发并写了几篇总结,算是有所沉淀。
其实H5游戏开发远比这个复杂,本游戏只是基于画笔实现,尚未涉及到图片的绘制,坐标轴转换等等。还有不少了要学习的东西啊。固然这只是本身一时的兴趣尝试,等何时心血来潮了,说不定再写一个系列呢。