前言
想参加游戏活动,但一点儿思路都没有,今天突然发现活动就要截止了,最后一天了,真不能再摆下去了。
于是花了两个小时复刻了一个植物大战僵尸,只有一关,甚至没有开始按钮🤷♂️
大家可以体验一下:tower-defense-mancuoj.vercel.app/
【24日晚,大更新】
- 修改文字,颜色,样式
- 添加美术素材
- 添加按钮
- 添加提示信息
- 如果可能还会继续更新...
下面说一下整体的思路做一个教程,权当是《抛砖引玉》,有兴趣的朋友可以继续完善,我大抵是没时间继续做下去了【此处教程是最开始的基础代码,点击查看最新代码】
游戏界面
脑海对植物大战僵尸的记忆,就是5行,上面还有一行控制栏,几列记不清楚了,这里就当10列吧(为了使用码上掘金,做了同比缩小,与原版代码有所区别)。
把每一个小方格设为50px,于是我们得到了现在的游戏界面:
我们创建了一个Cell类,同时记录鼠标位置,每次在游戏界面移动鼠标,就会显示之前设置号的小方格标识植物安置点,其中有几个点需要说一下:
- 使用
requestAnimationFrame()
进行每次的重绘,每个绘制函数都使用handleXxx()
的格式 。 collision
碰撞函数非常简单,画两个方块就能轻松理解- Cell事先存在,只要鼠标与Cell位置重合就会调用
draw()
画出 - 记录鼠标位置时,需要找到canvas距离边界的距离,绘图时减去该部分
植物 + 炮弹
与Cell类似,我们的植物和炮弹也采用面向对象的方式,效果如下:
- cellGap是因为
collision()
在边角重合时也会判定碰撞,之后的敌人伤害会有bug - 每次放置植物需要判断位置是否合适,同时消耗☀
- 植物类内置一个timer,用于控制发射炮弹的频率
- 炮弹超出
canvas.width
后,用splice(i, 1)
删除该炮弹,之后删除全部使用该函数
僵尸 + 胜利 + 失败
依旧是面向对象,效果如下:
- 僵尸本身的逻辑并不复杂,只是与植物,炮弹进行交互比较麻烦
- 每次重绘时
frame++
,相当于计算帧率,设计一个间隔时间生成僵尸,这个间隔并不是固定的。 - 内置timer,用于加速,移动速度越来越快
- 每杀死一只僵尸,会得到其血量/5的分数,当分数达到设定值且僵尸数组为0,游戏胜利且不再生成僵尸
- 僵尸碰到左边界时,游戏失败,不再进行重绘
- 每次生成僵尸时用一个数组记录僵尸在哪一行,方便植物在本行没有僵尸时停止射击,杀死僵尸时删除该位置信息
交互
与植物,炮弹的交互逻辑:
- 当本行有僵尸时开始射击,没有就停止
- 当僵尸与植物碰撞时,僵尸停止运动,植物扣血,植物死亡时删除,同时恢复僵尸速度
- 炮弹与僵尸碰撞时,僵尸扣血,僵尸死亡时删除僵尸并删除位置信息
随机☀
为了方便赢,特意添加了随机☀,依旧是同一套代码逻辑,这里不多解释了
后续
非常简单的代码,应该没有后续了🤷♂️