【问题标题】:Angelscript inheritance from C++ classAngelscript 从 C++ 类继承
【发布时间】:2014-09-03 22:32:06
【问题描述】:

这几天我一直在摸不着头脑,想你们可能有更好的主意。

基本上我想定义一个标准接口,然后可以从 Angelscript 类中继承。例如,假设我有一个像 Magic The Gathering 这样的纸牌游戏,我的基类可能如下所示:

class Card
{
public:
    virtual void PreDrawPhase() = 0;
    virtual void PostDrawPhase() = 0;
    // etc....
};

然后我希望能够在 Angelscript 中定义新卡片及其各自的行为,同时能够在 C++ 中处理它们(通过处理接口)。我怎样才能做到这一点?

【问题讨论】:

    标签: c++ inheritance angelscript


    【解决方案1】:

    免责声明:我从未在任何“真实”项目中使用过 Angelscript,这就是为什么下面的答案应该持保留态度。它在我为它设置的小测试代码中工作,大多数代码 sn-ps 在official manual 中进行了一些详细的解释,但这绝对不能保证它是一个合理的设计并且可以在你的游戏中合理使用.

    我相信,在official manual 中很好地描述了实现目标的相关部分:

    • This 描述了如何定义和使用接口。

    • This 描述了如何在 C++ 中实例化和使用“脚本类”。

    使用这些信息,我们可能会编写一个简单的包装类,它在构造时创建某个类的实例并在销毁时释放它,同时提供调用脚本类相应成员的成员函数:

    (注意:为简洁起见,我省略了所有错误处理和其他一些重要的做法,例如Rule of Tree(下面的类不能复制而不破坏很多...))

    标题:

    class Card
    {
        public:
        Card(asIScriptEngine *engine, asIScriptContext *ctx, const std::string &module_name, const std::string &class_name);
        ~Card();
    
        void PreDrawPhase();
        void PostDrawPhase();
    
        private:
        asIScriptContext *ctx;
        asIScriptObject *obj;
        asIScriptFunction *PreDrawPhaseFunc, *PostDrawPhaseFunc;
    };
    

    实施:

    Card::Card(asIScriptEngine *engine, asIScriptContext *ctx, const std::string &module_name, const std::string &class_name):
        ctx(ctx)
    {
        asIScriptModule *module = engine->GetModule(module_name.c_str());
        auto type_id=module->GetTypeIdByDecl(class_name.c_str());
        asIObjectType *type = engine->GetObjectTypeById(type_id);
    
        PreDrawPhaseFunc=type->GetMethodByDecl("void PreDrawPhase()");
        PostDrawPhaseFunc=type->GetMethodByDecl("void PostDrawPhase()");
    
        asIScriptFunction *factory = type->GetFactoryByDecl((class_name+" @"+class_name+"()").c_str());
        ctx->Prepare(factory);
        ctx->Execute();
        obj=*(asIScriptObject**)ctx->GetAddressOfReturnValue();
        obj->AddRef();
    }
    
    Card::~Card()
    {
        obj->Release();
    }
    
    void Card::PreDrawPhase()
    {
        ctx->Prepare(PreDrawPhaseFunc);
        ctx->SetObject(obj);
        ctx->Execute();
    }                                                                                                                    
    
    void Card::PostDrawPhase()
    {                                                                                                                    
        ctx->Prepare(PostDrawPhaseFunc);
        ctx->SetObject(obj);
        ctx->Execute();
    }
    

    我相信代码很容易解释(如果我错了,请纠正我,我会尝试详细说明),因此我将仅描述基本思想:

    • Card 的每个实例都包含一个指向某个 Angelscript 对象的指针,该对象是实现所需接口的某种任意类型(目前强制执行此操作的唯一方法是在出现问题时崩溃,这有点糟糕)。
    • 在构造时,创建 this(从传入的引擎、上下文和名称)并获取指向其成员函数的指针,在销毁时释放它。
    • 每当调用成员时,它都会转发给 Angelscript 对象的相应成员。

    如开头所述,我对 Angelscript 没有任何经验,因此这可能确实是一种非常不理想的方法,而且很有可能确实存在更好的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多