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
İleti aktarımı (message passing), Defold oyun nesnelerinin (game object) birbirleriyle iletişim kurmasını sağlayan bir mekanizmadır. Bu kılavuz, Defold’un adresleme mekanizması ve temel yapı taşları hakkında temel bilgiye sahip olduğunuzu varsayar.
Defold’daki nesne yönelimi, uygulamanızı (Java, C++ veya C#’ta olduğu gibi) kalıtım içeren sınıf hiyerarşileri kurarak ve nesnelerinizde üye işlevler tanımlayarak oluşturmanız anlamına gelmez. Bunun yerine Defold, Lua’yı nesne durumunun betik bileşenlerinde (script component) tutulduğu ve self başvurusu üzerinden erişilebildiği basit ve güçlü bir nesne yönelimli tasarımla genişletir. Ayrıca nesneler arasında iletişim için eşzamansız ileti aktarımı kullanılarak nesneler birbirinden tamamen bağımsız tutulabilir.
Önce birkaç basit kullanım örneğine bakalım. Şu öğelerden oluşan bir oyun geliştirdiğinizi varsayalım:

Bu örneğin içeriği iki ayrı dosyada bulunur. Ana başlangıç koleksiyonu için bir dosya, “level” tanımlayıcısına sahip koleksiyon için de bir dosya vardır. Ancak Defold’da dosya adları önemli değildir. Önemli olan, örneklere (instance) atadığınız kimliktir.
Oyunda, nesneler arasında iletişim gerektiren birkaç basit mekanik vardır:

"punch" iletisi gönderilir. Her iki nesne de koleksiyon hiyerarşisinde aynı yerde bulunduğundan göreli adresleme tercih edilir:
-- Send "punch" from the "hero" script to "enemy" script
msg.post("enemy#controller", "punch")
Oyunda yalnızca tek bir güç düzeyine sahip yumruk hareketi bulunduğundan, iletinin adı olan “punch” dışında herhangi bir bilgi içermesi gerekmez.
Düşmanın betik bileşeninde, iletiyi almak için bir işlev oluşturursunuz:
function on_message(self, message_id, message, sender)
if message_id == hash("punch") then
self.health = self.health - 100
end
end
Bu durumda kod yalnızca iletinin adına bakar (ad, message_id parametresinde karma değeri alınmış bir dize olarak gönderilir). Kod, ileti verisiyle veya gönderenle ilgilenmez—“punch” iletisini gönderen herkes zavallı düşmana hasar verir.
"update_score" iletisi gönderilir.
-- Enemy defeated. Increase score counter by 100.
self.score = self.score + 100
msg.post("/interface#gui", "update_score", { score = self.score })
Bu durumda göreli bir adres yazmak mümkün değildir; çünkü “interface” adlandırma hiyerarşisinin kökündeyken “hero” kökte değildir. İleti, kendisine bir betik eklenmiş olan GUI bileşenine gönderilir; böylece bileşen iletiye uygun şekilde tepki verebilir. Betikler, GUI betikleri ve işleme betikleri (render script) arasında serbestçe ileti gönderilebilir.
"update_score" iletisi, puan verisiyle birlikte gönderilir. Veri, message parametresinde bir Lua tablosu olarak aktarılır:
function on_message(self, message_id, message, sender)
if message_id == hash("update_score") then
-- set the score counter to new score
local score_node = gui.get_node("score")
gui.set_text(score_node, "SCORE: " .. message.score)
end
end
"update_minimap" iletisi göndererek kendi konumunu bildirmekten sorumludur:
-- Send the current position to update the interface minimap
local pos = go.get_position()
msg.post("/interface#gui", "update_minimap", { position = pos })
GUI betiğinin kodu her düşmanın konumunu izlemelidir; aynı düşman yeni bir konum gönderirse eski konum değiştirilmelidir. İletiyi gönderen (sender parametresinde aktarılır), konumları içeren bir Lua tablosunda anahtar olarak kullanılabilir:
function init(self)
self.minimap_positions = {}
end
local function update_minimap(self)
for url, pos in pairs(self.minimap_positions) do
-- update position on map
...
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("update_score") then
-- set the score counter to new score
local score_node = gui.get_node("score")
gui.set_text(score_node, "SCORE: " .. message.score)
elseif message_id == hash("update_minimap") then
-- update the minimap with new positions
self.minimap_positions[sender] = message.position
update_minimap(self)
end
end
Yukarıda gördüğümüz gibi, ileti gönderme mekanizması oldukça basittir. İletinizi ileti kuyruğuna ekleyen msg.post() işlevini çağırırsınız. Ardından motor, her karede kuyruğu tarar ve her iletiyi hedef adresine teslim eder. Bazı sistem iletilerini ("enable", "disable", "set_parent" vb.) motor kodu işler. Motor ayrıca nesnelerinize teslim edilen bazı sistem iletileri de üretir (fizik çarpışmalarında "collision_response" gibi). Betik bileşenlerine gönderilen kullanıcı tanımlı iletiler için motor yalnızca on_message() adlı özel bir Defold Lua işlevini çağırır.
Var olan herhangi bir nesneye veya bileşene istediğiniz iletileri gönderebilirsiniz; iletiye yanıt vermek alıcı taraftaki koda bağlıdır. Bir betik bileşenine ileti gönderirseniz ve betik kodu iletiyi yok sayarsa bu bir sorun oluşturmaz. İletileri işleme sorumluluğu tamamen alıcı taraftadır.
Motor, iletinin hedef adresini kontrol eder. Bilinmeyen bir alıcıya ileti göndermeye çalışırsanız Defold konsolda bir hata bildirir:
-- Try to post to a non existing object
msg.post("dont_exist#script", "hello")
ERROR:GAMEOBJECT: Instance '/dont_exists' could not be found when dispatching message 'hello' sent from main:/my_object#script
msg.post() çağrısının tam imzası şöyledir:
msg.post(receiver, message_id, [message])
-- Send table data containing a nested table
local inventory_table = { sword = true, shield = true, bow = true, arrows = 9 }
local stats = { score = 100, stars = 2, health = 4, inventory = inventory_table }
msg.post("other_object#script", "set_stats", stats)
message parametresindeki tablonun boyutu için kesin bir sınır vardır. Bu sınır 2 kilobayt olarak belirlenmiştir. Bir tablonun bellekte kapladığı tam boyutu belirlemenin şu anda basit bir yolu yoktur; ancak bellek kullanımını izlemek için tabloyu eklemeden önce ve sonra collectgarbage("count") kullanabilirsiniz.
Defold, tam bir URL belirtmeden ileti göndermek için kullanabileceğiniz iki kullanışlı kısa gösterim sunar:
.#Örneğin:
-- Let this game object acquire input focus
msg.post(".", "acquire_input_focus")
-- Post "reset" to the current script
msg.post("#", "reset")
İleti almak için hedef betik bileşeninin on_message() adlı bir işlev içerdiğinden emin olmanız yeterlidir. İşlev dört parametre kabul eder:
function on_message(self, message_id, message, sender)
selfmessage_idmessagesenderfunction on_message(self, message_id, message, sender)
print(message_id) --> hash: [my_message_name]
pprint(message) --> {
--> score = 100,
--> value = "some string"
--> }
print(sender) --> url: [main:/my_object#script]
end
Çalışma zamanı ortamına yeni bir oyun dünyası yüklemek için koleksiyon vekili (collection proxy) bileşeni kullanıyorsanız oyun dünyaları arasında ileti aktarmak isteyeceksiniz. Bir koleksiyonu vekil aracılığıyla yüklediğinizi ve koleksiyonun Name özelliğinin “level” olarak ayarlandığını varsayalım:

Koleksiyon yüklenip başlangıç işlemleri tamamlandıktan ve etkinleştirildikten hemen sonra, alıcı adresinin “socket” alanında oyun dünyasının adını belirterek yeni dünyadaki herhangi bir bileşene veya nesneye ileti gönderebilirsiniz:
-- Send a message to the player in the new game world
msg.post("level:/player#controller", "wake_up")
Vekillerin nasıl çalıştığına ilişkin daha ayrıntılı bir açıklamayı Koleksiyon vekilleri belgesinde bulabilirsiniz.
Gönderilmiş bir ileti sonunda dağıtıldığında alıcıların on_message() işlevi çağrılır. Tepki veren kodun, ileti kuyruğuna eklenen yeni iletiler göndermesi oldukça yaygındır.
Motor dağıtıma başladığında ileti kuyruğunu işler, her iletinin alıcısının on_message() işlevini çağırır ve ileti kuyruğu boşalana kadar devam eder. Dağıtım turu sırasında kuyruğa yeni iletiler eklenirse bir tur daha gerçekleştirir. Ancak motorun kuyruğu boşaltmayı kaç kez deneyeceğine ilişkin kesin bir sınır vardır; bu da bir kare içinde tamamen dağıtılmasını bekleyebileceğiniz ileti zincirlerinin uzunluğunu sınırlar. Motorun her update() çağrısı arasında kaç ileti dağıtım turu gerçekleştirdiğini aşağıdaki betikle kolayca test edebilirsiniz:
function init(self)
-- We’re starting a long message chain during object init
-- and keeps it running through a number of update() steps.
print("INIT")
msg.post("#", "msg")
self.updates = 0
self.count = 0
end
function update(self, dt)
if self.updates < 5 then
self.updates = self.updates + 1
print("UPDATE " .. self.updates)
print(self.count .. " dispatch passes before this update.")
self.count = 0
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("msg") then
self.count = self.count + 1
msg.post("#", "msg")
end
end
Bu betiği çalıştırmak aşağıdakine benzer bir çıktı verir:
DEBUG:SCRIPT: INIT
INFO:ENGINE: Defold Engine 1.2.36 (5b5af21)
DEBUG:SCRIPT: UPDATE 1
DEBUG:SCRIPT: 10 dispatch passes before this update.
DEBUG:SCRIPT: UPDATE 2
DEBUG:SCRIPT: 75 dispatch passes before this update.
DEBUG:SCRIPT: UPDATE 3
DEBUG:SCRIPT: 75 dispatch passes before this update.
DEBUG:SCRIPT: UPDATE 4
DEBUG:SCRIPT: 75 dispatch passes before this update.
DEBUG:SCRIPT: UPDATE 5
DEBUG:SCRIPT: 75 dispatch passes before this update.
Defold motorunun bu belirli sürümünün, init() ile ilk update() çağrısı arasında ileti kuyruğunda 10 ileti dağıtım turu gerçekleştirdiğini görüyoruz. Ardından sonraki her güncelleme döngüsünde 75 tur gerçekleştirir.