ERROR:SCRIPT: level/platform.script:24: attempt to perform arithmetic on field ‘coins’ (a nil value)
stack traceback:
level/platform.script:24: in function 'create_coins’
level/platform.script:37: in function <level/platform.script:33>
the script i have in platform.script:
21 function create_coins(self, params)
22 local spacing = 56
23 local pos = go.get_position()
24 local x = pos.x - params.coins * (spacing*0.5) - 24
25 for i = 1, params.coins do
26 local coin = factory.create("#coin_factory", vmath.vector3(x + i * spacing , pos.y + 64, 1))
27 msg.post(coin, "set_parent", { parent_id = go.get_id() })
28 msg.post(coin, "start_animation", { delay = i/10 })
29 table.insert(self.coins, coin)
30 end
31 end
32
33 function on_message(self, message_id, message, sender)
34 if message_id == hash("set_speed") then
35 self.speed = message.speed
36 elseif message_id == hash("create_coins") then
37 create_coins(self, message)
38 end
39 end
It seems that your message table doesn’t contain field coins. In this case params.coins will evaluate to nil on 24 line and you can’t use it for arithmetic, as said in error message.
Exactly. And the last part of the tutorial involves a change to the controller.script where you are supposed to post the create_coins message:
msg.post(p, "create_coins", { coins = coins })
So either coins is nil there or there’s a problem when you receive the message in platform.script and pass it to the create_coins() function. My recommendation is to add:
pprint(message)
In the on_message() function in platform.script. Does the create_coins message contain a coins
key-value pair? And do you pass the message along to the create_coins() function?
i seem to have followed the tutorial step by step but its still not working…can someone check and see whats wrong with my code…ill paste it here…thanks heaps
Controller.script:
go.property("speed", 6)
local grid = 460
local platform_heights = { 100, 200, 350 }
local coins = coins
if math.random() > 0.5 then
f = "#platform_long_factory"
coins = coins * 2 -- Twice the number of coins on long platforms
end
function init(self)
msg.post("ground/controller#script", "set_speed", { speed = self.speed })
self.gridw = 0
self.spawns = {}
end
function update(self, dt)
self.gridw = self.gridw + self.speed
if self.gridw >= grid then
self.gridw = 0
-- Maybe spawn a platform at random height
if math.random() > 0.2 then
local h = platform_heights[math.random(#platform_heights)]
local f = "#platform_factory"
if math.random() > 0.5 then
f = "#platform_long_factory"
end
local p = factory.create(f, vmath.vector3(1600, h, 0), nil, {}, 0.6)
msg.post(p, "set_speed", { speed = self.speed })
msg.post(p, "create_coins", { coins = coins })
table.insert(self.spawns, p)
end
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("reset") then
-- Tell the hero to reset.
msg.post("hero#script", "reset")
-- Delete all platforms
for i,p in ipairs(self.spawns) do
go.delete(p)
end
self.spawns = {}
elseif message_id == hash("delete_spawn") then
for i,p in ipairs(self.spawns) do
if p == message.id then
table.remove(self.spawns, i)
go.delete(p)
end
end
end
end
Platform.script:
function init(self)
self.speed = 9 -- Default speed
self.coins = {}
end
function final(self)
for i,p in ipairs(self.coins) do
go.delete(p)
end
end
function update(self, dt)
local pos = go.get_position()
if pos.x < -500 then
msg.post("/level/controller#script", "delete_spawn", { id = go.get_id() })
end
pos.x = pos.x - self.speed
go.set_position(pos)
end
function create_coins(self, params)
local spacing = 56
local pos = go.get_position()
local x = pos.x - params.coins * (spacing*0.5) - 24
for i = 1, params.coins do
local coin = factory.create("#coin_factory", vmath.vector3(x + i * spacing , pos.y + 64, 1))
msg.post(coin, "set_parent", { parent_id = go.get_id() })
msg.post(coin, "start_animation", { delay = i/10 })
table.insert(self.coins, coin)
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("set_speed") then
self.speed = message.speed
elseif message_id == hash("create_coins") then
create_coins(self, message)
end
end
Hmm, I believe there’s a typo in the tutorial. Could you try changing this line back:
-- controller.script
local coins = 3
Otherwise you’ll simply store a nil
value into that variable, and continue to send that along.
Also, when debugging, since you know where from the message is passed, and what it should contain, you can print out the value
Ah, yes, I remember someone else coming across the same thing… @sicher, update needed!
i managed to get 3 coins on platform, but also only 3 coins on platform_long
You have to add some code where random selection of platform type is done
if math.random() > 0.5 then
f = "#platform_long_factory"
coins = coins * 2
end
i already have that, but its still not spawning coinsx2 for platform_long
go.property("speed", 6)
local grid = 460
local platform_heights = { 100, 200, 350 }
local coins = 3
if math.random() > 0.5 then
f = "#platform_long_factory"
coins = coins * 2
end
No, the problem is not local coins = coins
. You have added code in the wrong place, particularly the top of the file is wrongly placed:
local grid = 460
local platform_heights = { 100, 200, 350 }
local coins = coins
if math.random() > 0.5 then
f = "#platform_long_factory"
coins = coins * 2 -- Twice the number of coins on long platforms
end
Here is what controller.lua should look like after the last step. I have added annotations for the last 3 edits; (1) (2) and (3) below:
go.property("speed", 6)
local grid = 460
local platform_heights = { 100, 200, 350 }
local coins = 3 -- (1) A local containing the base number of coins
function init(self)
msg.post("ground/controller#script", "set_speed", { speed = self.speed })
self.gridw = 0
self.spawns = {}
end
function update(self, dt)
self.gridw = self.gridw + self.speed
if self.gridw >= grid then
self.gridw = 0
-- Maybe spawn a platform at random height
if math.random() > 0.2 then
local h = platform_heights[math.random(#platform_heights)]
local f = "#platform_factory"
local coins = coins -- (2) Make a new local var defaulting to the base number of coins defined at (1)
if math.random() > 0.5 then
f = "#platform_long_factory"
coins = coins * 2 -- (2) Twice the number of coins on long platforms
end
if math.random() > 0.5 then
f = "#platform_long_factory"
end
local p = factory.create(f, vmath.vector3(1600, h, 0), nil, {}, 0.6)
msg.post(p, "set_speed", { speed = self.speed })
msg.post(p, "create_coins", { coins = coins }) -- (3) Send message to platform to create coins.
table.insert(self.spawns, p)
end
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("reset") then
-- Tell the hero to reset.
msg.post("hero#script", "reset")
-- Delete all platforms
for i,p in ipairs(self.spawns) do
go.delete(p)
end
self.spawns = {}
elseif message_id == hash("delete_spawn") then
for i,p in ipairs(self.spawns) do
if p == message.id then
table.remove(self.spawns, i)
go.delete(p)
end
end
end
end
You can download or browse working code from our “defold-examples” github. Here’s the runner project: https://github.com/defold/defold-examples/tree/master/runner
that fixed it…thanks for that