3首先我们在上一次代码基础上进行整理,把 Vec2 类移到 math.js 类中 , 由于以后还需在 math.js 文件中暴露其他方法或类所以没有使用 export default 而是使用 export。
再把 Entity 类移到新建的 Entity.js 文件。
继续整理代码,将 mario 相关的代码移至新建的 entities.js。mario 也是 Entity 类的一个实例。以后所有在游戏中出现的人物都将是 Enitiy 类为基础。
对代码进行调整,使用
将 sprites.js 文件中 loadMarioSprites方法名修改 loadMarioSprite ,去掉方法名后表示复数的s。这样看起来就更合理了,顺便说一下,我们在定义方法、类和变量名称时,尽量用有意义的英文,且不要图省事,用拼音代替。再多说一句,也要注意一下像单复数这样基本语法的问题。这样定义好了,即使不写注释,其他人通过阅读代码也可以理解变量或函数用途。
我们将 loadMarioSprite 也整合到 createMario 方法中。
然后在 main.js 中引用之前分离出去的方法和类。
代码也做适当调整如下图。
最后将 createSpriteLayer 方法移动到 layers.js 文件中。
本次分享将 mario 的运动调整为相同时间内有相同的运动轨迹。也就是不同(有快有慢)计算机上表现一致,只是在慢的计算机上会有些卡顿效果。
为专注观察 mario 的运动轨迹,就注释掉背景图层。
requestAnimationFrame的回调函数会接收到一个参数 time,这个参数就是浏览器开始调用 requestAnimationFrame添加进来的回调函数时(每次重新渲染页面内容之前),performance.now()的返回值,可见,这是一个从页面开始加载时,包括白屏的时候哦,直到当前时间的时间间隔。时间间隔长,mario 运动速度就慢,相反时间间隔短 mario就运动的快。也就是每秒帧的数是有快慢变化的。可以想象一下,性能高电脑运行游戏速度就比性能低的电脑运行游戏快。
只要记录下上一次的时间,并用当前时间减去上一次的时间,就是每一帧的时间差。这个时间差就是逝去的时间,要变化的动画属性什么的,我们肯定设定了变化速度。计算出当前动画属性,例如高度,应该处于什么状态,可以通过 路程 = 速度 * 时间计算出来,这样就可以实现流畅的动画效果,并且标签页处于后台运行时,渲染次数大大减少,时间差也变长了,仍然可以确保随着时间的流逝,动画属性的值仍然是正确的,即使页面性能太差,帧率下降,虽然用户看起来卡了,但属性的值仍然是正确的。这也是为什么低配置的电脑虽然玩游戏画面卡顿很厉害,但人物还是跑了很远的距离,而没有一动不动,因为他们走的路程=速度时间*?? !
我们先模拟不同(有快有慢)计算机效果,我们通过 setTimeout 设置不同时间间隔来模拟 requestAnimationFrame 在不同计算机上由于配置表现不同的时间间隔。如果高配时间间隔就短,效果为单位时间运动距离远。1000/60 要比 1000/1 运动的快,用 1000/x 来表示 一秒钟/帧数
那么也就是帧数高,高配的电脑运动快,单位时间距离远。
切换回 requestAnimationFrame 然后打印一下时间看效果。
这样开始时间间隔不直观,我们来通过计算两次渲染间时间间隔,并将两次渲染间的时间间隔打印出来。
发现每次渲染的间隔时间各不相同,所以mario运动相同距离时间不同。
所以我们希望时间间隔长,mario 运动距离也是应该长,所以可以将 deltaTime 作为参数来调整 mario 在不同时间间隔运动不同距离,将 deltaTime 传入 update 方法。
调整后刷新界面,发现 mario 没有反应,我们需要调试一下程序。
打印 mario 的位置(pos),发现位置为 NaN,这是什么原因呢?这是由于第一次 time 为 undefined , undefined - 时间为就为 NaN.
我们可以将 time 初始值赋值为 0 来解决此问题.
这样 mario 就运动起来了。但是看不出来效果,这是由于给的值不合理的原因
我们 delatTime 除以 1000。
将 mario.pos 和 mario.vel 从 createMario 方法中移回至 main.js 文件中。然后调整 mario 速度和重力系数值。
这样调整 mario 的运动就是和时间一致了,
我们再次模拟一下在不同配置计算机下 mario 的表现。注意到在相同条件下运动轨迹还是不固定。每次跳的高度不同,这不是我们想要看到的效果。
我们将 deltaTime 写为固定值,这样每次运动轨迹就一致了,但是之前的问题就又回来了,在高配计算机上运动的帧数多,运动的快,低配与之相反。
这里我们通过一个小技巧来解决这个问题。然后 timer 整理到 Timer 类,如下图。这里先定义一个 accumulatedTime 变量并初始为 0;然后将每次渲染的时间间隔递增到 accumulatedTime 这个变量,然后当 accumulatedTime 累计到大于 deltaTime 才进行更新 mario 位置,并且减去 deltaTime。这样就解决高配频繁更新mario 位置,低配更新频率慢的问题。这样 mario 位置就和电脑的快慢无关,仅与时间有关了。
请关注我的公众号,为您推送更快更好的文章