Angelscript继承自C ++类

时间:2014-09-03 22:32:06

标签: c++ inheritance angelscript

我已经在这个问题上刮了几天,以为你们可能会有更好的主意。

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

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

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

1 个答案:

答案 0 :(得分:0)

免责声明:我从未在任何"真实"中使用过Angelscript。项目,这就是为什么以下答案应该与一粒盐。它在我为它设置的小测试代码中工作,大多数代码片段在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对象的指针,该对象具有实现所需接口的任意类型(目前强制实施的唯一方法是在出现问题时崩溃,这有点不好)。
  • 在构造时,这是创建的(来自传入的引擎,上下文和名称),并且指向其成员函数的指针是有效的,在销毁时它被释放。
  • 每当调用一个成员时,它就会转发给Angelscript对象的相应成员。

正如一开始所提到的,我对Angelscript的所有事情都很有经验,所以这可能确实是一种非常不理想的方法,而且确实存在更好的解决方案。