War battles tutorial - Rocket launch direction is strange (SOLVED)

https://www.defold.com/tutorials/war-battles/

Hello.

I’m following this tutorial(War battles tutorial) in editor 2(1.2.107), and the rocket launch direction is strange. The other direction works normally. However, the “down + left” fires to the left and the “down + right” fires to the right.

-- player.script
function init(self)
    msg.post("#", "acquire_input_focus")

    self.moving = false
    self.firing = false

    self.input = vmath.vector3()
    self.dir = vmath.vector3(0, 1, 0)
    self.speed = 50
end

function final(self)
    msg.post("#", "release_input_focus")
end

function update(self, dt)
    if self.moving then
        local pos = go.get_position()
        pos = pos + self.dir * self.speed * dt
        go.set_position(pos)
    end

    if self.firing then
        factory.create("#rocketfactory")
    end

    self.input.x = 0
    self.input.y = 0

    self.moving = false
    self.firing = false
end

function on_input(self, action_id, action)
    if action_id == hash("up") then
        self.input.y = 1
    elseif action_id == hash("down") then
        self.input.y = -1
    elseif action_id == hash("left") then
        self.input.x = -1
    elseif action_id == hash("right") then
        self.input.x = 1
    elseif action_id == hash("fire") and action.pressed then
        local angle = math.atan2(self.dir.y, self.dir.x)
        local rot = vmath.quat_rotation_z(angle)
        local props = { dir = self.dir }
        factory.create("#rocketfactory", nil, rot, props )
    end


    if vmath.length(self.input) > 0 then
        self.moving = true
        self.dir = vmath.normalize(self.input)
    end
end

-- rocket.script
go.property("dir", vmath.vector3())

function init(self)
    self.speed = 200
    self.life = 1
end

function update(self, dt)
    local pos = go.get_position()
    pos = pos + self.dir * self.speed * dt
    go.set_position(pos)

    self.life = self.life - dt
    if self.life < 0 then
        self.life = 1000
        go.set_rotation(vmath.quat())
        self.speed = 0
        msg.post("#sprite", "play_animation", { id = hash("explosion") })
    end
end

function on_message(self, message_id, message, sender)
    if message_id == hash("animation_done") then
        go.delete()
    end
end

2 Likes

I havent personally tested that tutorial but if I’m not mistaken there could be a problem with having the “fire” code in the on_input function.
As self.input is reseted every update you are setting new value to it every frame but you cannot really be sure that all “up”, “down” “left” and “right” has actually arrived before an eventual “fire” arrives.
If “fire” arrives before say “down”, it will create the rocket with the self.dir that is currently it and I believe the vmath vector3 is actually copied when being send to the factory, so any changes on self.dir after the factory.create will not impact the props.

Thats probably why you have a self.firing and should move all the creation of the rocket to the update function. In on_input you should when “fire” happens only set self.firing = true.

update(self,dt) will be run after all on_input has been handled

4 Likes

Thank you andreas. I modified the code to fix the problem.

-- player.script
function init(self)
    msg.post("#", "acquire_input_focus")

    self.moving = false
    self.firing = false

    self.input = vmath.vector3()
    self.dir = vmath.vector3(0, 1, 0)
    self.speed = 50
end

function final(self)
    msg.post("#", "release_input_focus")
end

function update(self, dt)
    if self.moving then
        local pos = go.get_position()
        pos = pos + self.dir * self.speed * dt
        go.set_position(pos)
    end

    if self.firing then -- 2.
        local angle = math.atan2(self.dir.y, self.dir.x)
        local rot = vmath.quat_rotation_z(angle)
        local props = { dir = self.dir }
        factory.create("#rocketfactory", nil, rot, props )
    end

    self.input.x = 0
    self.input.y = 0

    self.moving = false
    self.firing = false
end

function on_input(self, action_id, action)
    if action_id == hash("up") then
        self.input.y = 1
    elseif action_id == hash("down") then
        self.input.y = -1
    elseif action_id == hash("left") then
        self.input.x = -1
    elseif action_id == hash("right") then
        self.input.x = 1
    elseif action_id == hash("fire") and action.pressed then
        self.firing = true  -- 1.
    end

    if vmath.length(self.input) > 0 then
        self.moving = true
        self.dir = vmath.normalize(self.input)
    end
end

7 Likes

This tutorial is not 30 minutes old so wonderful that you put it to the test!! :slight_smile:

You have found an error. I’m fixing it now. Thanks!

7 Likes