其实在2016年,我就准备写这个小游戏了。可是奈何当时没文化😌,也尚未转行成前端。既没有面向对象的思想,也不懂什么寻径算法,更不了解模块化,只是掌握了canvas的基本知识。因此以当时的水平,就搞了一段时间后,把羊,狼,砖块画了出来,具体怎么运动?搞不下去,就搁置下来了。时间飞逝,这个小游戏就这么静静地烂尾了两年多,直到前几天,在codepen上看到了一个寻径的demo,才又从新捡起来。css
如今再捡起来,感受驾轻就熟应手了许多,尽管中间也碰到了一些坑,但不至于无从下手。尽管还有许多能够改进的地方,代码写的也不怎么规范,断断续续搞了一周多,好歹搞出来一个能用的版本。下面说说开发过程当中遇到的一些问题,和学到的知识。html
这里是试玩地址:https://www.imgss.top/demo/wAs/
github: https://github.com/imgss/wAs前端
在手机上打开这个小游戏时,游戏画面会变得比较模糊,这是因为手机屏幕的css尺寸和真实的物理像素数量是不同的。这也是window.devicePixelRatio
这个属性存在的意义。同时canvas的css宽度和canvas自己的宽度也是这个区别。举个例子:git
一个手机的 devicePixelRatio 是3,canvas的css宽度是500px,要想使canvas绘制出的图片不模糊,须要给canvas的宽度设置成多少?答案是500 * 3 = 1500。写成代码是:github
var ratio = window.devicePixelRatio; var oldWidth = canvas.width; var oldHeight = canvas.height; canvas.width = oldWidth * ratio; //根据radio设置新的width,解决图片模糊问题 canvas.height = oldHeight * ratio; canvas.style.width = oldWidth + "px"; canvas.style.height = oldHeight + "px";//使canvas在屏幕上的显示和以前保持一致
这也是整个游戏最难的地方,游戏中羊是在不断运动的,狼须要根据羊当前的位置计算出行动路径。在实现中,我参考了codepen上的这个demo,具体的思路是,用一个二维数组来表示整张地图,从目标节点(羊的位置)开始,向上下左右遍历,若是碰到墙或者边界就中止,并标记为访问过。再根据这些节点的兄弟节点进行遍历,直到找到狼所在的位置,或者整个地图所有搜索了一遍。算法
当在遍历中找到狼的位置后,进行一次回溯,就拿到了狼的运动路径。canvas
整个算法在search.js中,是根据上面的那个demo修改的,实现了一个pathFinder类;数组
export default class Pathfinder{ constructor(gridData, targetPosition, foundCallback) { this.gridData = gridData; this.targetPosition = targetPosition; this.foundCallback = foundCallback; this.width = this.gridData[0].length; this.height = this.gridData.length; } // 将二维地图转换成节点数据 parseGridData() { ... }
了解更多的寻径算法知识能够看这篇文章: https://www.redblobgames.com/pathfinding/a-star/introduction.html模块化
在开发过程当中发现手机端的操做不是很流畅,找到了一个叫nipplejs的虚拟摇杆的库。使用方法也很简单,虚拟摇杆能够是固定在屏幕的某个地方,也能够是显示在屏幕的任何一个地方。可是在实际中使用发现,用摇杆操做,很容易致使羊多跑或者少跑一两格,对于这个游戏来讲,不如箭头控制精度好,最终仍是放弃了。优化
游戏里还用到一个sweetalert库,用来作弹出框的,没有依赖,用起来很方便(实际上是作不出酷炫的弹窗特效)。
整个过程当中,加深了本身对算法重要性的认识,虽然前端不多涉及高深的算法,可是多懂一点算法知识绝对大有裨益。小游戏中还有许多值得优化的地方,也还有几个bug,这些之后再慢慢优化吧。(完)