我正在学习有关自定义绘画的知识,并且我了解到我可以告诉flutter何时重新绘画画布。但是,如果我正在开发游戏,我认为如果每帧都被调用,事情会变得更顺畅,这样我就可以更新游戏板上的任何状态,然后绘制。这可能吗?
我当时想我总是可以从shouldRepaint()返回true。不管什么(每秒60次),我都会在每一帧调用我的绘画方法吗?
我也知道有一个飞镖定时器,但是我不认为它会与帧同步,所以除非我想要一个慢得多的更新,否则这似乎不是路要走。
>我知道那里有游戏引擎-我的目标是更好地理解抖动,所以我正在尝试自己做一些事情以更好地理解它。
答案 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();
}
这更符合游戏通常的行为方式。