2014-09-03 146 views
0

我一直在挠挠我的头这几天,认为你们可能有一个更好的主意。Angelscript继承自C++类

本质上我想定义一个标准接口,然后可以从Angelscript类继承。例如,说我有一个纸牌游戏,像魔术聚会,我的基类可能看起来像:

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

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

回答

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,所以这可能确实是一个非常不理想的方法,它是相当propable更好的解决方案确实存在。