【问题标题】:Cannot force a canvas refresh in javascript无法在 javascript 中强制刷新画布
【发布时间】:2021-12-16 11:35:01
【问题描述】:

我试图让游戏定期刷新画布,主循环包括一个重播屏幕的函数和一个让计算机计算移动的函数(如果轮到它的话)。玩家可以选择 1-9 步,然后,如果计算机在玩家最后一次移动后还没有离开,它将使用一个非常深的树来计算它的移动。计算机移动需要几秒钟才能移动。尽管在计算机移动之前已经更新了画布,但直到计算机离开后它才会刷新,这意味着玩家和计算机移动是同时显示的,而不是顺序显示的。我可以做些什么来确保画布每 100 毫秒更新一次,而不是在计算机计算出它的移动之后才更新?

function playGame() {
    function doKeyDown(evt) {
        console.log(evt.keyCode)
        if (evt.keyCode > 48 && evt.keyCode < 58) { 
            game.makeMove(evt.keyCode-48); // 1-9 are user actions
        }
    }

    function mainLoop(ctx, game, board) {
        board.showBoard(ctx); // display board
        game.makeMove(0); // zero is computer move
    }

    Canvas.canvas = document.getElementById("myCanvas");
    let game = new Game();
    let board = new Board(game);
    window.addEventListener( "keydown", doKeyDown, true);
    Canvas.ctx = Canvas.canvas.getContext('2d');
    setInterval(() => {mainLoop(Canvas.ctx, game, board)}, 100);
};  

document.addEventListener('DOMContentLoaded', playGame);

【问题讨论】:

  • 欢迎来到 JavaScript 的单线程特性。当 JS 主动运行时,浏览器不能做任何事情,包括渲染屏幕。
  • 如果可能的话,考虑使用 Web Workers 并行计算一些东西。

标签: javascript canvas 2d-games


【解决方案1】:

有几件事绝对可以帮助您确保画布按预期刷新。

  1. 将计算密集型任务转移到 Web Worker。

  2. 使用window.requestAnimationFrame() 而不是setInterval() 进行渲染。

网络工作者

Web Workers 非常适合将计算密集型任务转移到; Web Workers 的 MDN 文档指出,“工作线程可以在不干扰用户界面的情况下执行任务。”这将允许在不阻塞渲染线程的情况下计算计算机的移动。

有关 Web Workers 的更多信息,请参阅:Web Workers (MDN Web Docs)

window.requestAnimationFrame()

window.requestAnimationFrame() 方法是当前实现动画的最佳方法。本质上,它会导致浏览器在下一次重绘之前执行提供的回调。这是对之前的setTimeout()setInterval() 方法的改进,因为它只在浏览器重绘之前调用回调,换句话说,它减少了使用setTimeout()setInterval() 可能导致的不必要的计算。

有关window.requestAnimationFrame() 的更多信息,请参阅:window.requestAnimationFrame() (MDN Web Docs)

有关为什么选择 window.requestAnimationFrame() 而不是 setTimeout()setInterval() 的精彩短文,请参阅 Matt West 的这篇文章:Efficient Animations with requestAnimationFrame

工作示例:

我已经使用codesandbox.io 编写了一个小的工作示例;正如我所描述的,它使用 Web Workers 和 requestAnimationFrame()。请注意,它使用计时器代替计算密集型任务,它使用 5 秒计时器来模拟计算机移动,并使用 1 秒计时器来模拟玩家移动。

代码沙盒:Web Worker & requestAnimationFrame() Example

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 2014-12-12
    • 2013-08-30
    • 2010-12-04
    • 2011-06-26
    • 2020-04-19
    相关资源
    最近更新 更多