最早接触贪吃蛇是在诺基亚老式单色手机上,曾经有很长一段时间都迷恋这款游戏,尽管当时丰富的3D网游已经遍地都是。贪吃蛇算不上智力游戏,规则简单,于是我就想写一个JavaScript版本的贪吃蛇。
源码直接看Demo就有: 点这里试玩
分析游戏规则与需求
- 在一个范围内计算出n*n列格子(根据屏幕宽高)
- 画出蛇在中间位置 (计算)
- 蛇能移动 (定时处理)
- 蛇能控制方向 (键盘事件)
- 撞边或者尾巴就Game over (有一个Game over规则)
- 吃蛋(预计下一步坐标与蛋坐标是否相等)
- 每吃一个蛋蛇身加长一个单位(节点操作)
- 随机位置出蛋(不要在蛇身上)
- 每吃一个速度越快(定时函数处理)
以上大概是游戏的基本实现步骤,我们一条条来分析。
计算出列宽与列高
网页上的长度单位以px(像素)为基本单位,从直观上来看,蛇是由多个一定的长与宽基本单位组成的,蛋就只有一个基本单位,移动时可以根据每一个基本单位进行移动。得出每一个方块的基本单位以后,算出游戏区域的宽与高。
我使用的是自适应去自动画出这块游戏区域,列数我固定是50,然后算出每一个基本单位的宽高像素,因此浏览器小的看起来基本单位可能会小,浏览器大的看起来可能会大。
我最大化浏览器算出来的基本单位28px
我拉小后算出基本单位10px
画出蛇在中间位置
其实这是根据每个人的爱好设计,我喜欢游戏一开始蛇是在中间位置,有些贪吃蛇是在左上角往下跑出来的,只要你知道怎么控制位置,那剩下的你摆放在哪都无所谓。怎么能够算出中间位置呢?
其实很简单,经过第一步构建游戏画面以后,我们已经知道列数与行数,比如我的单位宽度是10像素,然后我们算出x与y坐标,然后赋给left与top就好。
x坐标:
50/2 = 25,25 * 基本单位宽 10px = 250px
y坐标:
60/2 = 30,30 * 基本单位宽 10px = 300px
这样就算出了默认蛇出现的位置接近中间位置了。然后把x与y赋值给蛇身即可。
蛇跑动
我们知道了基本单位以后,就按照多少毫秒内移动一个基本单位,从而实现蛇的移动。比如蛇从上往下跑,目前x=50,y=50。蛇的基本单位是10px,那么要计算下一步蛇的位置直接y=50+10即可,因为是向下移动所以x轴不需要改变。
配合setInterval
即可实现周期内一步一步移动。
控制方向
要控制方向,因此我们需要建立一个方向控制机制,可以使用键盘事件来监听上下左右键的键值,如果按用户按下左键,下一步蛇移动的时候就要把当前的x轴减去基本单位10px即可,往上就把y轴减去10px。这样就能实现利用键盘的方向键控制蛇的走向。
实现方法:
可以在body增加onkeydown
键盘按下时间,然后利用event获取键盘keyCode,然后做判断就好。比如方向下键的keyCode=40、方向上键的keyCode=38。
Game Over规则
首先来考虑撞边,因为游戏的列数与行数我们都知道,所以只要预测蛇头的下一步x与y轴是不是超出了即可,比如x与y轴不能小于0,负数就跑出外面了,以及游戏区域的宽高减去x与y轴要大于等于蛇的基本单位10px,否则也算撞边了。
至于如何判断是否撞尾巴很简单,利用一个数组动态记录当前蛇身的每一个单位的x与y轴,然后预计下一步蛇头的x与y轴如果重合在蛇身的记录中,那么就撞尾巴,否则就没事。
吃蛋
吃蛋就很容易了,判断一下蛇头的下一步x与y轴是否与蛋的x与y轴相等,如果相等,就是吃上,不相等就吃不到。吃上蛋以后就把蛋的节点remove即可
越吃越长
这个就涉及到节点操作了,每吃一个蛋以后,直接在蛇尾添加一个单位,即可以实现越吃越长。
随机出现蛋
这里比较麻烦,蛋的位置要随机出现在游戏区域内的任何一个地方,但又不能出现在蛇身上。其实利用数组也可以实现着一个功能,即计算出区域内除蛇身以外能出现蛇蛋的所有x与y轴的坐标存到一个数组里,然后随机数组索引即可实现。
我有点懒,直接就随机计算出来,然后再比对是否出现在蛇身上?出现再重新随机一次坐标,直至可以。
吃蛋加速
其实这个处理很简单,在setInterval的时候直接赋给一个变量 ,如果每提速一次直接clearInterval后重新把最新的速度setInterval即可。这里有点建议,我认为setInterval的速度最低50毫秒即可,或者40毫秒也可以,再快就影响性能了,所以在游戏中我最快也只到50毫秒。
最后
以上步骤,只是说了一下实现步骤与思路,具体代码可以看我的Demo里有源码。这里要说一下蛇的摆动效果实现,蛇的摆动效果是由很多个基本单位组成,当蛇的移动方向放生改变的时候,你只需要把蛇的最后一个单位remove掉,然后计算出一个新的基本单位添加到预算出的x与y轴的位置即可实现蛇的摆动效果。
为了增加可玩性,我在游戏中增加了时间倒计时、远程炸弹等,这些都是画蛇添足,当然也是锻炼思维的一种方式