Deleting an Object from a Table

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Itswolfcity811
Prole
Posts: 7
Joined: Tue Jun 27, 2023 12:38 am

Deleting an Object from a Table

Post by Itswolfcity811 »

I'm making a game and I'm trying to make a bullet script and I have it delete it's self after it fly's a specific distance.
Before I made it destroy its self it worked fine. After I added it it would work fine until the first bullet destroys its self. When that happens it destroys its self and all the other bullets except the second one and won't let me shoot more. Have tried many things but can't find the error. Can someone help me?

Here is the code to spawn in the bullet:

Code: Select all

function love.mousepressed(x, y, button, istouch, presses)
    if CheckGameState("Running") then
        if button == 1 then
            game.State.Running.Bullets[#game.State.Running.Bullets + 1] = bullet(5, 1, game.Weapons.Type.Pistol, "Sprites/Ammo/PistolAmmo.png", 200, 100, (#game.State.Running.Bullets + 1))
            
            -- table.insert(game.State.Running.Bullets, (#game.State.Running.Bullets + 1), bullet(5, 1, game.Weapons.Type.Pistol, "Sprites/Ammo/PistolAmmo.png", 200, 100, (#game.State.Running.Bullets + 1)))
        end
--Rest of function
Here is the code for destroying the enemies (In the love.update(dt) functon):

Code: Select all

for i in pairs(game.State.Running.Bullets) do
            game.State.Running.Bullets[i]:Move(dt)

            if game.State.Running.Bullets[i]:CheckTouched() == true then
                table.remove(game.State.Running.Bullets, game.State.Running.Bullets[i].place, game.State.Running.Bullets[i])
            end
        end
And here is the code for the bullets:

Code: Select all

local love = _G.love

function Bullet(dmg, id, Weapon, ImagePath, speed, distance, place)
    local Image = love.graphics.newImage(ImagePath)

    local MouseX, MouseY = love.mouse.getPosition()
    
    local angle = math.atan2(MouseY - Weapon.Player.y, MouseX - Weapon.Player.x)

    return {
        dmg = dmg,
        id = id,
        Weapon = Weapon,
        Image = Image,
        x = nil,
        y = nil,
        angle = angle,
        speed = speed,
        distance = distance,
        place = place,

        Draw = function(self)
            if id == Weapon.Player.WeaponId then

                local MouseX, MouseY = love.mouse.getPosition()
                                
                if self.x == nil and self.y == nil then
                    -- local x = (self.Weapon.Player.x + math.cos(self.angle) * self.Weapon.Distance)
                    local x = nil
                    local y = nil
                    
                    if math.deg(angle) <= 180 and math.deg(angle) >= 0 and false then
                        x = (self.Weapon.Player.x + math.cos(self.angle) * self.Weapon.Distance) + 5
                        y = (self.Weapon.Player.y + math.sin(self.angle) * self.Weapon.Distance)
                    elseif math.deg(angle) <= 45 and math.deg(angle) >= -90 and false then
                        y = (self.Weapon.Player.y + math.sin(self.angle) * self.Weapon.Distance)
                        x = (self.Weapon.Player.x + math.cos(self.angle) * self.Weapon.Distance) - 5
                    elseif math.deg(angle) <= 90 and math.deg(angle) >= -90 and true then
                        x = (self.Weapon.Player.x + math.cos(self.angle) * self.Weapon.Distance)
                        y = (self.Weapon.Player.y + math.sin(self.angle) * self.Weapon.Distance) - 5
                    else 
                        x = (self.Weapon.Player.x + math.cos(self.angle) * self.Weapon.Distance)
                        y = (self.Weapon.Player.y + math.sin(self.angle) * self.Weapon.Distance) + 5
                    end
                    
                    self.x = x
                    self.y = y
                else
                    local x = self.x
                    local y = self.y

                    self.x = x
                    self.y = y
                end


                love.graphics.draw(self.Image, self.x, self.y, angle)

                return
            else
                return
            end
        end,
        Move = function(self, dt)
            local run = false
            pcall(function()
                local MouseX, MouseY = love.mouse.getPosition()

                local x = self.speed * dt * math.cos(self.angle)
                local y = self.speed * dt * math.sin(self.angle)

                self.x = self.x + x
                self.y = self.y + y

                run = true
            end)
            if run then
                if self.distance > 0 then
                    self.distance = self.distance - 1
                    return false
                elseif not (self.distance == nil) then
                    return true
                else
                    return false
                end
            else
                return false
            end
        end,
        CheckTouched = function(self)
            local run = false
            pcall(function()
                local MouseX, MouseY = love.mouse.getPosition()

                local x = 0

                self.x = self.x + x

                run = true
            end)

            if run then
                if self.distance > 0 then
                    self.distance = self.distance - 1
                    return false
                elseif not (self.distance == nil) then
                    return true
                else
                    return false
                end
            else
                return false
            end
        end,
    }
end

return Bullet
Any help is appreciated!
User avatar
marclurr
Party member
Posts: 158
Joined: Fri Apr 22, 2022 9:25 am

Re: Deleting an Object from a Table

Post by marclurr »

I seem to remember reading that modifying a table while iterating using pairs can cause some weird behaviour. There was another thread about this a few days ago but the suggestion was to iterate from the end of the array. That way deleting elements doesn't interfere with the iteration. Something like this will probably work:

Code: Select all

for i=#bullets, 1, -1 do
  .. logic ...

  table.remove(bullets, i)
end
On a side note, you really shouldn't load images on demand in this way. If you create many bullets using the same sprite it will result in multiple attempts to load the same image file. It's better to load the images once at the beginning of the program and reference the global instance where they're needed.

If the above doesn't fix your issue it's probably worth uploading a .love file so we can run and debug it.
Itswolfcity811
Prole
Posts: 7
Joined: Tue Jun 27, 2023 12:38 am

Re: Deleting an Object from a Table

Post by Itswolfcity811 »

Thanks for the tip on not creating a new image for each bullet but changing the for loop to not have pairs() didn't work. It is still like it was
before.

Here is the .love file, thanks for helping!

*I removed the attachment*
Last edited by Itswolfcity811 on Wed Jul 05, 2023 8:53 pm, edited 1 time in total.
User avatar
marclurr
Party member
Posts: 158
Joined: Fri Apr 22, 2022 9:25 am

Re: Deleting an Object from a Table

Post by marclurr »

I got it working by changing your call to remove from:

Code: Select all

table.remove(game.State.Running.Bullets, game.State.Running.Bullets[i].place)
to

Code: Select all

table.remove(game.State.Running.Bullets, i)
Edit: Actually it's still not quite right.
Last edited by marclurr on Wed Jul 05, 2023 8:54 pm, edited 1 time in total.
Itswolfcity811
Prole
Posts: 7
Joined: Tue Jun 27, 2023 12:38 am

Re: Deleting an Object from a Table

Post by Itswolfcity811 »

Thanks it work fine know!!
User avatar
marclurr
Party member
Posts: 158
Joined: Fri Apr 22, 2022 9:25 am

Re: Deleting an Object from a Table

Post by marclurr »

Itswolfcity811 wrote: Wed Jul 05, 2023 8:52 pm Thanks it work fine know!!
I've simplified your bullet class and it all works more reliably now. You were nearly there with the maths, it just had some weird logic causing a few weird behaviours.

Code: Select all

local love = _G.love

function Bullet(dmg, id, Weapon, Image, speed, distance, place)
    local MouseX, MouseY = love.mouse.getPosition()
    
    local angle = math.atan2(MouseY - Weapon.Player.y, MouseX - Weapon.Player.x)

    return {
        dmg = dmg,
        id = id,
        Weapon = Weapon,
        Image = Image,
        x = Weapon.Player.x + math.cos(angle) * Weapon.Distance,
        y = Weapon.Player.y + math.sin(angle) * Weapon.Distance,
        angle = angle,
        speed = speed,
        distance = distance,
        place = place,

        Draw = function(self)      
            love.graphics.draw(self.Image, self.x, self.y, angle)
        end,
        Move = function(self, dt)
            local x = self.speed * dt * math.cos(self.angle)
            local y = self.speed * dt * math.sin(self.angle)

            local len = math.sqrt(x*x+y*y)


            self.x = self.x + x
            self.y = self.y + y

            self.distance = self.distance - len
 
        end,
        CheckTouched = function(self)
            return self.distance <= 0

        end,
    }
end

return Bullet
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests