我有一场比赛,我已经有一段时间了。核心是C ++,但我使用Python编写脚本和攻击/状态效应/项目等。
我已经将自己编码到一个角落,我必须使用eval来获得我想要的行为。以下是它的产生方式:
我有一个用于规范攻击的xml文档,如下所示:
<Attack name="Megiddo Flare" mp="144" accuracy="1.5" targetting="EnemyParty">
<Flags>
<IgnoreElements/>
<Unreflectable/>
<ConstantDamage/>
<LockedTargetting/>
</Flags>
<Components>
<ElementalWeightComponent>
<Element name="Fire" weight="0.5"/>
</ElementalWeightComponent>
<ConstantDamageCalculatorComponent damage="9995" index="DamageCalculatorComponent"/>
</Components>
</Attack>
我在python中解析这个文件,并构建我的攻击。每个攻击由任意数量的组件组成,以实现不同的行为。在这个Attack的例子中,我实现了一个DamageCalculatorComponent,告诉python使用ConstantDamage变体。我在脚本文件中实现了所有这些组件。这对于我经常使用的组件类型来说都很好。有些攻击是攻击是使用该特定组件变体的唯一攻击。而不是将组件添加到我的脚本文件中,我希望能够在xml文件中指定Component类。
例如,如果我要实施最终幻想中的经典白风攻击(通过攻击者的HP数量恢复团队HP)
<Attack name="White Wind" mp="41" targetting="AnyParty">
<Flags>
<LockedTargetting/>
</Flags>
<Components>
<CustomComponent index="DamageCalculatorComponent">
<![CDATA[
class WhiteWindDamageComponent(DamageCalculatorComponent):
def __init__(self, Owner):
DamageCalculatorComponent.__init__(self, Owner)
def CalculateDamage(self, Action, Mechanics):
Dmg = 0
character = Action.GetUsers().GetFirst()
SM = character.GetComponent("StatManagerComponent")
if (SM != None):
Dmg = -SM.GetCurrentHP()
return Dmg
return WhiteWindDamageComponent(Owner)
]]>
</CustomComponent>
</Components>
</Attack>
我想知道是否有更好的方法可以做到这一点?我能看到的另一种方法是将所有可能的Component变量定义放入我的python文件中,并展开我的Component创建器以检查其他变体。似乎abit浪费一次性组件。有没有更好/更安全的动态生成类型的替代方案,或者可能是我没有看到的其他解决方案?
提前致谢
答案 0 :(得分:2)
内联Python很糟糕,因为
Python源代码编辑器无法理解您的源代码文件,您将错过语法高亮显示
所有其他工具,如pylint,可用于lint和验证源代码也将失败
<强>替代强>
在元素<CustomComponent index="DamageCalculatorComponent">
...添加参数script
:
<CustomComponent index="DamageCalculatorComponent" script="damager.py">
然后在文件系统的某处添加文件damager.py
。
按照此处所述加载:What is an alternative to execfile in Python 3?
在你的主游戏引擎代码中构造出加载系统模块的类,如:
damager_class = sys.modules["mymodulename"].my_factory_function()
所有Python模块必须共享某种商定的类名/入口点函数。
如果您想拥有真正的可插拔架构,请使用Python egg和setup.py
入口点
示例