我正在尝试使用 react 开发经典游戏教程how-to-make-a-simple-html5-canvas-game。
一切都很顺利,直到我发现我的动作有点小故障,在线测试链接和代码。
虽然用 JS 编写的原始游戏要流畅得多:
所以我深入研究了一下,发现实际的 fps 是不同的:
反应:
奇怪的是,在我向 calc fps 添加了一些代码之后,我在 react hook 和 useEffect 中都得到了“60 fps”:
// log interval in useEffect
useEffect(() => {
console.log('interval', Date.now() - renderTime.current);
renderTime.current = Date.now();
});
// calc fps in hook directly
fps: rangeShrink(Math.round(1000 / (Date.now() - time.current)), 0, 60),
// render
<Text
x={width - 120}
y={borderWidth}
text={`FPS: ${fps}`}
fill="white"
fontSize={24}
align="right"
fontFamily="Helvetica"
/>
定位问题
我添加了一个对比鲜明的画布,每次heroPos
更新时都会呈现。它让我在 chrome 开发工具中获得 60FPS。现在问题肯定是由我正在使用的画布库引起的:react-konva。
const canvasRef = useRef(null);
useEffect(() => {
const ctx = canvasRef.current.getContext('2d');
if (backgroundStatus === 'loaded') {
ctx.drawImage(backgroundImage, 0, 0);
}
if (heroStatus === 'loaded') {
ctx.drawImage(heroImage, heroPos.x, heroPos.y);
}
}, [backgroundStatus, heroStatus, heroPos]);
定位问题
我找到了问题,它是由使用的batchDraw react-konva
引起的:
改变这条线后,我现在可以得到 60fps 的移动。
- drawingNode && drawingNode.batchDraw();
+ drawingNode && drawingNode.draw();
根据他们的文档,batchDraw 会绘制the next animationFrame
。但react
它本身也用于RAF
触发下一次道具更新,所以batchDraw
这里发生2 frames
在 i 之后setHeroPos()
。
解决方案:
我要向他们的项目提交一个拉取请求。