2014-09-03 143 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更好的解決方案確實存在。