HTML Canvas 显示不完整的框架。 (反应开销)

问题描述 投票:0回答:1

我目前正在为自己制作一个 HTMLCanvas2D 引擎,但正如标题所示,画布偶尔会显示未完成的框架。何时或多久这样做并没有一致性。我认为问题是与我的结构以及反应更新组件的方式相结合的。 (如果这很重要的话,树中这些函数下面的几乎所有内容都是基于类的,而不是像反应开销那样起作用)

export function GameScreen( ... ) {
  const Canvasref = useRef<HTMLCanvasElement>(null);
  const Globalvars = UseGameContext(); //Get React information from outside.
  
  const Gameinput: InputHandler = InputHandler.getInput(); //deals with Event Listeners
  const Logic: GameLogic = new GameLogic(); //Entry point into my actual logic.

  useEffect(() => {
    function game() {
      RenderLoop(
        ({ canvvas, ctx }) => {
          ... checks for a valid canvas ...
          ... add Event listeners ...
          window.addEventListener("resize", () => { canvas.height = window.innerHeight; 
            canvas.width = window.innerWidth; }); 
            //Window listener to make the canvas always the size of the Webpage if that matters here
          Logic.Initialize(ctx);
        },
        (delta, { canvas, ctx }) => {
          ...Savety checks...
          Logic.updateLogic(delta);
          Logic.drawFrame(delta);
        }, id = "myCanvas";
      );
    }
    game();
  }, []);
  return (< canvas id="myCanvas" ref={Canvasref}></canvas>);
}

//the function implemented above
export function RenderLoop(
    onInit: (context: {
        ctx: CanvasRenderingContext2D;
        canvas: HTMLCanvasElement;
    }) => void,
    onUpdate: (
        delta: number,
        context: {
            ctx: CanvasRenderingContext2D;
            canvas: HTMLCanvasElement;
        }
    ) => void,
    id = "myCanvas"
) {
    const canvas = document.getElementById(id);
    if (canvas && canvas instanceof HTMLCanvasElement) {
        const ctx = canvas.getContext("2d");

        if (ctx) {
            onInit({ canvas, ctx });
            window.requestAnimationFrame(
                Update((delta) => onUpdate(delta, { canvas, ctx }))
            );
        }
    }
}

//delta calculation and the recursive loop to rerender every frame
const Update = (onUpdate: (delta: number) => void) => (time: number) => {
    if (elapsedTime !== null) {
        const delta = time - elapsedTime;
        onUpdate(delta);
    }
    elapsedTime = time;
    window.requestAnimationFrame(Update(onUpdate));
};

class GameLogic {
...lots of things ...

drawFrame(delta: number) {
  this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.width);
  this.GameObject.forEach((object) => { object.Draw(delta)});//What I draw should not matter
}

我尝试删除clearRect,假设这可能是原因,但虽然不太明显,但它仍然发生在彼此相邻的代码行中绘制的对象之间。据我所知,逻辑和函数在每一帧中被调用,这纯粹是视觉上的。画布/窗口的大小和对象的数量似乎都没有任何明显的相关性(我现在有 1 个对象还是 20 个对象)。

如果还有其他可能对此很重要的事情,请告诉我我的代码库总体来说有点太大,无法发布所有内容,但这应该给出应该重现问题的最小值的概述

html5-canvas 2d game-engine react-typescript renderer
1个回答
0
投票

由于一个不相关的错误,我偶然发现了真正的原因。

HTMLImages 是异步加载的。我已经在前面的drawFrame函数中加载了每一帧。只需在创建对象时加载 HTMLImageElement 并仅绘制它。所以最初的帖子没有显示实际的问题原因。如果有人有类似的问题,这里是我在结构中修复它的原因:

之前:

export class Button extends GameComponent{
...
drawFrame(delta: number) {
const buttonImg = new Image();
buttonImg.src = myImportedSource;
this.ctx.drawImage(buttonImg, 0, 0, 50, 50);
  }
}

之后:

export class Button extends GameComponent{
...
buttonImg: HTMLImageElement;
constructor() {
  super();
  const this.buttonImg = new Image();
  this.buttonImg.src = myImportedSource;
}
drawFrame(delta: number) {
this.ctx.drawImage(this.buttonImg, 0, 0, 50, 50);
  }
}

虽然我设法解决了自己的问题,但我希望它可以帮助任何遇到同样错误的人。或者,我可以使用await作为解决方案,但是如果某人的互联网连接不好并将fps与您的ping联系起来,这会使引擎滞后。

© www.soinside.com 2019 - 2024. All rights reserved.