Python 为玩家创造效果?
我会尽量简短地说:Python 为玩家创造效果?,python,python-3.x,class-hierarchy,Python,Python 3.x,Class Hierarchy,我会尽量简短地说: 我有一个由游戏引擎提供的PlayerEntity类,它有一个move\u type属性 move\u type可以一次设置为一个:MoveTypes.NONE,MoveTypes.FLY,MoveTypes.WALK 我已经对PlayerEntity类进行了子类化,我希望我的子类能够执行类似player.freeze(duration=5) 我还希望有一些自定义效果,如player.burn(持续时间=3) 这是我的第一个想法: class Player(game.Pla
- 我有一个由游戏引擎提供的
类,它有一个PlayerEntity
属性move\u type
可以一次设置为一个:move\u type
MoveTypes.NONE,MoveTypes.FLY,MoveTypes.WALK
- 我已经对
类进行了子类化,我希望我的子类能够执行类似PlayerEntity
player.freeze(duration=5)
- 我还希望有一些自定义效果,如
player.burn(持续时间=3)
class Player(game.PlayerEntity):
def __init__(self):
super().__init__()
self._effects = []
def add_effect(self, effect, duration=None):
self.effects.append(effect)
if duration is not None:
delayed(duration, self.remove_effect, effect)
self._apply_effects()
def remove_effect(self, effect):
if effect in self.effects:
self.effects.remove(effect)
self._apply_effects()
def _apply_effects(self):
if 'freeze' in self.effects:
self.move_type = MoveTypes.NONE
elif 'fly' in self.effects:
self.move_type = MoveTypes.FLY
else:
self.move_type = MoveTypes.WALK
if 'burn' in self.effects:
self.ignite()
else:
self.extinguish()
freeze = lambda self, duration: self.add_effect('freeze', duration)
fly = lambda self, duration: self.add_effect('fly', duration)
burn = lambda self, duration: self.add_effect('burn', duration)
但是,我想让它更灵活,例如有一个效果
类
我遇到的几个问题:
Player
是否具有\u效果
列表并调用self.\u效果[0]。应用(self,duration)
,或者Effect
类是否具有Player
属性并只调用它自己的应用(duration)
移动类型
)。然而,burn
是完全独立的效果Effect
类,然后将Effect
对象列表存储在Player
对象中。在Player
中调用一个方法,将Effect
对象添加到此列表中。在每个回合/勾选中,浏览效果的列表,以检查堆栈、更新剩余持续时间、删除任何没有剩余持续时间的,等等
效果
对象,可以与多种效果交互。例如,如果您想要一个允许移动的冻结状态,并且只增加该玩家
受到暴击的机会,请创建一个新的效果
,定义您正在寻找的行为Effect
类,然后将Effect
对象列表存储在Player
对象中。在Player
中调用一个方法,将Effect
对象添加到此列表中。在每个回合/勾选中,浏览效果的列表,以检查堆栈、更新剩余持续时间、删除任何没有剩余持续时间的,等等
效果
对象,可以与多种效果交互。例如,如果您想要一个允许移动的冻结状态,并且只增加该玩家
受到暴击的机会,请创建一个新的效果
,定义您正在寻找的行为Effect
类,然后将Effect
对象列表存储在Player
对象中。在Player
中调用一个方法,将Effect
对象添加到此列表中。在每个回合/勾选中,浏览效果的列表,以检查堆栈、更新剩余持续时间、删除任何没有剩余持续时间的,等等
效果
对象,可以与多种效果交互。例如,如果您想要一个允许移动的冻结状态,并且只增加该玩家
受到暴击的机会,请创建一个新的效果
,定义您正在寻找的行为Effect
类,然后将Effect
对象列表存储在Player
对象中。在Player
中调用一个方法,将Effect
对象添加到此列表中。在每个回合/勾选中,浏览效果的列表,以检查堆栈、更新剩余持续时间、删除任何没有剩余持续时间的,等等
效果
对象,可以与多种效果交互。例如,如果您想要一个允许移动的冻结状态,并且只增加该玩家
受到暴击的机会,请创建一个新的效果
,定义您正在寻找的行为以下代码提供了使用激活/停用定义新效果的可能性,并创建“类别”。如果两个效果属于同一类别,则优先级较高的效果将影响玩家。不同类别的影响是独立的 实现中存在一个“缺陷”,想象一下如果发生以下情况:
- 应用效果a
- 由于超时,效果a被删除而不是
- 在第一次给药超时之前,再次应用效果a
- 由于达到第一次给药持续时间,效果a被删除
Effect
转换为类/元类,这可能很容易解决
这里的Effect应该是一个类/元类,我刚开始这样写,并想完成它。为什么是元类?解决所述问题的一种方法是让Effect
成为一个元类,这样Freeze
就是一个类,一个管理就是这个类的一个实例,延迟与这个实例相耦合
from collections import namedtuple, defaultdict
Effect = namedtuple("Effect", ["activate", "deactivate", "category", "priority", "name"])
class Player(game.PlayerEntity):
def __init__(self):
super().__init__()
# Instead of list a priority list could/should be used
self._effects = defaultdict(list)
def add_effect(self, effect, duration=None):
# Check if player allready suffers from effect
if effect not in self._effects[effect.category]:
# If the new effect has a higher priority than all others, activate it
max_priority_effect = max(self._effects, key = lambda effect: effect.priority):
if effect.priority > max_priority_effect
# Deactivate the old effect to savely change status
max_priority_effect.deactivate(self)
effect.activate(self)
self._effects[effect.category].append(effect)
if duration is not None:
delayed(duration, remove_effect, effect)
def remove_effect(self, effect):
if effect.name in self._effects[effect.category]:
priority_element = max(self._effects, key = lambda effect: effect.priority)
# Might not be optimal?
# If Effect is implemented as class do proper __eq__
if effect.name == priority_element.name:
# If the effect is the currently active effect deactive it and activate
# the effect with the secondmost priority
self._effects[effect.category][effect.name].deactivate()
max(self._effects, key = lambda effect: effect.priority).activate()
# If Effect is implemented as class do proper max() handling
del self._effects[effect.category][effect.name]
#Effects:
freeze = Effect(
activate = lambda player: player.move_type = MoveTypes.None,
deactivate = lambda player: player.move_type = MoveTypes.WALK,
category = "movement",
priority = 2,
name = "freeze")
fly = Effect(
activate = lambda player: player.move_type = MoveTypes.FLY,
deactivate = lambda player: player.move_type = MoveTypes.WALK,
category = "movement",
priority = 1,
name = "fly")
burn = Effect(
activate = lambda player: player.ignite(),
deactivate = lambda player: player.extinguish(),
category = "other",
priority = 0,
name = "burn")
编辑:
看来我错了,这里不需要元类。下面是一个效果
为类的实现。未经测试
from collections import namedtuple, defaultdict
from functools import total_ordering
@total_ordering
class Effect:
def __init__(self):
super().__init__(self)
self.deactivate = self.if_fresh(deactivate)
def if_fresh(self, f):
if self.fresh:
f()
self.fresh = False
def activate(self, player):
# Overwrite me!
pass
def deactivate(self, player):
# Overwrite me!
pass
def __eq__(self, other):
return(self is other)
def __lt__(self, other):
return(self.priority < other.priority)
class Burn(Effect):
category = "other"
priority = "0"
def activate(self, player):
player.ignite()
def deactivate(self, player):
player.extinguish()
[... other effects ... ]
class Player(game.PlayerEntity):
def __init__(self):
super().__init__()
# Instead of list a priority list could/should be used
self._effects = defaultdict(list)
def add_effect(self, effect, duration=None):
# Check if player allready suffers from effect
if effect not in self._effects[effect.category]:
# If the new effect has a higher priority than all others, activate it
max_priority_effect = max(self._effects[effect.category])
if effect > max_priority_effect:
# Deactivate the old effect to savely change status
max_priority_effect.deactivate(self)
effect.activate(self)
self._effects[effect.category].append(effect)
if duration is not None:
delayed(duration, remove_effect, effect)
def remove_effect(self, effect):
if effect in self._effects[effect.category]:
priority_element = max(self._effects)
if effect is priority_element:
# If the effect is the currently active effect deactive it and activate
# the effect with the secondmost priority
self._effects[effect.category][effect].deactivate()
max(self._effects.activate())
del self._effects[effect.category][effect]
从集合导入namedtuple,defaultdict
从functools导入总排序
@总订单
阶级效应:
定义初始化(自):
超级()。\uuuu初始化\uuuuu(自)
self.deactivate=self.if_fresh(停用)
def如果_新鲜(自身,f):
如果self.fresh:
f()
self.fresh=False
def激活(自我,玩家):
#覆盖我!
通过
def停用(自身、玩家):
#覆盖我!
通过
定义(自身、其他):
返回(自我是他者)
定义(自身、其他):
返回(自优先级<其他优先级)
等级烧伤(效果):
类别=“其他”