2

LuaBindを使用してC++アプリケーションにLuaを埋め込みました。同じファイル名を実行する他のオブジェクトからアクセスできない、複数の実行にわたって持続する変数が必要です。

例:。というクラスがあるとしNPCます。は文字列を保持します。これNPCは、実行するスクリプトの名前です。がNPC作成されると、と呼ばれる変数が作成されHealthます。ヒットするNPCと、体力が5減少します。Luaのスクリプトは次のようになります。

local health = 10

function onHit()
    health = health - 5
end

私がこれに関して抱えている問題は、このスクリプトを実行するすべてNPCのものが、独自のヘルスインスタンスを持っていないということです。たとえば、を作成しNPC A、そのヘルスから5を引いたとします。次に、を作成しますNPC B。ヘルスを10にリセットするため、NPC Aヘルスを印刷するように指示すると、5であるはずなのに、10に戻ります。

オブジェクトごとに異なるLuaインスタンスを使用すると、そのように機能しますが、その場合、一度に数百のインスタンスが作成されることになります。これは良いことではないことを理解しています。

Luaで変数をこのように機能させる方法はありますか?そうでない場合、このように効率的に機能するスクリプト言語はありますか?

参考までに、私がテストしているコードは次のとおりです。

Lua:

local health = 10;

function onHit()
    health = health - 5
    print_out(health)
end

C ++:

class NPC
{
public:
   NPC(lua_State* inState);
   void onHit();

   const char* behavior;
   lua_State* luaState;  
};

NPC::NPC(lua_State* inState)
{
   luaState = inState;
   behavior = "testBehavior.lua";
   luaL_dofile(luaState, behavior);
}

void NPC::onHit()
{    
   luaL_loadfile(luaState, behavior); 
   luabind::call_function<int>(luaState, "onHit");
}

void print_out(int number) {
   cout << "Health : " << number << endl;
}

int main() 
{
   lua_State *myLuaState = luaL_newstate();
   luabind::open(myLuaState);

   luabind::module(myLuaState) [
      luabind::def("print_out", print_out)
   ];

   NPC test(myLuaState);
   NPC test2(myLuaState);
   test.onHit();
   test2.onHit();
   test.onHit();

   lua_close(myLuaState);
}
4

4 に答える 4

8

あなたはルアのクロージャを調べることができます。次のようになります。

function healthPoints()
    local health = 10
    return function()
        health = health - 5
        return health
    end
end

何が起こるかというと、各NPCは独自のカウンターで独自の機能を取得します。それらがヒットするたびに、onHit関数を呼び出すだけです。あなたはそれを次のように使うでしょう:

npc1.onHit = healthPoints()
npc2.onHit = healthPoints()
npc1.onHit() -- Now at 5, while npc2 is still at 10

次のようなパラメータを追加します。

function healthPoints(hp)
    local health = hp
    return function(dmg)
        health = health - dmg
        return health
    end
end

npc1.onHit = healthPoints(100)
npc1.onHit(-12)

一撃の価値があると思います。

于 2012-12-30T05:05:26.677 に答える
4

参考までに、私がテストしているコードは次のとおりです。

ここには多くの間違いがあります。Luaスクリプトを再実行し続けます。それがリセットされ続ける理由です。もう1つの問題は、スクリプトがグローバル関数を作成しているため、スクリプトを実行するたびに、新しい変数を使用する新しいグローバル関数を取得することです。 local

グローバルの使用を停止します。各NPCは個別のオブジェクトです。したがって、オブジェクト固有のデータが必要です。

behavior = "testBehavior.lua";
luaL_dofile(luaState, behavior);

これにより、オブジェクト固有のデータは作成されません。Luaスクリプトを実行するだけで、戻り値は完全に破棄されます。そのスクリプトが実際にオブジェクト固有のものをグローバルに格納しない限り、オブジェクト固有のデータは作成されません。

Luaスクリプトが行う必要があるのは、スクリプトがオブジェクトに必要とするオブジェクト固有のデータを含むテーブルを返すことです。スクリプトは次のようになります。

local function onHit(self)
    self.health = self.health - 5
end

return {
  health = 10,
  onHit = onHit,
}

C ++コードは、このテーブルをNPCクラスに格納してから、それを使用する必要があります。これは、Luabind呼び出しを介して簡単に実行できます。コンストラクターは次のようになります。

NPC::NPC(lua_State* L)
{
    behavior = "testBehavior.lua";
    int err = luaL_loadfile(L, behavior);
    //Handle compiler errors. DON'T FORGET THIS!
    luabind::object func = luabind::from_stack(L, -1);
    lua_pop(L, 1);
    luaData = func(); //Catch exceptions for runtime errors
    lua_pop(L, 1);
}

クラスに参加する代わりにlua_State* luaState、クラスに参加し続けluabind::object luaDataます。が必要な場合はlua_State、いつでもから取得できますluabind::object

LuaonHit関数を呼び出すには、次のluabind::objectインターフェイスを使用します。

void NPC::onHit()
{    
    luaData["onHit"](luaData);
}

Luaスクリプトを再実行しないことに注意してください。それがあなたの問題でした。Luaスクリプトがすでに定義している関数を呼び出しているだけです。

今、あなたはテーブルメモリの代わりにローカルを使いたいようです。それはいいです; これにより、C ++コードが直接アクセスできなくなりhealthます(トリックなしではありません)。また、に渡す必要がないため、コードが簡略化luaDataされonHitます。これでLuaでそれを行うことができます:

local health = 10
local NPC = {}

function NPC.onHit()
  health = health - 5
end

return NPC

NPCコンストラクターを変更する必要はありません。への呼び出しだけonHitです。

void NPC::onHit()
{    
    luaData["onHit"]();
}

グローバルの使用に行き詰まっている場合は、環境でゲームをプレイできますが、それはかなり複雑です。これにより、個々のスクリプト呼び出し間の分離が保証されます。

于 2012-12-30T21:30:41.930 に答える
2

Luaについては知らないので、それについては話しません。質問はPythonとしてもタグ付けされます。そのためには、「重要」なすべてのローカル変数をシリアル化できると思います。

または、ここでPyDONという辞書を永続化して、私のトリックを確認することもできます:http: //code.activestate.com/recipes/577508-pydon-an-alternative-to-xml/

また、これを確認してください。これはさらに役立つと思います。Python辞書を文字列にシリアル化してから、辞書に戻すにはどうすればよいですか。

于 2012-12-30T03:57:43.850 に答える
2

やり過ぎに思えるかもしれませんが、必要な値をSQLiteテーブルに保存してみませんか?

于 2012-12-30T04:00:34.320 に答える