如果您正在编写游戏,我强烈建议您为此使用框架,因为它可以处理各种此类事情。
但是,我很感激你试图理解如何做到这一点——这是一个令人钦佩的目标,所以我会尽力解释。
基本上,你需要挂钩到 Flutter 的渲染并改变它的完成方式,因为 Flutter 优化了很多不应该为游戏优化的东西。
返回 true fromshouldRepaint
是一个很好的第一步,但实际上你要做的远不止这些。在普通应用程序中,您的 CustomPainter 对象应该是一个常量对象,每次发生更改时都会创建该对象。通常你会使用 AnimationBuilder 之类的东西,并创建一个新的 custompainter,每次都会更新值。然后在 custompainter 的 shouldRepaint 中,将旧 custompainter 的值与新的值进行比较,只有当它们不同时才重绘。
对于一个非常简单的游戏,您可能可以使用一些动画,以及颤振的拖放和按钮等。但是任何复杂的事情可能会更好地在更自定义和更适合游戏的东西中完成。
要了解如何做到这一点,我建议阅读 Flame 的源代码。Flame 是一个轻量级的游戏引擎,在 Flutter 上运行。它实际上将绘图从颤振中抽象出来,取而代之的是一堆游戏“组件”,每个组件都有自己的绘画。请参阅 Flame 的game.dart 文件,因为它是该逻辑所在的位置。
一些相关代码,来自继承 RenderBox 的 GameRenderBox :
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();
}
这会调用游戏的渲染函数,该函数反过来告诉它的每个组件进行渲染:
void render(Canvas canvas) {
canvas.save();
components.forEach((comp) => renderComponent(canvas, comp));
canvas.restore();
}
这更符合游戏通常的做事方式。