每一帧都受到Flutter回调的呼唤

时间:2019-06-06 18:01:36

标签: canvas flutter custom-painting

我正在学习有关自定义绘画的知识,并且我了解到我可以告诉flutter何时重新绘画画布。但是,如果我正在开发游戏,我认为如果每帧都被调用,事情会变得更顺畅,这样我就可以更新游戏板上的任何状态,然后绘制。这可能吗?

我当时想我总是可以从shouldRepaint()返回true。不管什么(每秒60次),我都会在每一帧调用我的绘画方法吗?

我也知道有一个飞镖定时器,但是我不认为它会与帧同步,所以除非我想要一个慢得多的更新,否则这似乎不是路要走。

>

我知道那里有游戏引擎-我的目标是更好地理解抖动,所以我正在尝试自己做一些事情以更好地理解它。

1 个答案:

答案 0 :(得分:1)

如果您正在编写游戏,强烈建议您使用该框架,因为它会处理所有此类事情。

但是,我感谢您正在尝试了解该怎么做-这是一个令人钦佩的目标,所以我会尽力解释。

基本上,您需要了解flutter的渲染并更改其完成方式,因为flutter可以优化很多本不应该针对游戏进行优化的内容。

shouldRepaint返回true是一个很好的第一步,但实际上您要做的还远远不止这些。在普通应用程序中,您的CustomPainter对象应该是一个常量对象,每次更改时都会创建一个常量对象。通常,您会使用诸如AnimationBuilder之类的东西,并每次使用更新的值创建一个新的custompainter。然后在custompainter的shouldRepaint中,将旧的custompainter的值与新的值进行比较,并仅在它们不同时才重绘。

对于一个非常简单的游戏,您可能可以使用一些动画,以及Flutter的拖放,按钮等来摆脱困境。但是,所有复杂的事情都可以通过更自定义和更优化的方式来完成。游戏。

要了解如何完成此操作,建议您阅读Flame的源代码。 Flame是一种轻巧的游戏引擎,可在颤动下运行。它实际上使绘图远离抖动,而是具有一堆游戏“组件”,每个组件各自进行绘画。请参见Flame的game.dart file,因为它就是这个逻辑所在。

GameRenderBox中的一些相关代码继承了RenderBox:

  void _scheduleTick() {
    _frameCallbackId = SchedulerBinding.instance.scheduleFrameCallback(_tick);
  }

  void _unscheduleTick() {
    SchedulerBinding.instance.cancelFrameCallbackWithId(_frameCallbackId);
  }

  void _tick(Duration timestamp) {
    if (!attached) {
      return;
    }
    _scheduleTick();
    _update(timestamp);
    markNeedsPaint();
  }

_tick每帧都被调用一次,然后在下一帧期间重新安排自身的时间。

RenderBox的渲染功能被覆盖:

  @override
  void paint(PaintingContext context, Offset offset) {
    context.canvas.save();
    context.canvas.translate(
        game.builder.offset.dx + offset.dx, game.builder.offset.dy + offset.dy);
    game.render(context.canvas);
    context.canvas.restore();
  }

然后调用游戏的render函数,该函数依次告诉游戏的每个组件进行渲染:

  void render(Canvas canvas) {
    canvas.save();
    components.forEach((comp) => renderComponent(canvas, comp));
    canvas.restore();
  }

这更符合游戏通常的行为方式。