goo blog サービス終了のお知らせ 

gooブログはじめました!

写真付きで日記や趣味を書くならgooブログ

クラスの使い方(C++,angelscript)

2010-01-31 10:07:34 | angelscript

c++とangelscriptでクラスを使用するには2パターンある。

angelscript側ではクラスを宣言しない(クラスをglobalpropertyとして使用)

Register*関連の関数を呼ぶ前にクラスの実態が存在してそいつをangelscriptからアクセスできるようにする。
struct MyStruct { 
    int health;      
    char name[32];
};                      

// Struct instance
MyStruct mystruct;
MyStruct mystruct; iRet = g_pasengine->RegisterObjectType("MyObject", 0, asOBJ_REF | asOBJ_NOHANDLE); assert( iRet >= 0 ); iRet = g_pasengine->RegisterObjectProperty("MyObject", "int health", offsetof(MyStruct, health)); assert( iRet >= 0 );



 

angelscript側でもクラスの宣言をする(スクリプト側でC++のクラスの宣言可能)

iRet = m_pasengine->RegisterObjectType("CMoveObject", sizeof(CMoveObject), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS); assert( iRet >= 0 );


プロパティ

2010-01-31 09:50:45 | angelscript

angelscriptのプロパティの使い方がいまいち理解できない。char型で登録したときは予想どりだが
構造体やクラスのメンバにint handle[10]を追加して下記と同様なやり方をすると「variable is not a member of MyClass」 となる。c++の構造体をGlobalPropertyと登録して、プロパティ用の関数をC++の関数として用意して、スクリプト側ではC#の プロパティと同様な使い方をする(char型の場合) 。

プロパティ(char型) C++

プロパティ(char型) スクリプト側

<form>

プロパティ(char型) C++

<textarea rows="8" cols="75" readonly="readonly">struct MyStruct {     int health;     char name[32]; }; // Struct instance MyStruct mystruct; // Getter proxy function static string Proxy_get_name(const MyStruct * ms) {     int len = strnlen(ms->name, 32);     string name(ms->name, len);     return name; } // Setter proxy function void Proxy_set_name(MyStruct * ms, const string& new_name) {     memset(ms->name, 0, 32);     int len = new_name.length();     if (len > 32) len = 32;     if (len > 0) memcpy(ms->name, new_name.c_str(), len); } //Angelscript registration calls (fragment): memcpy(mystruct.name, "IT WORKS!!!\x00", 12); r = engine->RegisterObjectType("MyObject", 0, asOBJ_REF | asOBJ_NOHANDLE); assert( r >= 0 ); r = engine->RegisterObjectProperty("MyObject", "int health", offsetof(MyStruct, health)); assert( r >= 0 ); r = engine->RegisterObjectMethod("MyObject", "string get_name()", asFUNCTION(Proxy_get_name), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); r = engine->RegisterObjectMethod("MyObject", "void set_name(const string &in)", asFUNCTION(Proxy_set_name), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); r = engine->RegisterGlobalProperty("MyObject Obj", &mystruct); assert( r >= 0 ); </textarea>

</form>
<form>

プロパティ(char型) C++

<textarea rows="8" cols="75" readonly="readonly">void test1() {     print("Starting string: " + Obj.name);     Obj.name = "SDAFSDFSDFDAS";     print("Ending string: " + Obj.name); } </textarea>

</form>

angelscriptバイナリのサイズの違いについて

2010-01-30 17:12:28 | angelscript

angelscriptをビルドするとデバッグ版よりリリース版のほうがサイズが大きいのが気になって公式フォーラムをみたら 記述がありました。どうやら最適化等によってサイズが大きくなっている模様。以下が原文です。またスクリプト側で #ifdefマクロのような使い方があるとあったのでメモしておく。

 

バイナリのサイズ違いについて


#ifdefと同等な機能をangelscript側に持たせる

<form>

公式フォーラム抜粋(バイナリのサイズ違いについて)

<textarea rows="8" cols="75" readonly="readonly">The size of the binary can also increase a lot if it is optimized for speed rather than size. During this kind of optimization the compiler commonly 'inline' functions and 'roll out' loops, which effectively duplicates the code all over the place. </textarea>

</form>

<form>

