前端第一次做游戏,竟然选择做个3D游戏

5,735 阅读6分钟

2014070109573068477.jpg

关于自己

大家好,我是腿腿,一个喜欢玩游戏的前端。
疫情期间被隔离了一段时间,正好能抽出实现做点自己想做的事情————做个游戏。
CocosCreator可以用TS写游戏,我本身也是个前端,上手简单些,在撸完官方文档后就马上开始着手了。

关于游戏

一个塔防游戏,3D+2D的画面,也就是角色是3D的,但是地图是2D的。

tutieshi_640x296_10s.gif
差不多做了一个多月,能够实现塔防的基本要素了:地图、出怪、放置守卫、升级等等...

点击这里在线体验

体积较大,加载比较慢,大家担待~
其实可以编译成小程序的,但是发布需要各种资料,而且我也没做完....

项目地址

游戏代码我放在了GitHub上,有兴趣的同学可以拉下来玩一玩。

GitHub地址:GitHub - leglegend/spirit-td: 精灵塔防,一款塔防H5游戏

master分支是项目地址,需要通过CocosCreater打开编译。
main分支可以直接运行到浏览器。

游戏制作

做之前总觉得,这么小个游戏,应该不是很费事吧~
上手后真的啪啪打脸,需要考虑的东西太多了,而且3D的游戏有太多之前没接触过的几何问题...

QQ截图20220920215910.png

打开可以分成以下几个部分吧

1. UI界面

游戏的UI其实才是和前端最契合的部分,每个空间都有宽高边距内部图片填充等等,其关系就和HTML的标签如出一辙。

QQ截图20220920220336.png

通过这张图可以看出,UI完全是在一个二维空间绘制的,上面的文字内容完全没有双向绑定,在数值发生变化是,只能手动去获取控件,然后填充新的值(感觉回到了jQuery时代)。

UI结构比较简单,左上角显示生命和金钱,选中英雄时出现技能面板,并会根据英雄所在位置选择从左面划出还是右面划出。最右边是英雄列表和开始按钮,可以拖拽英雄放置到地图上。

2. 地图

地图其实就是一张图片,但不完全是一张图片。

QQ截图20220920220336.png

上图最上面是摄像头和光源,摄像头看到的就是我们玩游戏时屏幕看到的内容,拉近就会放大,推远就会缩小。摄像头和地图垂直,2D的地图就完整的显示在了显示器中:

QQ截图20220920220336.png

由于地图本身是45°视角,所以看起来也有点立体的感觉,这种感觉在我们将角色倾斜45°放上去之后会更加明显。

但是地图的内容还远远不止如此,我们需要怪物按照地图上的路径行进,而且英雄不能放置在路上和障碍物上。

QQ截图20220920220336.png

在路上放上了透明的障碍物,障碍物有碰撞体积,英雄不能放在上面,这里后面会详细的说。

3. 怪物

image.png

怪物和英雄都是3D的,资源都是从网上找的,有些自带骨骼和骨骼动画,有些则只有模型,就需要自己用3DMAX添加上骨骼还有自定义的动画。
这个真的难,对于我一个程序员来说,我竟然还要学骨骼动画,本就不剩多少的头发,更少了...

image.png

怪物还有很重要的一点就是按照行进路线行走,地图上我们已经提到了在地图上放置障碍物,只要设置怪物沿着障碍物行走就可以了~

image.png

4. 英雄

英雄首先要做到的一点就是从英雄列表拖拽到地图上。这个看似简单的问题,其实没那么简单。
上面我们提到了UI界面,其实就是一个二维的平面,和平时写HTML没有本质区别,但是英雄所在的是一个三维空间,也就是说UI和空间并不共享坐标系,我们需要在一个平面中把一个物体投放到一个三维的空间。
这里就用到了摄像头,我们可以想象自己的屏幕和摄像头同处一个平面,触摸屏幕时,触摸点有一个垂直向下的射线射向地图,这时候地图上就有一个与之对应的点,就是英雄应该放置的位置。同时还要考虑英雄不能够放置在障碍物上,钱不够买不了英雄等等问题。。

image.png

英雄有攻击范围,可以升级技能,这里工作量会很大,所以我只做了技能描述,实际应用到游戏中的效果还没做。

怪物和英雄最让人头疼的点就是,他们处在一个二维的地图上,如何才能让他们的运动更自然。
英雄是倾斜45°放置在地图上的,这样有立体感,直接丢在地图上那就只能看到一个头顶了。
由于是倾斜放置,在转身时就像转圈似的,想要自然的转身,那另外两轴就要填补倾斜带来的角度开销。
我知道这样子说很抽象,也确实不好描述,总之最后就是cos,sin函数搞定的,想不到初中数学学的东西,现在竟然用到了。

5. 子弹

子弹是连接英雄和怪物的重要角色,他通过英雄射出,打到怪物身上,需要判断子弹和怪物是否碰撞,然后减血。

image.png

管理后台

为了方便调试各种数值,我把地图/英雄/怪物/技能的信息都放在了服务器上,游戏启动时从服务器读取信息,也方便我随时调试:

image.png

后台通过uniCloud搭建并托管,像添加英雄啊设置技能等操作都能很方便的完成。

关于代码

上面提了这么多,也没有给出点代码,实在是不好放出来,有兴趣的同学可以看GitHub上的项目,这里仅简单的提一下。
CocosCreator使用的TypeScript,并且是class写法,写代码的时候总有种写java的错觉。
由于游戏中大部分内容都是复用的,比如说英雄、怪物、子弹,但是不同角色之间肯定是有差别的,位置啊,等级啊,就算是同一个英雄,数据也是不同的,所以CocosCreator的这种class写法就比较合理,当拖拽出来一个英雄时,就需要new一个英雄:

export class Player extends Component {
  @property({ type: Node })
  public body: Node | null = null // 英雄对应的模型
  private attackRange: number = 3 // 攻击范围
  private attackTime: number = 0.5 // 攻速
  
  private _curPos: Vec3 = new Vec3(0, 0, 0)  // 当前角色位置
  
  setData(){...}
  
  doAttack(){...}
}

上面是英雄的class简化版,有其相关的信息,在实例化后上面的属性和方法就会变为实例属性和实例方法,供每个英雄实例调用。

写在最后

想不到玩了十几年游戏,最后真的能亲身经历去做一款游戏,但其实很多地方跟自己想的差很多。代码只是一部分,素材,模型,音效等等很多元素才能凑成一款游戏。看似很小的一款游戏也是费尽很大心思才能够做出来。

一个前端程序员的游戏制作经历,虽然不太可能真正踏足游戏行业,但是能够真正投身自己的爱好一次,也值得了~