I’m attempting to use Lua’s closures in the following bit of code:
[lua]
for k,v in pairs(tiles) do
for key, value in pairs(v) do
position.xPos = value[1]
position.yPos = value[2]
if self.inventoryData[itemId].Type == “Seed” then
item = SeedClass.new(itemData, self._game, position) –
self.items[item.id] = item
TaskManager:addTask({id=item.id, desc="Plant “…item.name, duration=15000, repeated=false,
callback = function()
print(”* x: “…item.mainImage.x) --always referring to last item created in the for loop
print(”* Y: "…item.mainImage.y) --always referring to last item created in the for loop
return item:action({x=item.mainImage.x, y=item.mainImage.y}) --always referring to last item created in the for loop
end})
end
end
end
[/lua]
Many thanks…
The idea being that a task is added to create the object, once the task’s duration has passed the object is displayed on screen in the item:action() call via a call to the task.callback() method.
Although this code works fine it comes across a problem when I’m trying to spawn multiple objects; the callback function only refers to the last item created up above - so the call to item:action is always being made on the last created item object. I’m pretty sure there’s a way to do this via the corretc use of closures, but can’t seem to get it right yet…
Any
OK… so no sooner do I post then I find a solution…
[lua]
item = SeedClass.new(itemData, self._game, position) –
self.items[item.id] = item
local function createTask(item)
return TaskManager:addTask({id=item.id, desc="Plant “…item.name, duration=15000, repeated=false,
callback = function()
print(”* x: “…item.mainImage.x)
print(”* Y: "…item.mainImage.y)
item:action({x=item.mainImage.x, y=item.mainImage.y})
end})
end
createTask(item)
[/lua]
I’ve changed the code to this, it gets around the problem of ensuring the correct instance data is passed - however it’s far from an elegant solution, so be interested to know whether anybody has any better alternatives.
Many thanks…
You did not post where you call the callback function and where is the callback variable declared it looks like it’s global thus will change for ever new instance.
Hi Primoz…
The callback function is called in the TaskManager class. Essentially there is a method in that class that calls the callback when the task duration is finished:
[lua]
function TaskManager:isTaskReady(id)
if self.mTasks[id].taskDuration <= 0 then
self.mTasks[id].callback()
if self.mTasks[id].repeated == false then
self:removeTask(id)
end
return true
end
end
[/lua]
The callback variable is part of a table that is passed through in the code above to TaskManager:addTask(), as so:
[lua]
TaskManager:addTask({id=item.id, desc="Plant "…item.name, duration=15000, repeated=false,
callback = function()
print("* x: “…item.mainImage.x) --always referring to last item created in the for loop
print(”* Y: "…item.mainImage.y) --always referring to last item created in the for loop
return item:action({x=item.mainImage.x, y=item.mainImage.y}) --always referring to last item created in the for loop
end})
[/lua]
The technique in my second post works, I just thought there might be a more elegant solution then encapsulating the call within a function.
Thanks for checking over it for me…
Ah sorry I missed that it was a parameter.
What I like to do in a case like this is to add just the reference to the function that needs to be called and a table of parameters that it needs like so:
params = { 1, “something” }
task = {call = func1, params = params }
TaskManager.addTask(task)
and when task manager calls it just do this:
task.call(unpack(task.params))
OK… so no sooner do I post then I find a solution…
[lua]
item = SeedClass.new(itemData, self._game, position) –
self.items[item.id] = item
local function createTask(item)
return TaskManager:addTask({id=item.id, desc="Plant “…item.name, duration=15000, repeated=false,
callback = function()
print(”* x: “…item.mainImage.x)
print(”* Y: "…item.mainImage.y)
item:action({x=item.mainImage.x, y=item.mainImage.y})
end})
end
createTask(item)
[/lua]
I’ve changed the code to this, it gets around the problem of ensuring the correct instance data is passed - however it’s far from an elegant solution, so be interested to know whether anybody has any better alternatives.
Many thanks…
You did not post where you call the callback function and where is the callback variable declared it looks like it’s global thus will change for ever new instance.
Hi Primoz…
The callback function is called in the TaskManager class. Essentially there is a method in that class that calls the callback when the task duration is finished:
[lua]
function TaskManager:isTaskReady(id)
if self.mTasks[id].taskDuration <= 0 then
self.mTasks[id].callback()
if self.mTasks[id].repeated == false then
self:removeTask(id)
end
return true
end
end
[/lua]
The callback variable is part of a table that is passed through in the code above to TaskManager:addTask(), as so:
[lua]
TaskManager:addTask({id=item.id, desc="Plant "…item.name, duration=15000, repeated=false,
callback = function()
print("* x: “…item.mainImage.x) --always referring to last item created in the for loop
print(”* Y: "…item.mainImage.y) --always referring to last item created in the for loop
return item:action({x=item.mainImage.x, y=item.mainImage.y}) --always referring to last item created in the for loop
end})
[/lua]
The technique in my second post works, I just thought there might be a more elegant solution then encapsulating the call within a function.
Thanks for checking over it for me…
Ah sorry I missed that it was a parameter.
What I like to do in a case like this is to add just the reference to the function that needs to be called and a table of parameters that it needs like so:
params = { 1, “something” }
task = {call = func1, params = params }
TaskManager.addTask(task)
and when task manager calls it just do this:
task.call(unpack(task.params))