Python:如何序列化多人游戏的对象?
问题描述
我们正在开发一款自上而下的、类似RPG的多人游戏,目的是为了学习(而且很有趣!)和几个朋友在一起。我们在游戏中已经有一些实体并且输入正在工作,但是网络实现让我们头疼:d
问题
尝试使用dict进行转换时,某些值仍将包含pygame.Surface,我不想传输它,并且在尝试对它们进行jsonize时会导致错误。我要以简化方式传输的其他对象(如矩形)无法自动转换。
已正常运行
- 客户端-服务器连接
- 双向传输JSON对象
- 异步联网同步入队
情况
新玩家连接到服务器,希望获取所有对象的当前游戏状态。
数据结构
我们使用基于"实体-组件"的架构,因此我们非常严格地将游戏逻辑分离到"系统"中,而数据则存储在每个实体的"组件"中。该实体是一个非常简单的容器,只有一个ID和一个组件列表。
示例实体(缩短以提高可读性):
Entity |-- Component (Moveable) |-- Component (Graphic) | |- complex datatypes like pygame.SURFACE | `- (...) `- Component (Inventory)
我们尝试了不同的方法,但似乎都不太适合或感觉"毛骨悚然"。
仍然包含对旧对象的引用,因此对不需要的数据类型的"清理"或"过滤"也会在源中发生。深度复制引发异常。
显示一些代码
"EnitityManager"类的方法,它应该生成所有实体的快照,包括它们的组件。此快照应该转换为JSON,没有任何错误-如果可能的话,在此核心类中不需要太多配置。预期和实际结果
我们可以找到一种手动覆盖不需要的元素的方法。但是由于组件列表将会增加,我们必须将所有过滤逻辑放到这个核心类中,它不应该包含任何组件专门化。
我们真的需要将所有逻辑放到EntityManager中以筛选正确的对象吗?这感觉不太好,因为我希望在没有任何硬编码配置的情况下完成所有到JSON的转换。
如何以最通用的方法转换所有这些复杂数据?
感谢您阅读到目前为止,非常感谢您事先的帮助!
我们已经在撰写的有趣文章,可能对其他有类似问题的人有帮助
- https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/
- http://code.activestate.com/recipes/408859/
- https://docs.python.org/3/library/pickle.html
更新:解决方案-thx2懒惰
我们使用了以下体系结构的组合,到目前为止工作得非常好,维护起来也很好!
实体管理器现在调用实体的get_state()函数。
实体只有一些基本属性要添加到状态,并将get_state()调用转发给所有组件:
组件本身现在继承了它们的新超类组件的get_state()方法,超类组件只关心所有简单的数据类型:
现在,每个开发人员都有机会覆盖此函数,以便直接在组件类(如Graphic、Movement、Inventory等)中为复杂类型创建更详细的get_state()函数。如果需要以更准确的方式保护状态-这是未来维护代码的一件大事,请将这些代码片段放在一个类中。
下一步是实现静电方法,用于从同一个Class中的状态创建项。这使得这项工作非常顺利。
非常感谢你的帮助,懒惰。
推荐答案
是否确实必须将所有逻辑放入EntityManager以筛选正确的对象?
否,您应该使用polymorphism。
您需要一种以可在不同系统之间共享的形式表示游戏状态的方法;因此,可以为您的组件提供一个返回其所有状态的方法,以及一个允许您从该状态创建组件实例的工厂方法。
(Python已经有__repr__
魔术方法,但您不必使用它)
因此,无需在实体管理器中进行所有筛选,只需让他在所有组件上调用此新方法,并让每个组件决定结果将是什么样子。
如下所示:
组件可以这样实现它:
和从服务器接收状态的客户端EntityManager
将迭代每个实体的组件列表,并调用from_state
以创建实例。
这篇关于Python:如何序列化多人游戏的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!