1

我有一个游戏我已经做了一段时间了。核心是 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 中解析这个文件,并构建我的攻击。每个攻击由任意数量的组件组成,以实现不同的行为。在这个攻击的例子中,我实现了一个 DamageCalculatorComponent,告诉 python 使用 ConstantDamage 变体。我在我的脚本文件中实现了所有这些组件。这对于我将经常使用的组件类型来说非常好。在某些攻击中,该攻击将是使用该特定组件变体的唯一攻击。我希望能够在 xml 文件中指定 Component 类,而不是将组件添加到我的脚本文件中。

例如,如果我要执行最终幻想中的经典白风攻击(根据攻击者的生命值恢复团队生命值)

<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>

我想知道是否有更好的方法来做到这一点?我能看到的唯一另一种方法是将每个可能的组件变体定义放入我的 python 文件中,并扩展我的组件创建者以检查其他变体。单次使用的组件似乎有点浪费。动态生成类型是否有更好/更安全的替代方案,或者我没有看到的另一种解决方案?

提前致谢

4

1 回答 1

2

内联 Python 不好,因为

  • Python 源代码编辑器无法理解您的源代码文件,您将错过语法高亮显示

  • 所有其他可用于 lint 和验证源代码的工具,如 pylint 也将失败

选择

在元素中<CustomComponent index="DamageCalculatorComponent">

...添加参数script

<CustomComponent index="DamageCalculatorComponent" script="damager.py">

然后damager.py在文件系统的某处添加文件。

按照此处所述加载它:Python 3 中 execfile 的替代方法是什么?

在您的主游戏引擎代码中,使用已加载的系统模块构建类,例如:

 damager_class = sys.modules["mymodulename"].my_factory_function()

所有 Python 模块都必须共享某种约定的类名/入口点函数。

如果您想拥有真正可插拔的架构,请使用 Python 鸡蛋和setup.py入口点

例子

于 2012-04-27T22:33:02.267 回答