在Pygame中定义基类/模型



上下文

我正在用Python创建一个游戏,使用pygame来应用我自己研究的SOLID原理和MVC概念。

我曾经有一个类,我认为,它有不止一个责任(通过改变位置移动,改变移动角度/方向,对用户输入做出反应,开火,损坏实体等)

  • 静态
  • 可移动
  • 可控
  • 射击运动员
  • 可破坏的
  • 射弹

我把它们像接口一样分开,这样不同种类的类都可以使用其中的任何一个(例如,障碍物类是静态的,子弹类是可移动的和可投射的,玩家类是可控的和射手,等等)

前三个界面对我来说很奇怪。基本上:

  • Static负责在窗口区域中定位实体
  • Movable负责定义移动方向(有角度和移动速度)
  • 可控负责对用户输入做出反应(何时移动、开火等)

问题

上面的3个类具有这种依赖关系:

Static <---extends--- Movable <---extends--- Controllable

以下是3个基类的代码以及它们如何相互作用:

class Static(object):
def __init__(self, 
pos: Vector2 = None, 
off: Vector2 = None):
self._position = pos
self._offset = off
# has some setters and getters
...

class Movable(Static):
def __init__(self, 
angle: Vector2 = None, 
mov_spd: int = 0, 
**static_properties):
super(Movable, self).__init__(**static_properties)
self._angle_vector = angle
self._move_speed = mov_spd
def update_position(self, *args, **kwargs):
raise NotImplementedError
def update_angle(self, *args, **kwargs):
raise NotImplementedError

class Controllable(Movable):
def __init__(self, 
move_state: Dict[Enum, bool] = None,
**movable_properties):
super(Controllable, self).__init__(**movable_properties)

# self._move_state = { LEFT: False, RIGHT: False, UP: False, DOWN: False }
self._move_state = move_state
def set_move_state(self, direction):
self._move_state[direction] = not self._move_state[direction]
# overrides and defines Movable method
def update_position(self):
...
# overrides and defines Movable method
def update_angle(self, direction, magnitude):
...

分离的原因是,游戏中有/将有类似小工具的实体,或游戏障碍物(因此实现静态),只是像子弹一样移动的实体(因此实现可移动),或可以由玩家控制的实体(从而实现可控)。

但依赖性的原因是可控性将定义移动的方向,可移动将在其中使用,但需要知道更新它的位置,静态将在其中提供。


问题(2)

  • 在这种情况下,类的分解/分离是否合理?如果没有,它们应该有多小/多大
  • 这种情况下的依赖关系合理吗?如果没有,如何改进/耦合/解耦它们

初始解决方案:

  • 我确实熟悉了继承与组合,知道从基类继承/组合什么时候好(什么时候坏),但我没有其他方法知道我是否在我的情况下正确使用了它。此外,我仍然不理解"is a"one_answers"has a"的概念,因为它似乎不适用于我试图为实体构建基类/接口的情况。但感觉它应该适用。

  • 我非常了解单一责任原则,知道定位、移动和控制应该在一个单独的类中处理,而不是在一个大类中处理(除非我在定义这些责任时出错)。但现在我想知道定位、移动和控制责任应该有多小/多大

  • 我在9年前刚刚发现了这个StackOverflow问题,并在一定程度上回答了我的第二个问题和个人担忧。但我想知道除了mixin之外,是否还有其他有用的设计可以解决我的问题。

一般来说,您的方法似乎是合理的,但我不明白为什么在Controllable类中需要重写Movable类的update_positionupdate_angle

对我来说,在Controllable类中实现新方法更有意义,这些方法注册并响应用户的输入,然后使用基类(Movable)的方法更新位置。所以我会做一些类似的事情:

class Controllable(Movable):
def __init__(self, 
move_state: Dict[Enum, bool] = None,
**movable_properties):
super(Controllable, self).__init__(**movable_properties)

# self._move_state = { LEFT: False, RIGHT: False, UP: False, DOWN: False }
self._move_state = move_state
def set_move_state(self, direction):
self._move_state[direction] = not self._move_state[direction]
def update_position_from_user_input(self):
# some logic 
self.update_position()
def update_angle_from_user_input(self, direction, magnitude):
# some logic
self.update_angle()

现在,如果您需要更改输入逻辑,您只需要更改Controllable类方法中的特定位,但不需要对更新位置做任何操作,这仍然将由基类的方法处理。

相关内容

  • 没有找到相关文章

最新更新