我正在从事一个天文学项目,制作其中一个重力模拟器程序。我有一个 Uni
类,它代表一个充满天体的宇宙(Body
类的实例)。
这个Uni
类能够更新自身、添加新主体以及通过其id
删除主体。它完全基于数学,并且应该单独工作。
围绕它,我计划构建一个程序,使用 PyGame 来选择性地实时显示模拟,并使用 MatPlotLib 来分析结果。但是,我对如何保持计算 (Uni
) 和渲染 (Renderer
) 解耦感到有点困惑!
我的设想是这样的:
主程序:
- 导入 PyGame,对其进行初始化,并创建一个
屏幕
。 - 实例化一个 Universe,用主体填充它等(实际上由
FileManager
完成,它读取 uni 的 JSON 规范)。 - 创建一个
渲染器
进入
while run:
循环:uni.update(dt)
#监听PyGame事件,响应
r.render(screen, uni, ui) #UI 类具有 UI 元素列表。
但是,渲染器需要保留需要绘制的 PyGame 表面和图像的持久列表,这就是问题所在。 Uni
和 Body
实例都不需要知道 PyGame,因此它们自己无法保留这些实例。
另一方面,渲染器仅用于其 render
方法,该方法不能仅根据需要创建和销毁 PyGame 表面(我猜这会影响性能)。
一种可能的解决方案是让渲染器拥有 PyGame 对象的字典,所有对象均由主体 id 标识。然后,它将对其进行迭代,删除任何消失的主体,并在每帧添加任何新的主体。
这是正确的方法吗?
最佳答案
为什么不将 Body
本身添加到 pygame 对象的字典中而不是 ID 中,而不是主体 ID 呢?毕竟,Python 变量只是一个标签,因此渲染器不需要知道变量代表什么。而且它可能会省去您查找 ID 的麻烦。
一个相关选项是将一个或多个视口(viewport)
对象添加到您的宇宙中。因为无论查看机制的实现如何,您通常都不想显示整个宇宙,因此视口(viewport)将是宇宙的一个适当属性。使用该视口(viewport)可以使用几种方法(除了创建和调整大小)。首先是获取视口(viewport)中所有 Body
的方法(该方法可能只返回您保留在视口(viewport)对象中的列表)。其次是获取包含两个列表的元组的方法;其中一个 Body
出现在视口(viewport)中,第二个是自上次更新以来离开视口(viewport)的 Body
列表。视口(viewport)还应该有一个由 Universe 的更新方法调用的更新方法。
关于python - 如何正确地将计算与渲染解耦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13099963/