1

Allegro 5 で Lua と LuaBridge を使用しています。すべてのグラフィック オブジェクトを Lua に移植することにしましたが、いくつかの問題が発生しています。

一度呼び出される文字クラス

Character = {sprite; AI}

function Character:new()
  o = o or {} -- works!
  setmetatable(o, self) -- works!
  self.__index = self  -- works!
  return o -- works!
end

function Character:LoadSprite(filename)
  self.sprite = self.sprite or Bitmap() -- works!
  self.sprite:LoadFile(filename) -- works!
  self.sprite.x = 0 -- works!
  self.sprite.y = 0 --works!
end

function Character:SetX(xx)
  self.sprite.x = xx -- maybe? cannot tell if it works or not.
end

function Character:AddBehavior(fname, cname)
    self.AI = self.AI or Pattern()
    self.AI:AddBehavior(fname, cname)
end

function Character:Draw()
  self.sprite:Draw() -- works!
 end

Foo = Character:new()

関数がメイン プログラムから呼び出される Lua スクリプト:

function CoreInit() --called at initialization
  Foo:LoadSprite("Image.png") -- works!
end

function CoreLogic() --called during logic cycle
  Foo:SetX(50)  -- does NOT work!
end

function CoreDraw() --called during drawing/rendering cycle
  Foo:Draw()  --works perfectly!
end

基本的に、スクリプトは適切な座標と画像でキャラクターを初期化し、それを描画しますが、ロジックが呼び出されていない (ロジック ループ内にある) か、X 座標を変更する関数に問題があります。

また、タスク マネージャーは、C++ で画像オブジェクトを持っていたときには発生しなかった、サイクルごとに約 30 KB のメモリ リークがあることを示唆しています。

必要な場合に備えて、LuaBridge 経由で Lua にエクスポートされた Bitmap 構造体のスニペットを次に示します。

void Bitmap::Register(lua_State*lua) {
  luabridge::getGlobalNamespace(lua)
    .beginClass<Bitmap>("Bitmap")
    .addConstructor <void (*) (void)> ()
    .addStaticData("scale", &Bitmap::scale)
    .addFunction("LoadFile", &Bitmap::LoadFile)
    .addFunction("Draw", &Bitmap::Draw)
    .addData("x", &Bitmap::x)
    .addData("y", &Bitmap::y)
    .addData("w", &Bitmap::w)
    .addData("h", &Bitmap::h)
  .endClass();
}


void Bitmap::LoadFile(string file) {
  name = file;
  bitmap = al_load_bitmap(file.c_str());
  w = al_get_bitmap_width(bitmap);
  h = al_get_bitmap_height(bitmap);
}

void Bitmap::Draw() {
  if (scale > 1)
    al_draw_scaled_bitmap(bitmap, 0, 0, w, h, x * scale , y * scale, w * scale, h * scale, 0);
  else
    al_draw_bitmap(bitmap, x, y, 0);
}

Bitmap::Bitmap() :  velocity(1) {
   bitmap = NULL; 

}
Bitmap::~Bitmap() {
  name = "";
  if (!bitmap) 
    al_destroy_bitmap(bitmap);
}

更新: 私が把握できたことの 1 つは、メモリ リークがCoreLogicから発生していることです。C++ での呼び出しをコメント アウトすると、メモリ リークはなくなりましたが、呼び出しをそのままにして、CoreLogicの内容をコメント アウトすると、リークは続きました。うーん...

2 番目の更新: メモリ リークは、私が投稿していない AI の何かに絞り込まれました。

Pattern = {complete; timer; command; Files; Commands; itr; num}

function Pattern:new()
  o = o or {}
  o.Files = {}
  o.Commands = {}
  o.complete = false
  o.timer = 0
  o.itr = 1
  o.num = 1
  setmetatable(o, self)
  self.__index = self
  return o
end

function Pattern:AddBehavior(filename, commandname)
  self.Files[self.num] = filename
  self.Commands[self.num] = commandname
  self.num = self.num + 1
end

function Pattern:DoBehavior()
  self.command = self.Commands[self.itr]
  dofile(self.Files[self.itr])
end

function Pattern:CheckBehavior()
  if self.complete == true then
    self.itr = self.itr + 1
self.timer = 0
self.complete = false
  end
  if itr >= num then
    self.itr   = 1
self.timer = 0
self.complete = false
  end
end

function Pattern:Initialize()
  self.itr = 1; self.timer = 0
  self.complete = false
  self.command = self.Commands[self.itr]
end

また、CoreLogic関数ではFoo.AI:DoBehavior()を呼び出しますが、これはまったく何もせず、メモリ リークを引き起こしました。

4

2 に答える 2

1

Foo.AI:DoBehavior()ファイルからチャンクを読み取り、その内容、バイトコード変換された形式、関数環境、およびこのファイルの最上位で作成される可能性のある一時的な値のためにメモリを予約します。ここでメモリが失われることが予想され、リークではありません。Lua はすぐにメモリを解放しません。実際には、システムにまったく返されません。

ガベージ コレクターが実行され、使用されなくなった文字列、テーブル、関数などを見つけることがあります。Lua は、このメモリを独自の内部インデックスで空きとしてマークし、次に空きメモリが必要になったときにそれを使用しますが、システムから見た Lua のメモリ消費は決して縮小しません。

プログラムの一部が自動 GC 呼び出しの間に不要なガベージを生成しすぎる可能性があると思われる場合は、collectgarbageC API または C API を使用して GC ステップを強制することができます。

于 2012-11-23T22:27:21.663 に答える
0

もう少し手間をかけた後、問題を解決することができました。基本的に、Patternテーブルのコンストラクターと、AIオブジェクトがCharacterでどのように初期化されたかに戻りました。コンストラクターを次のように変更する必要がありました。

Pattern = {complete; timer; command; Files; Commands; itr; num}

function Pattern:new()
  o = o or {}
  o.Files = {}
  o.Commands = {}
  o.complete = false
  o.timer = 0
  o.itr = 1
  o.num = 1
  setmetatable(o, self)
  self.__index = self
  return o
end

に:

Pattern = {}

function Pattern:new()
  local o = {complete = false; timer = 0; command = ""; Files = {}; Commands = {}; itr = 1; num = 1}
  setmetatable(o, self)
  self.__index = self
  return o
end

この:

Character = {sprite; AI}

function Character:new()
  o = o or {} 
  setmetatable(o, self) 
  self.__index = self 
  return o 
end

に:

Character = {}

function Character:new()
  local o = {sprite; AI = Pattern:new()}
  setmetatable(o, self)
  self.__index = self
  return o
end

これで、 Foo.AI:DoBehavior()の呼び出しが想定どおりに実行され、余分なメモリは使用されなくなりました。このコードは、私が初めて Lua で OOP を実装しようとしたものであり、おそらくこれからはこの方法で行おうとしています。

于 2012-11-24T10:28:23.207 に答える