0%

Chrome小恐龙的实现小技巧

嘿,我带着小恐龙回来了!


在上次对canvas的初探之后,我迅速地整起了Chrome小恐龙。当然,如果只是在上次的基础上做少量修改,那就没意思啦,所以这次用了些不同的方法去实现。最主要的区别是,这次用了ES6的Class语法,将所有组件按类分开进行表示,在一定程度上实现了解耦,这样看起来就舒服多了。除此之外还有一些其他方面的改变,下面就写些值得记录的小点。

照例,项目地址在这里,也可以在这里召唤小恐龙陪你玩耍。

代码结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
├───index.html

├───images
│ ├────dinosaur.ico
│ └────sprite.png

└───js
├────base.js
├────cactus.js
├────cloud.js
├────cover.js
├────dino.js
├────gamearea.js
├────main.js
├────score.js
├────still.js
└────util.js

这下每个元素都有自己的类了,按照字母排列顺序依次为:

  • 地面
  • 仙人掌
  • 云朵
  • 幕布
  • 恐龙
  • 整个画布
  • (主函数)
  • 分数
  • 无需刷新的内容
  • (工具函数)

sprite图

所有图片资源被放在了一张大图内,因此需要通过截取相应位置来获得相应图片。

通过这篇DRAW IMAGES AND SPRITE ANIMATIONS发现了如何在画布上显示部分图片:context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height),其中img为原始sprite图,sxsy表示所需区域起始点在原始sprite图上的坐标,swidthsheight表示所需区域在原始sprite图上的大小,后四个参数则为将所需区域放置在canvas上的位置和大小信息(“s” is for “source”)。

通过这个工具SVG Sprite Position Finder Tools可以获取sprite图中某部分的sxsyswidthsheight

动画实现

跳跃

这次的跳跃和上次Flappy Bird跳跃的不同之处在于,这次有地面的支持,因此需要设置“只在空中受重力加速度影响”,触发条件也需要仔细看看。

我差不多是这样得出判断条件的,左下角情况跳变为-20(或其它合适的负数),右下角情况跳变为0,写成代码的话就是:

眨眼

仔细看的话,会发现在恐龙会在等待页眨眼。我最开始是用everyInterval()来实现的,每隔指定帧数就切换恐龙图片,但发现它的结果是1s闭眼、1s睁眼、1s闭眼、1s睁眼…而不是想要的1s闭眼、5s睁眼、1s闭眼、5s睁眼。于是想到这种方法:

起始动画

在等待画面中敲空格键会触发开场动画,小恐龙跳起、地面向右展开。向右展开的动画是还是思考了一会儿的:可以先绘制完整的地面,再拿一块白色的幕布挡住,当敲空格键时让幕布不断向右移动,来实现向右“展开”的过程。

注意点

在Class内部的函数内调用同级的内部函数时要注意丢失this的问题,解决办法可以是let that = this再传递that、用箭头函数获取外部this
比如这样写是会出错的:

可以改写成这样:

好了,我们的小游戏就告一段落,之后如果有空并且有想法的话,我再来开发自己的小游戏吧!