Function scoping issue possibly ?

HI,

I have been working a set of turrets that fire a bullet at a moving player.

All is fine when I create one instance.

But what I wanted to do is create several instances of the turrets.

I created them in a for loop, added a timer to each obj.e.g. turret.timer = timerPreformWithDelay(blah, blah).

I also added the bullets and timers to their own table.

Now my problem is this, I call the timer to begin when the player collides with a sensor then when it exits remove the timer.

In the collision function I call a function on the began and ended phase.

The function does trigger but it only enables a single turret to fire.

If I remove the call to the bullet function and place the timer in the main chunk it works fine(albeit not with the sensor)

So my question is why and how can I fix it ?

I am going to post the module that works without the use of putting the timer in a function and the second which does not work with the timer in a function.

I am sure the main issue is function scope and the timer call but I really lost on this one.

ANy help greatly appreciated, apologies for posting without formatting the lua tags dont seem to be working again

local bullets = {}
local turrets = {}
local spawnBulletTimers = {}
local turretSensors = {}

local function createTurrets(layer)

    local layer = layer or display.currentStage

    local xPos = { 250, 250 }
    local yPos = { 30, 270 }

    for i = 1, 2 do

        local turret = display.newRect(layer, 0, 0, 10, 20)
        turret.x = xPos[i]
        turret.y = yPos[i]
        turret.name = “turret”

        physics.addBody(turret, “static”, { isSensor = true})
        turret:addEventListener(“collision”, turret)

        function turret:collision(event)

            local phase = event.phase
            local target = event.target
            local other = event.other
            if phase == “began” then
                if target.name == “turret” and other.name == “player” then
                end
            end
        end
        turrets[turret] = turret

        local turretSensor = display.newRect(layer, 0, 0, 200, 100) – set turret sensor size
        turretSensor.x = turret.x
        turretSensor.y = turret.y
        turretSensor.name = “turretSensor”
        turretSensor.isVisible = false
        physics.addBody(turretSensor, “static”, { isSensor = true })
        turretSensor:addEventListener(“collision”, turretSensor)
        turretSensors[turretSensor] = turretSensor

        function turretSensor:collision(event)

            local phase = event.phase
            local target = event.target
            local other = event.other

            if phase == “began” then
                if target.name == “turretSensor” and other.name == “player” then

                    enableTurret()
                end
            end
            if phase == “ended” then
                if target.name == “turretSensor” and other.name == “player” then

                    disableTurret()
                end
            end
        end

         function updateBullet()

            if turrets[turret] then

                local bullet = display.newRect(layer, 0, 0, 5, 5)
                bullet.x = turrets[turret].x
                bullet.y = turrets[turret].y
                bullet.name = “turretBullet”
                physics.addBody(bullet, { isSensor = true, filter = filtersModule.pickupFilter })
                bullet:addEventListener(“collision”, bullet)

                local vx, vy = vecSub(player, turrets[turret])
                local len = vecLen(vx, vy)
                local nx, ny = vecNorm(vx, vy)
                speed = 1000
                local speed = 10000
                local bx, by = vecScale(nx, ny, speed)
                bullet:setLinearVelocity(vx, vy)

                function bullet:collision(event)
                    local phase = event.phase
                    local target = event.target
                    local other = event.other

                    if phase == “began” then

                        if target.name == “turretBullet” and other.name == “player”
                                or target.name == “turretBullet” and other.name == “lazer”
                                or target.name == “turretBullet” and other.name == “RectRight”
                                --or target.name == “turretBullet” and other.name == “RectLeft”
                                or target.name == “turretBullet” and other.name == “Rect”
                        then

                            display.remove(target)
                            target = nil
                        end
                    end
                end
                bullets[bullet] = bullet
            end
         end

        function enableTurret()
            turret.spawnBulletTimer = timer.performWithDelay(500, updateBullet, -1)
            spawnBulletTimers[turret.spawnBulletTimer] = turret.spawnBulletTimer
        end

        function disableTurret()
           – how to cancel the timer here?
        end

    end
