I’m doing the War battle tutorial, running through the extras, and I have a function called move(self, dt) that updates the location of the tanks.
I also have the same function for the rocket, and the same function for the player.
Everything seems to be fine, until I launch the rocket, when the rocket seems to call the tanks move() and I don’t really understand why.
If I rename the rockets move to rocket_move() then it all works perfectly. It feels like some kind of function naming collision, but I don’t really understand why.
go.property("direction", vmath.vector3())
function init(self)
self.speed = 300
self.life = 1
end
function update(self, dt)
self.life = self.life - dt
if self.life < 0 then
explode(self)
else
move(self, dt)
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("animation_done") then
go.delete()
elseif message_id == hash("collision_response") then
explode(self)
go.delete(message.other_id)
msg.post("/gui#ui", "add_score", {score = 100})
end
end
function explode(self)
-- Give ourselves some time to complete the animation
self.life = 10000
-- Reset rotation otherwise the explosion will be rotated
go.set_rotation(vmath.quat())
-- Stop moving
self.speed = 0
-- Play explosion
msg.post("#sprite", "play_animation", {id = hash("explosion")})
end
function move(self, dt)
local pos = go.get_position()
pos = pos + self.direction * self.speed * dt
go.set_position(pos)
end
My tank script in tank.script:
local defs = require "modules/defines"
go.property("parent", msg.url())
go.property("dead_zone", 5)
function init(self)
self.target = nil
self.speed = 50
end
function final(self)
msg.post(self.parent, "tank_dead", { id = go.get_id() })
end
function update(self, dt)
if self.target == nil then
new_target(self)
else
-- move towards the target at some speed
move(self, dt)
-- If we're close enough, we've arrived, drop the target
check_arrived(self)
end
end
function on_message(self, message_id, message, sender)
-- Add message-handling code here
-- Remove this function if not needed
end
function on_input(self, action_id, action)
-- Add input-handling code here
-- Remove this function if not needed
end
function on_reload(self)
-- Add reload-handling code here
-- Remove this function if not needed
end
function new_target(self)
print(go.get_id() .. " has no target, finding new target")
-- If we don't have a target, pick a random location and move towards it
-- TODO: Find a way to get a random location within the level bounds
x, y, w, h = tilemap.get_bounds("/map#map")
local xt = math.random(w * defs.tile_size)
local yt = math.random(h * defs.tile_size)
self.target = vmath.vector3(xt, yt, 1)
end
function move(self, dt)
if self.target == nil then
print("WTF " .. go.get_id())
else
print("we have target")
local p = go.get_position()
local dir = vmath.normalize(self.target - p)
p = p + (dir * self.speed * dt)
go.set_position(p)
end
end
function check_arrived(self)
local sqr_dist = vmath.length_sqr(self.target - go.get_position())
local sqr_zone = self.dead_zone * self.dead_zone
if sqr_zone > sqr_dist then
print(go.get_id() .. " arrived at target")
self.target = nil
end
end
If you don’t write local then they will be global functions that any script can call.
Note that once you make them local you have to define them before (above) where you call them, or forward declare them. See: Locals, globals and lexical scoping
If you create a function in one script without prefixing it with local it will be be defined globally (this goes for regular variables as well).
You are overwriting the same global function multiple times from different scripts. (I agree it might be a bit unexpected since the script specific init/update/etc functions are not overwritten.)
Instead you should do something like this:
-- rocket.script
local function move()
-- do rocket movement
end
-- rocket.script
local function move()
-- do player movement
end
Then you would be able to use the different move functions separately in each script.
“There are naive questions, tedious questions, ill-phrased questions, questions put after inadequate self-criticism. But every question is a cry to understand the world. There is no such thing as a dumb question”
Agreed, it is a bit unexpected since any other functions land in global space… I don’t have any better answer than that those are special instance specific functions that the engine will “remember” and call for that specific component/instance.
It depends. If you have a lot of images for the tank it might need a separate atlas (like if it’s 4096x4096), but if both are small you can put the images in the same atlas, that have some performance benefits because the renderer can reduce the number of draw calls.