公式フォーラム抜粋(#ifdefと同等な機能をangelscript側に持たせる)

add_onフォルダ下にあるCScriptBuilderのDefineWordメソッドを使用する。

<textarea rows="8" cols="75" readonly="readonly">The compiler for your editor could define the word 'EDITOR' with CScriptBuilder::DefineWord("EDITOR");, and the game would define the word 'GAME' in the same way. In the script you can then do: void BasicObj_OnClick(BasicWorldObj@ pthis) { #if EDITOR   creatorContainer.MoveCreateItems();   creatorContainer.CreateFinish(); #endif #if GAME   pthis.SetFocus(move); #endif } </textarea>

</form>

AngelScript管理クラス更新

2010-01-17 17:55:30 | angelscript
timeSetEventをangelscriptで使う前に、CAngelScriptMgrに結構無駄なソースがあったので整理する。

CAngelScriptMgr.h

CAngelScriptMgr.cpp

<form>

CAngelScriptMgr.h

<textarea rows="8" cols="75" readonly="readonly"> #ifndef _CANGELSCRIPT_MGR_H_ #define _CANGELSCRIPT_MGR_H_ #include <windows.h> #include <iostream> // cout #include <assert.h> // assert() #include <angelscript.h> #include "../angel_incluce_lib/angel_include/add_on/scriptstring/scriptstring.h" #include "../angel_incluce_lib/angel_include/add_on/contextmgr/contextmgr.h" #include "../angel_incluce_lib/angel_include/add_on/scriptstdstring/scriptstdstring.h" #include "../angel_incluce_lib/angel_include/add_on/scriptbuilder/scriptbuilder.h" #include "../angel_incluce_lib/angel_include/add_on/scriptany/scriptany.h" //\angel_incluce_lib\angel_include\add_on #include <crtdbg.h> #include <conio.h> // kbhit(), getch() #include "CMoveObject.h" using namespace std; class CAngelMap { public: //! angelscriptが管理しているfuncID,angelscriptに登録するときのchar* chfuncIDとは別 int iAngelFuncID; //! angelscriptに登録するときのchar *funIDのこと string strFuncName; }; class CAngelScriptMgr { public: CAngelScriptMgr(); ~CAngelScriptMgr(); //! m_mapAngelfunc(map)を取得 /*! \return int m_mapAngelfunc(map)に登録してある関数の数 */ int GetAngelFuncNum(); //! angelscriptのタイムアウト時間の設定 /*! \param imsec angelscriptのタイムアウト時間(ミリ秒単位で設定 1秒だったら1000を指定する) \return void */ void SetScriptTimeOut( DWORD dwMsec ); //! angelscriptのタイムアウト時間の取得 /*! \return DWORD angelscriptのタイムアウト時間 */ DWORD GetScriptTimeOut(); //! angelscriptの関数実行する /*! \param index ファンクション番号 (CAngelScriptMgrのAngelFuncListに登録してある番号) \param fret 戻り値 (この関数はangelscriptの戻り値floatの結果を受け取る) \return int 0:成功(angelscript内の関数呼び出し成功)  -1:失敗 */ int Excute( int index, float &fret); //! angelscriptの関数実行する /*! \param index ファンクション番号 (CAngelScriptMgrのAngelFuncListに登録してある番号) \param dret 戻り値 (この関数はangelscriptの戻り値doubleの結果を受け取る) \return int 0:成功(angelscript内の関数呼び出し成功)  -1:失敗 */ int Excute( int index, double &dret); //! angelscriptの関数実行する /*! \param index ファンクション番号 (CAngelScriptMgrのAngelFuncListに登録してある番号) \param *ret angelscript内で自由に変更するためのパラメータ。c++,angelscriptどちらからでも更新可能。 \return int 0:成功(angelscript内の関数呼び出し成功)  -1:失敗 */ int Excute( int index,CMoveObject *ret); private: int LoadScript( char *ScriptName ); //以下はクラス関数として登録できない。globalにする必要がある。 //void MessageCallback2( const asSMessageInfo *msg, void *param ); //void print2( string &msg ); //void print2( int num ); //void print2( asUINT num ); //void print2( float num ); //void print2( double num ); //! c++,angelscript両方で使用できる変数を登録。(C++側ではグローバル変数にする) /*! \return int 0:成功  -1:失敗 */ int RegisterProperty(); //! c++,angelscript両方で使用できるクラスを登録。(angelscriptに渡す引数はここで登録する) /*! \return int 0:成功  -1:失敗 */ int RegisterMyClass(); //! angelscriptのエンジン初期化 /*! \return int 0:成功  -1:失敗 */ int InitializeAngelEngine(); //! angelscriptのビルド /*! \return int 0:成功  -1:失敗 */ int BuildAngelScript(); //! angelscriptのビルドcheck /*! \return int 0:成功  -1:失敗 */ int CheckBuild(); //! angelscriptがc++の関数を登録したときにできるfuncidをm_mapAngelfunc(マップ)に登録しておく。 //! c++からangelscriptを実行するときにfuncidをすぐ取り出すため /*! \return int 0:成功  -1:失敗 */ int SetAngelFuncMap(); //! angelscriptに失敗したときのangelscriptが出力されるメッセージ /*! \return int 0:成功  -1:失敗 */ void DisplayErrorMsg( int err ); //! angelscriptの関数実行前処理 /*! \param index ファンクション番号 (CAngelScriptMgrのAngelFuncListに登録してある番号) \return int 0:成功(angelscript内の関数呼び出し成功)  -1:失敗 */ int Before_Excute( int index ); //! angelscript内の関数の実行に失敗したときの共通エラーメッセージを表示する。 /*! 表示されるのはangelscriptの名前、モジュール名、ライン番号等 \return void */ void CAngelScriptMgr::CommonErrorMsg(); private: //! angelscript engine asIScriptEngine *m_pasengine; //! angelscript module asIScriptModule *m_pasmod; //! angelscript context asIScriptContext *m_pasctx; //! angelscript contextmgr CContextMgr *m_pcontextMgr; //! angelscript,c++の情報管理のためのマップ map<int,CAngelMap> m_mapAngelfunc; //! angelscriptの実行待ち時間(この時間がすぎればabort()をなげてangelscriptの関数は実行しない default=1000) DWORD m_dwTimeOut; }; #endif //_CANGELSCRIPT_MGR_H_ </textarea>

</form>

<form>

CAngelScriptMgr.cpp

<textarea rows="8" cols="75" readonly="readonly"> #include "CAngelScriptMgr.h" #include "CMoveObject.h" #include <windows.h> // timeGetTime() #include "LogUtility.h" #define OK 0 #define NG -1 //angelscript,c++両方で使用できるグローバル変数を定義する float g_fdata = 0; float g_fx = 0; float g_fy = 0; int g_LogLevel = LOG_WARN; //scriptひとつひとつ読み込み、ビルドに成功した場合bsuccessをtrueに設定しておく struct _ScriptList { char *scriptname; //angel script名 bool bsuccess; //scrptnameのangelscriptがビルドできたか }ScriptList[] = { { "resource/script/test11.as", false }, { "resource/script/test12.as",false }, }; #define ANGEL_SCRIPT_NUM (sizeof(ScriptList)/sizeof(ScriptList[0]) ) //angle scritptないで使用するmethodがふえたらここに追加 //別々のscript(ファイル)にある関数でもここにはすべて記述する。 chDescriptionにはどのファイル名で定義してあるかも記述しておく //asIScriptContextのmethodでangelscriptから戻り値を受け取ることができるのは以下の型のみ //chFuncIDは戻り値の型が違う場合c++側で再コンパイルが必要 //GetReturnAddress(),GetReturnByte(),GetReturnDouble() //GetReturnDWord(),GetReturnFloat(),GetReturnObject() //GetReturnQWord(),GetReturnWord() struct _AngelFuncList { int iID; //index、for,while 用途 char *chFuncID; //angle scriptのasIScriptContext->Prepare(funcId); のfuncIdに指定する文字列 char *chDescription; //angle script用の関数説明用 }AngelFuncList[] = { {0,"float test1()","print test file:test11.as"}, {1,"CMoveObject getscriptreturn()"," file:test11.as"}, {2,"CMoveObject getscriptreturn2( CMoveObject cmove )"," file:test11.as"}, {3,"float test2()"," file:test2.as"}, {4,"float TestCorutine()","corotine test file::test3.as"}, //{3,"int test4()",""}, }; //anglesciprtで使用する関数の数 #define ANGEL_FUNC_NUM (sizeof(AngelFuncList)/sizeof(AngelFuncList[0]) ) //このクラスのコンストラクタで、angelscriptの関数類を使えるようにしておく CAngelScriptMgr::CAngelScriptMgr() : m_pasengine( NULL ),m_pasmod( NULL ),m_pasctx( NULL ), m_pcontextMgr( NULL ), m_dwTimeOut( 1000 ) { int iRet = OK; m_mapAngelfunc.clear(); //angelscriptのengine初期化 iRet = InitializeAngelEngine(); assert( iRet >= 0 ); //c++,angelscript両方で使用する変数登録 iRet = RegisterProperty(); assert( iRet >= 0 ); //angelscriptで使用したいc++のクラスを登録 iRet = RegisterMyClass(); assert( iRet >= 0 ); //angelscriptをひとつひとつ読み込みビルドできるかcheck iRet = CheckBuild(); assert( iRet >= 0 ); SetAngelFuncMap(); } CAngelScriptMgr::~CAngelScriptMgr() { if( m_pasctx != NULL ) { m_pasctx->Release(); } if( m_pasengine != NULL ) { m_pasengine->Release(); } if( m_pcontextMgr != NULL ) { delete m_pcontextMgr; m_pcontextMgr = NULL; } if( m_pasmod != NULL ) { m_pasmod = NULL; } m_mapAngelfunc.clear(); } void CAngelScriptMgr::CommonErrorMsg() { int ifuncid = m_pasctx->GetExceptionFunction(); asIScriptFunction *func = m_pasengine->GetFunctionDescriptorById( ifuncid ); cout << "func: " << func->GetDeclaration() << endl; cout << "modl: " << func->GetModuleName() << endl; cout << "sect: " << func->GetScriptSectionName() << endl; cout << "line: " << m_pasctx->GetExceptionLineNumber() << endl; cout << "desc: " << m_pasctx->GetExceptionString() << endl; PUT_LOG( g_LogLevel,"func:%sn",func->GetDeclaration() ); PUT_LOG( g_LogLevel,"modl:%s\n", func->GetModuleName() ); PUT_LOG( g_LogLevel,"sect:%s\n", func->GetScriptSectionName() ); PUT_LOG( g_LogLevel,"line:%d\n", m_pasctx->GetExceptionLineNumber() ); PUT_LOG( g_LogLevel,"line:%d\n", m_pasctx->GetExceptionString() ); func->Release(); } void CAngelScriptMgr::DisplayErrorMsg( int err ) { int ifuncid = m_pasctx->GetExceptionFunction(); asIScriptFunction *func = m_pasengine->GetFunctionDescriptorById( ifuncid ); //エラー内容によってメッセージを分ける。coutはコマンドライン用、PUT_LOGはOutputDebugPrintを使い //どちらでもメッセージが出力されるようにする switch( err ) { case asEXECUTION_ABORTED: cout << "The script was aborted before it could finish. Probably it timed out." << endl; PUT_LOG( g_LogLevel,"The script was aborted before it could finish. Probably it timed out.n" ); break; case asEXECUTION_EXCEPTION: cout << "The script ended with an exception." << endl; PUT_LOG( g_LogLevel,"The script ended with an exception.n" ); //共通エラーメッセージ CommonErrorMsg(); break; case asEXECUTION_ERROR: cout << "The script ended with an exception error." << endl; PUT_LOG( g_LogLevel,"The script ended with an exception error.n" ); //共通エラーメッセージ CommonErrorMsg(); default: cout << "Unknown error " << endl; PUT_LOG( g_LogLevel,"Unknown error.n" ); break; } } //angelscript内の関数に時間がかかる場合はabortを投げて例外終了させる void LineCallback2( asIScriptContext *ctx, DWORD *timeOut ) { // If the time out is reached we abort the script if( *timeOut < timeGetTime() ) { ctx->Abort(); } // It would also be possible to only suspend the script, // instead of aborting it. That would allow the application // to resume the execution where it left of at a later // time, by simply calling Execute() again. } //angelscript前にタイムアウト時間やmapにあるangelscriptのfuncIDを取得する。 int CAngelScriptMgr::Before_Excute( int index ) { int iRet = OK; CAngelMap mapdata; //int ifuncid = m_mapAngelfunc[string(chFunc)]; mapdata = m_mapAngelfunc[index]; // Create our context, prepare it, and then execute m_pasctx = m_pasengine->CreateContext(); //anglescriptの関数を実行するための準備 m_pasctx->Prepare( mapdata.iAngelFuncID ); // We don't want to allow the script to hang the application, e.g. with an // infinite loop, so we'll use the line callback function to set a timeout // that will abort the script after a certain time. Before executing the // script the timeOut variable will be set to the time when the script must // stop executing. DWORD timeOut; iRet = m_pasctx->SetLineCallback( asFUNCTION( LineCallback2 ), &timeOut, asCALL_CDECL ); if( iRet < 0 ) { cout << "Failed to set the line callback function." << endl; PUT_LOG( g_LogLevel,"Failed to set the line callback function.n" ); return NG; } // Set the timeout before executing the function. Give the function 1 sec // to return before we'll abort it. // timeoutは1秒(1000ミリ秒)にしておく。SetScriptTimeOutで指定されていればその値 timeOut = timeGetTime() + m_dwTimeOut; return iRet; } //この関数では戻り値float,引数なしの関数を実行する //indexにしていするのはAngelFuncList[]のインデックス値 int CAngelScriptMgr::Excute( int index, float &fret ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { fret = m_pasctx->GetReturnFloat(); } return iRet; } //この関数では戻り値float,引数なしの関数を実行する //indexにしていするのはAngelFuncList[]のインデックス値 int CAngelScriptMgr::Excute( int index,double &dret ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { dret = m_pasctx->GetReturnDouble(); } return iRet; } //angelscritの引数をセットする int CAngelScriptMgr::Excute( int index,CMoveObject *ret ) { int iRet = OK; iRet = Before_Excute( index ); if( iRet != 0 ) { return NG; } //angelscriptに引数をセット,複数の引数にする場合クラスにまとめた方がよさそう iRet = m_pasctx->SetArgObject( 0,(void*)ret ); if( iRet != 0 ) { return NG; } //angel scriptの実行 iRet = m_pasctx->Execute(); //angelscript内の関数に実行した場合、エラー表示を行う if( iRet != asEXECUTION_FINISHED ) { DisplayErrorMsg( iRet ); } else { *ret = *(CMoveObject*)(void*)m_pasctx->GetReturnObject(); } return iRet; } int CAngelScriptMgr::GetAngelFuncNum() { return m_mapAngelfunc.size(); } int CAngelScriptMgr::SetAngelFuncMap() { int iRet = OK; int iangelfuncnum = 0; for( int i = 0; i < ANGEL_SCRIPT_NUM; i++) { //buildに成功したangelscriptのみ読み込み if( ScriptList[i].bsuccess == true ) { LoadScript( ScriptList[i].scriptname ); iangelfuncnum++; } } //使用できるangelscriptのみモジュールとしてbuild BuildAngelScript(); for( int i = 0; i < ANGEL_FUNC_NUM; i++) { //anglescript内でのc++の関数のfuncidを取得しておく int ifuncid = m_pasmod->GetFunctionIdByDecl( AngelFuncList[i].chFuncID ); if( ifuncid < 0 ) { printf("The script must have the function %s. Please add it and try again.n",AngelFuncList[i].chFuncID ); PUT_LOG( g_LogLevel,"The script must have the function %s. Please add it and try again.n",AngelFuncList[i].chFuncID ); continue; } CAngelMap angeldata; angeldata.iAngelFuncID = ifuncid; angeldata.strFuncName = string( AngelFuncList[i].chFuncID ); m_mapAngelfunc[i] = angeldata; } return iRet; } int CAngelScriptMgr::CheckBuild() { int iRet = OK; for( int i = 0; i < ANGEL_SCRIPT_NUM; i++) { iRet = LoadScript( ScriptList[i].scriptname ); if( iRet == OK ) { iRet = BuildAngelScript(); if( iRet == OK ) { //angelscriptのビルドに成功したらtrueに設定しておく ScriptList[i].bsuccess = true; } else { printf("faile build script name %sn",ScriptList[i].scriptname ); PUT_LOG( g_LogLevel,"faile build script name %sn",ScriptList[i].scriptname ); } } } return iRet; } int CAngelScriptMgr::LoadScript( char *ScriptName ) { int iRet = OK; FILE *f = fopen(ScriptName, "rb"); if ( f == NULL ) { printf(" file not foundn"); PUT_LOG( g_LogLevel,"file not foundn"); return NG; } fseek(f, 0, SEEK_END); //file sizeを取得する int len = ftell( f ); fseek( f, 0, SEEK_SET ); std::string script; script.resize(len); size_t c = fread( &script[0], len, 1, f ); fclose(f); //scriptのファイル名でセクションを登録する。 iRet = m_pasmod->AddScriptSection( ScriptName, &script[0], len ); return iRet; } //この関数はangelscriptひとつひとつチェックした後 //buildに成功したすべてのangelscriptをモジュールとして再Buildする。 int CAngelScriptMgr::BuildAngelScript() { int iRet = OK; iRet = m_pasmod->Build(); if( iRet < 0 ) { printf("angel script build failedn" ); PUT_LOG( g_LogLevel,"angel script build failedn"); return NG; } return iRet; } void MessageCallback2( const asSMessageInfo *msg, void *param ) { const char *type = "ERR "; if( msg->type == asMSGTYPE_WARNING ) { type = "WARN"; } else if( msg->type == asMSGTYPE_INFORMATION ) { type = "INFO"; } printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message); PUT_LOG( g_LogLevel,"%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message ); } void print2( string &msg ) { std::cout << msg << std::endl; } void print2( int num ) { std::cout << num << std::endl; } void print2( asUINT num ) { std::cout << num << std::endl; } void print2( float num ) { std::cout << num << std::endl; } void print2( double num ) { std::cout << num << std::endl; } int CAngelScriptMgr::RegisterProperty() { int iRet = OK; iRet = m_pasengine->RegisterGlobalProperty("int g_fdata", &g_fdata); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalProperty("int g_fx", &g_fx); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalProperty("int g_fy", &g_fy); assert( iRet >= 0 ); return iRet; } int CAngelScriptMgr::RegisterMyClass() { //CMoveObject.hにあるクラスを登録 int iRet = OK; iRet = m_pasengine->RegisterObjectType("CMoveObject", sizeof(CMoveObject), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fx", offsetof(CMoveObject, fx)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fy", offsetof(CMoveObject, fy)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fwidth", offsetof(CMoveObject, fwidth)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fheight", offsetof(CMoveObject, fheight)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fhitradius", offsetof(CMoveObject, fhitradius)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float facceleration", offsetof(CMoveObject, facceleration)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fdirection", offsetof(CMoveObject, fdirection)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fspeed", offsetof(CMoveObject, fspeed)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fangle", offsetof(CMoveObject, fangle)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float finterval", offsetof(CMoveObject, finterval)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float flevel", offsetof(CMoveObject, flevel)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fkind", offsetof(CMoveObject, fkind)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fcolor", offsetof(CMoveObject, fcolor)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float falpha", offsetof(CMoveObject, falpha)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float falive", offsetof(CMoveObject, falive)); assert( iRet >= 0 ); iRet = m_pasengine->RegisterObjectProperty("CMoveObject", "float fscale", offsetof(CMoveObject, fscale)); assert( iRet >= 0 ); return iRet; } int CAngelScriptMgr::InitializeAngelEngine() { PUT_LOG( g_LogLevel,"start\n" ); int iRet = OK; // Create the script engine m_pasengine = asCreateScriptEngine(ANGELSCRIPT_VERSION); //SHIFT-JIS対応 m_pasengine->SetEngineProperty(asEP_SCRIPT_SCANNER ,0); // Set the message callback to receive information on errors in human readable form. // It's recommended to do this right after the creation of the engine, because if // some registration fails the engine may send valuable information to the message // stream. iRet = m_pasengine->SetMessageCallback( asFUNCTION( MessageCallback2 ), 0, asCALL_CDECL ); assert( iRet >= 0 ); if( iRet < 0 ) { printf("failed Message Callbackn" ); PUT_LOG( g_LogLevel,"failed Message Callbackn" ); return NG; } m_pasmod = m_pasengine->GetModule( 0, asGM_ALWAYS_CREATE ); if( iRet < 0 ) { printf("failed GetModulen" ); PUT_LOG( g_LogLevel,"failed GetModulen" ); return NG; } // AngelScript doesn't have a built-in string type, as there is no definite standard // string type for C++ applications. Every developer is free to register it's own string type. // The SDK do however provide a standard add-on for registering a string type, so it's not // necessary to implement the registration yourself if you don't want to. RegisterStdString( m_pasengine ); //anglescript側でprint(string),print(型)でそれぞれの値を表示できるようにする。print系は複数 //GUIやwindow関連では以下のprint関数は使えないため無意味 iRet = m_pasengine->RegisterGlobalFunction( "void print(const string &in)", asFUNCTIONPR(print2, (string &in), void), asCALL_CDECL ); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalFunction( "void print(int)", asFUNCTIONPR(print2, (int), void), asCALL_CDECL ); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalFunction( "void print(float)", asFUNCTIONPR(print2, (float), void), asCALL_CDECL ); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalFunction( "void print(uint)", asFUNCTIONPR(print2, (asUINT), void), asCALL_CDECL ); assert( iRet >= 0 ); iRet = m_pasengine->RegisterGlobalFunction( "void print(double)", asFUNCTIONPR(print2, (double), void), asCALL_CDECL ); assert( iRet >= 0 ); RegisterScriptAny( m_pasengine ); // Add the support for co-routines m_pcontextMgr = new CContextMgr(); m_pcontextMgr->RegisterCoRoutineSupport( m_pasengine ); return iRet; } void CAngelScriptMgr::SetScriptTimeOut( DWORD dwMsec ) { //angelscriptの実行タイムアウト設定 m_dwTimeOut = dwMsec; } DWORD CAngelScriptMgr::GetScriptTimeOut() { //angelscriptのタイムアウト時間 return m_dwTimeOut; } </textarea>

</form>

timeEvent使い方

2010-01-17 14:22:38 | angelscript

timeEvnet( VC++での実装(angelscriptとの連携なし ) ) timeEvnetのコールバックに自作クラスを登録する。
コールバック関数でtimeKillEvnetを実行するため。

common.h

CTimeEvent.h

CTimeEvent.cpp

main.cpp



<form>

common.h

<textarea readonly="readonly" cols="75" rows="8">#ifndef _COMMON_H_ #define _COMMON_H_ #include "DxLib.h" #include "LogUtility.h" #include "const.h" #endif //_COMMON_H_ </textarea>

</form>

<form>

CTimeEvent.h

<textarea readonly="readonly" cols="75" rows="8">#ifndef _CTIMEEVNET_H_ #define _CTIMEEVNET_H_ #define COUNTUP 0 #define COUNTDOWN 1 class CTimeEvent { public: //! CTimeEvent constructor /*! */ CTimeEvent(); //! CTimeEvent desstructor /*! */ ~CTimeEvent(); //! timeSetEvnetのインターバル設定 /*!   \param iMillsec timeSetEvnetのインターバル設定(何も設定しなければ1秒を設定)   \return void */ void SetTimeInterval( int iMillsec = 1000 ); //! timeSetEvnetでm_iCountMode=0だったらカウントアップ,m_iCountMode=1だったらカウントダウン /*!   \return void */ void Count(); //! timeSetEvnetのコールバック関数でカウントアップやカウントダウンされる値の設定 /*!   \param iFinishCount コールバックの終了タイムを設定   \param imode imode=COUNTDOWNならiFinishCountの値を0にするまでtimeEvnet発生,imode=COUNTUPだったらiFinishCountまでカウントアップ   \return void */ void SetCounter( int iFinishCount,int imode = COUNTDOWN ); //! m_iFinishCountのgetter /*!   \return int */ int  GetCounter(); //! timeEvnetが実行中かを表すフラグ /*!   \return int  1:timeEvent実行中   0:timeEventは実行されていない */ int IsRunning(); //! timeEvnetのスタート(コールバック関数はCTimeEvent.cppで定義) /*!   \return int  0:失敗  0以外:timeKillEvnetに使用するTimerID */ int StartTimeEvent(); //! timeEvnet実行中フラグのセット、StartTimeEvnetに成功した場合 /*!   \return void */ void SetRunningFlag( int iRun ); //! メンバ変数の初期化 (timeKillEvnetを実行した後は必ずこいつを呼ぶ) /*!   \return void */ void ResetValue(); private: //! timeSetEvnetのインターバル設定 int m_iInterval; //! timeSetEvnetのcallbackでの終わり判定用変数(カウントダウン用) int m_iFinishCount; //! timeSetEvnetのcallbackでの現在値保持よう変数カウントアップ用) int m_iNowCount; //! timeSetEvnetのcallbackでのカウントアップかカウントアップ判定用変数 int m_iCountMode; ////! timeSetEvnetの実行中フラグ int m_iRunning; ////! timeSetEvnetの戻り値格納 unsigned int m_uiTimerID; }; #endif //_CTIMEEVNET_H_ </textarea>

</form>

<form>

CTimeEvent.cpp

<textarea readonly="readonly" cols="75" rows="8">#include "CTimeEvent.h" #include "common.h" void CALLBACK TimeCallBack(unsigned int timerID, unsigned int msg, unsigned int usrParam, unsigned int dw1, unsigned int dw2) { ((CTimeEvent*)usrParam)->Count(); if( ((CTimeEvent*)usrParam)->IsRunning() == 0 ) { //timeEventの終了 timeKillEvent( timerID ); //再利用のためメンバ変数を初期化 ((CTimeEvent*)usrParam)->ResetValue(); } } CTimeEvent::CTimeEvent() : m_iInterval(0),m_iFinishCount(0),m_iNowCount(0),m_iCountMode(0),m_iRunning(0),m_uiTimerID(0) { } CTimeEvent::~CTimeEvent() { } void CTimeEvent::SetTimeInterval( int iMillsec ) { //timeSetEvnetのインターバル m_iInterval = iMillsec; } void CTimeEvent::SetCounter( int iFinishCount,int imode ) { if( iFinishCount > 0 ) { m_iFinishCount = iFinishCount; } switch( imode ) { case COUNTUP: m_iCountMode = COUNTUP; break; case COUNTDOWN: m_iCountMode = COUNTDOWN; break; default: break; } } void CTimeEvent::Count() { bool bEnd = false; //モードによってカウントアップ、カウントダウンを行う。 switch( m_iCountMode ) { case COUNTUP: if( m_iFinishCount <= m_iNowCount ) { bEnd = true; } if( m_iFinishCount > m_iNowCount ) { m_iNowCount++; } break; case COUNTDOWN: if( m_iFinishCount < 0 ) { bEnd = true; } else if( m_iFinishCount > 0 ) { m_iFinishCount--; PUT_LOG(LOG_WARN,"m_iFinishCount %d\n",m_iFinishCount); } break; default: break; } //countup,countdownのtimeEvnet終了したらメンバ変数を初期しておく if( bEnd == true ) { m_iRunning = 0; } } int CTimeEvent::GetCounter() { int iret = -9999; switch( m_iCountMode ) { case COUNTUP: //カウントアップしているときは現在の数値を iret = m_iNowCount; break; case COUNTDOWN: //カウントダウンしているときは残りの数値 iret = m_iFinishCount; break; default: break; } return iret; } int CTimeEvent::IsRunning() { return m_iRunning; } int CTimeEvent::StartTimeEvent() { //timeSetEventの準備ができているかチェックする if( m_iRunning == 1 ) { //このクラスでtimeEventを実行しているならなにもしない return NG; } if( m_iInterval == 0 ) { //timeSetEventのインターバルが設定されていなければ何もしない return NG; } //timeSetEvnetのTimeCallBack関数に自分のクラスを登録 m_uiTimerID = timeSetEvent( m_iInterval,1,(LPTIMECALLBACK)TimeCallBack,(DWORD)this, TIME_PERIODIC ); if( m_uiTimerID == 0 ) { return NG; } return m_uiTimerID; } void CTimeEvent::SetRunningFlag( int iRun ) { m_iRunning = iRun; } void CTimeEvent::ResetValue( ) { //! timeSetEvnetのインターバル設定 int m_iInterval = 0; //! timeSetEvnetのcallbackでの終わり判定用変数(カウントダウン用) int m_iFinishCount = 0; //! timeSetEvnetのcallbackでの終わり判定用変数(カウントアップ用) int m_iNowCount = 0; //! timeSetEvnetのcallbackでのカウントアップかカウントアップ判定用変数 int m_iCountMode = 0; ////! timeSetEvnetの実行中フラグ int m_iRunning = 0; ////! timeSetEvnetの戻り値格納 unsigned int m_uiTimerID = 0; } </textarea>

</form>

<form>

main.cpp

mainではtimeSetEvnetのインターバル(引数を省略した場合1秒ごと)とtimeSetEvnetごとにカウントアップ、カウントダウンされる変数の登録後にStartTimeEvent()を実行する。
timeSetEvnetが別スレッドで動作するためmain部分にはSleep関数が必要。またCTimeSetEvent動作中は他のtimeSetEventが2度実行されないようにする。

<textarea readonly="readonly" cols="75" rows="8">int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow ) { timeBeginPeriod( 1 ); //test CAngelScriptMgr CAngelScriptMgr *ptest = new CAngelScriptMgr(); CMoveObject *pobj = new CMoveObject(); float ret; ptest->Excute( 0, ret ); ptest->Excute( 0, ret ); ptest->Excute( 2, pobj ); ptest->Excute( 2, pobj ); ptest->Excute( 2, pobj ); //test CAngelScriptMgr //test CTimeEvnet CTimeEvent time; time.SetCounter( 100 ); time.SetTimeInterval(); time.StartTimeEvent(); //test CTimeEvnet //SetJoypadInputStateToKeyInput( DX_INPUT_PAD1, PAD_INPUT_A, KEY_INPUT_Z, -1, -1, -1 );     ChangeWindowMode( TRUE );//ウィンドウモード     if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) { return -1;//初期化と裏画面化 } //CTimeMgr *ptimemgr = new CTimeMgr(); //ptimemgr->SetTimeEvnetParam( 1000,60 );     while( ProcessLoop() == 0 ) {//メインループ         if(CheckStateKey(KEY_INPUT_ESCAPE)==1) { break;//エスケープが入力されたらブレイク } switch( g_gamestatus ) { case GAME_STATUS_INIT: //初期化 //ptest->Excute( 2, pobj ); //printfDx( "fx:%f\n",pobj->fx ); //ptimemgr->StartTimeEvnegt(); time.Count(); break; case GAME_STATUS_TITLE: //title break; case GAME_STATUS_SHOOT: //game main break; case GAME_STATUS_MUSIC: //music room break; case GAME_STATUS_END: //end break; default: break; }         ScreenFlip();//裏画面反映 Sleep( 10 );     }     DxLib_End();//DXライブラリ終了処理 timeEndPeriod( 1 );     return 0; } </textarea>

</form>