end

--------------------------------------------- working with timer in main chunk, no sensors ----------------------------

local bullets = {}
local turrets = {}
local spawnBulletTimers = {}
local turretSensors = {}

local function createTurrets(layer)

    local layer = layer or display.currentStage

    local xPos = { 250, 250 }
    local yPos = { 30, 270 }

    for i = 1, 2 do

        local turret = display.newRect(layer, 0, 0, 10, 20)
        turret.x = xPos[i]
        turret.y = yPos[i]
        turret.name = “turret”

        physics.addBody(turret, “static”, { isSensor = true})
        turret:addEventListener(“collision”, turret)

        function turret:collision(event)

            local phase = event.phase
            local target = event.target
            local other = event.other
            if phase == “began” then
                if target.name == “turret” and other.name == “player” then
                end
            end
        end
        turrets[turret] = turret

        local turretSensor = display.newRect(layer, 0, 0, 200, 100) – set turret sensor size
        turretSensor.x = turret.x
        turretSensor.y = turret.y
        turretSensor.name = “turretSensor”
        turretSensor.isVisible = false
        physics.addBody(turretSensor, “static”, { isSensor = true })
        turretSensor:addEventListener(“collision”, turretSensor)
        turretSensors[turretSensor] = turretSensor

        function turretSensor:collision(event)

            local phase = event.phase
            local target = event.target
            local other = event.other

            if phase == “began” then
                if target.name == “turretSensor” and other.name == “player” then

                    --enable bullet timer–
                end
            end
            if phase == “ended” then
                if target.name == “turretSensor” and other.name == “player” then

                     --disable bullet timer –
                end
            end
        end

         function updateBullet()

            if turrets[turret] then

                local bullet = display.newRect(layer, 0, 0, 5, 5)
                bullet.x = turrets[turret].x
                bullet.y = turrets[turret].y
                bullet.name = “turretBullet”
                physics.addBody(bullet, { isSensor = true, filter = filtersModule.pickupFilter })
                bullet:addEventListener(“collision”, bullet)

                local vx, vy = vecSub(player, turrets[turret])
                local len = vecLen(vx, vy)
                local nx, ny = vecNorm(vx, vy)
                speed = 1000
                local speed = 10000
                local bx, by = vecScale(nx, ny, speed)
                bullet:setLinearVelocity(vx, vy)

                function bullet:collision(event)
                    local phase = event.phase
                    local target = event.target
                    local other = event.other

                    if phase == “began” then

                        if target.name == “turretBullet” and other.name == “player”
                                or target.name == “turretBullet” and other.name == “lazer”
                                or target.name == “turretBullet” and other.name == “RectRight”
                                --or target.name == “turretBullet” and other.name == “RectLeft”
                                or target.name == “turretBullet” and other.name == “Rect”
                        then

                            display.remove(target)
                            target = nil
                        end
                    end
                end
                bullets[bullet] = bullet
            end
         end

            turret.spawnBulletTimer = timer.performWithDelay(500, updateBullet, -1)
            spawnBulletTimers[turret.spawnBulletTimer] = turret.spawnBulletTimer

    end
end

Hi @bubblebobble,

Without going into detail on your code at this point, I would suggest that you “attach” the various timers to the actual sensor objects, so they’re easy to manage (cancel, pause, etc.). Meaning, add them as a property of the actual sensor object (which is a Lua table), and when something collides with it, you can easily tell that timer to start, and when the player exits the sensor field, you stop the timer.

Best regards,

Brent

Hi @bubblebobble,

Without going into detail on your code at this point, I would suggest that you “attach” the various timers to the actual sensor objects, so they’re easy to manage (cancel, pause, etc.). Meaning, add them as a property of the actual sensor object (which is a Lua table), and when something collides with it, you can easily tell that timer to start, and when the player exits the sensor field, you stop the timer.

Best regards,

Brent