This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Lua modülleri (Lua modules), projenizi yapılandırmanıza ve yeniden kullanılabilir kütüphane kodu oluşturmanıza olanak tanır. Projelerinizde kod tekrarından kaçınmak genellikle iyi bir fikirdir. Defold, Lua’nın modül özelliğini kullanarak betik (script) dosyalarını başka betik dosyalarına dahil etmenizi sağlar. Böylece işlevselliği (ve verileri) harici bir betik dosyasında kapsülleyerek oyun nesnesi (game object) ve GUI betik dosyalarında yeniden kullanabilirsiniz.
Oyun projenizin dizin yapısında herhangi bir yerde bulunan .lua uzantılı dosyalarda saklanan Lua kodu, require ile betik ve GUI betik dosyalarına yüklenebilir. Yeni bir Lua modülü dosyası oluşturmak için Assets görünümünde dosyayı oluşturmak istediğiniz klasöre sağ tıklayın, ardından New... ▸ Lua Module seçeneğini seçin. Dosyaya benzersiz bir ad verin ve Ok düğmesine basın:

Aşağıdaki kodun “main/anim.lua” dosyasına eklendiğini varsayalım:
function direction_animation(direction, char)
local d = ""
if direction.x > 0 then
d = "right"
elseif direction.x < 0 then
d = "left"
elseif direction.y > 0 then
d = "up"
elseif direction.y < 0 then
d = "down"
end
return hash(char .. "-" .. d)
end
Ardından herhangi bir betik bu dosyayı require ile yükleyip işlevi kullanabilir:
require "main.anim"
function update(self, dt)
-- update position, set direction etc
...
-- set animation
local anim = direction_animation(self.dir, "player")
if anim ~= self.current_anim then
sprite.play_flipbook("#sprite", anim)
self.current_anim = anim
end
end
require işlevi, belirtilen modülü yükler. Önce modülün zaten yüklenmiş olup olmadığını belirlemek için package.loaded tablosuna bakar. Modül yüklenmişse require, package.loaded[module_name] konumunda saklanan değeri döndürür. Aksi takdirde dosyayı bir yükleyici aracılığıyla yükler ve değerlendirir.
require işlevine verilen dosya adı dizesinin sözdizimi biraz özeldir. Lua, dosya adı dizesindeki . karakterlerini yol ayırıcılarıyla değiştirir: macOS ve Linux’ta /, Windows’ta ise \\ kullanılır.
Yukarıda yaptığımız gibi durum saklamak ve işlev tanımlamak için genel kapsamı (global scope) kullanmanın genellikle iyi bir fikir olmadığını unutmayın. Ad çakışmalarına yol açma, modülün durumunu dışarıya açma veya modülü kullanan kodlar arasında bağımlılık oluşturma riski vardır.
Lua, verileri ve işlevleri kapsüllemek için modülleri kullanır. Lua modülü, işlevleri ve verileri içermek için kullanılan sıradan bir Lua tablosudur. Genel kapsamı kirletmemek için tablo yerel olarak tanımlanır:
local M = {}
-- private
local message = "Hello world!"
function M.hello()
print(message)
end
return M
Ardından modül kullanılabilir. Burada da modülü yerel bir değişkene atamak tercih edilir:
local m = require "mymodule"
m.hello() --> "Hello world!"
Basit bir modülü ele alalım:
-- module.lua
local M = {} -- creates a new table in the local scope
M.value = 4711
return M
Modülü kullanan kod ise şöyle olsun:
local m = require "module"
print(m.value) --> "4711" (even if "module.lua" is changed and hot reloaded)
Modül dosyasını çalışma sırasında yeniden yüklerseniz (hot reload) kod yeniden çalıştırılır, ancak m.value değişmez. Bunun nedeni nedir?
İlk olarak, module.lua içindeki tablo yerel kapsamda (local scope) oluşturulur ve bu tabloya bir başvuru modülü kullanan koda döndürülür. module.lua dosyasını yeniden yüklemek modül kodunu yeniden değerlendirir, ancak bu işlem m değişkeninin başvurduğu tabloyu güncellemek yerine yerel kapsamda yeni bir tablo oluşturur.
İkinci olarak Lua, require ile yüklenen dosyaları önbelleğe alır. Bir dosya ilk kez yüklendiğinde package.loaded tablosuna yerleştirilir; böylece sonraki require çağrılarında daha hızlı okunabilir. Dosyanın tablodaki girdisini nil olarak ayarlayarak dosyanın diskten yeniden okunmasını zorlayabilirsiniz: package.loaded["my_module"] = nil.
Bir modülü çalışma sırasında doğru şekilde yeniden yüklemek için modülü yeniden yüklemeniz, önbelleği sıfırlamanız ve ardından modülü kullanan tüm dosyaları yeniden yüklemeniz gerekir. Bu, ideal bir çözüm olmaktan uzaktır.
Bunun yerine, geliştirme sırasında kullanabileceğiniz bir geçici çözümü düşünebilirsiniz: modül tablosunu genel kapsama yerleştirin ve dosya her değerlendirildiğinde yeni bir tablo oluşturmak yerine M değişkeninin genel kapsamdaki tabloya başvurmasını sağlayın. Böylece modülü yeniden yüklemek genel kapsamdaki tablonun içeriğini değiştirir:
--- module.lua
-- Replace with local M = {} when done
uniquevariable12345 = uniquevariable12345 or {}
local M = uniquevariable12345
M.value = 4711
return M
Durum tutan (stateful) modüller, modülü kullanan tüm kodlar arasında paylaşılan bir iç durum saklar ve tek örnekli yapılara (singleton) benzetilebilir:
local M = {}
-- all users of the module will share this table
local state = {}
function M.do_something(foobar)
table.insert(state, foobar)
end
return M
Durum tutmayan (stateless) bir modül ise herhangi bir iç durum saklamaz. Bunun yerine, durumu, modülü kullanan kodun yerel kapsamında bulunan ayrı bir tabloya taşıyan bir mekanizma sağlar. Bunu uygulamanın birkaç farklı yolu vardır:
local M = {}
function M.alter_state(the_state, v)
the_state.value = the_state.value + v
end
function M.get_state(the_state)
return the_state.value
end
function M.new(v)
local state = {
value = v
}
return state
end
return M
Modülü şu şekilde kullanın:
local m = require "main.mymodule"
local my_state = m.new(42)
m.alter_state(my_state, 1)
print(m.get_state(my_state)) --> 43
local M = {}
function M:alter_state(v)
-- self is added as first argument when using : notation
self.value = self.value + v
end
function M:get_state()
return self.value
end
function M.new(v)
local state = {
value = v
}
return setmetatable(state, { __index = M })
end
return M
Modülü şu şekilde kullanın:
local m = require "main.mymodule"
local my_state = m.new(42)
my_state:alter_state(1) -- "my_state" is added as first argument when using : notation
print(my_state:get_state()) --> 43
__index meta yöntemlerinden geçmesi gerekmediği için bu yöntem meta tablo kullanımından biraz daha hızlıdır; ancak her kapanış yöntemlerin kendi kopyasını içerdiğinden bellek tüketimi daha yüksektir. local M = {}
function M.new(v)
local state = {
value = v
}
state.alter_state = function(v)
state.value = state.value + v
end
state.get_state = function()
return state.value
end
return state
end
return M
Modülü şu şekilde kullanın:
local m = require "main.mymodule"
local my_state = m.new(42)
my_state.alter_state(1)
print(my_state.get_state())