Spawning items/checking collision

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
Ries
Prole
Posts: 1
Joined: Sat Nov 30, 2024 9:12 pm

Spawning items/checking collision

Post by Ries »

Trying to spawn a random amount of objects on load while checking to see whether they collide with any pre-existing objects in the table

This is the code where I am adding to the table in the love.load function

Code: Select all

    for i = 1, numberofDust do
        dust = {}
        dustSize = 1.5

        if next(listofDust) = nil then
            dust.x = love.math.random(20, love.graphics.getWidth() - 50)
            dust.y = love.math.random(20, love.graphics.getHeight() - 50)
            table.insert(listofDust,dust)
        else
            for a, v in ipairs(listofDust) do

                        dust.x = love.math.random(20, love.graphics.getWidth() - 50)
                        dust.y = love.math.random(20, love.graphics.getHeight() - 50)

                        if not collision(dust.x, dust.y, dustImg:getWidth()*(1/dustSize), dustImg:getHeight()*(1/dustSize), v.x, v.y, henry:getWidth()*0.25, henry:getHeight()*0.25) then
                            table.insert(listofDust,dust)
                        end
            end
        end
    end
The using this in the love.draw function

Code: Select all

    for v = #listofDust, 1, -1 do
        if collision(posX, posY, henry:getWidth()*0.25/2, henry:getHeight()*0.25/2, listofDust[v].x, listofDust[v].y, dustImg:getWidth()*(1/dustSize), dustImg:getHeight()*(1/dustSize)) then
            table.remove(listofDust,v)
            increaseScore()
            sucka = suck:clone()
            sucka:setVolume(0.2)
            sucka:play()
        end
    end
    

    
And these functions outside of love.draw/update/load

Code: Select all

function collision(x1,y1,w1,h1, x2,y2,w2,h2)
    return x1 < x2+w2 and x2 < x1+w1 and y1 < y2+h2 and y2 < y1+h1
end

function increaseScore()
            score = score + 100
end
The code itself works fine adding/removing the objects on the screen when collision happens however the increaseScore function is rather than adding 100 each time an object is removed its adding multiple thousands to the score. Hopefully someone can see where I have gone wrong here and help?
User avatar
pgimeno
Party member
Posts: 3672
Joined: Sun Oct 18, 2015 2:58 pm

Re: Spawning items/checking collision

Post by pgimeno »

Can you give a working example exhibiting the problem? The code you've shown doesn't work at all.
RNavega
Party member
Posts: 385
Joined: Sun Aug 16, 2020 1:28 pm

Re: Spawning items/checking collision

Post by RNavega »

I think you're adding many objects in the same places. Your creation loops are weird:

For (numberOfDust)
For a, v in ipairs( listOfDust )
If the dust doesn't collide, add it to listOfDust
End
End

----
Edit: I also wonder if such a loop would go forever (on my phone now, can't test it):

for a, b in ipairs( myTable ) do
table.insert( myTable, item )
end

... would ipairs() keep iterating forever, since the list is constantly growing in its array part?
User avatar
pgimeno
Party member
Posts: 3672
Joined: Sun Oct 18, 2015 2:58 pm

Re: Spawning items/checking collision

Post by pgimeno »

RNavega wrote: Mon Dec 02, 2024 9:59 pm Edit: I also wonder if such a loop would go forever (on my phone now, can't test it):

for a, b in ipairs( myTable ) do
table.insert( myTable, item )
end

... would ipairs() keep iterating forever, since the list is constantly growing in its array part?
It does, I tested it. I tried adding glue code around the OP's snippets, but not having the parameters, it was all guesswork and it got stuck on that loop. That's why I requested a complete running example.

Here's what I tried:

Code: Select all

local score = 0
local numberofDust = 1000
local dustSize
local listofDust = {}
local dustImgData = love.image.newImageData(8, 8, 'rgba8', ('\100\100\100\255'):rep(8*8))
local dustImg = love.graphics.newImage(dustImgData)
local collision, increaseScore
local posX, posY = 400, 300
local henryData = love.image.newImageData(32, 32, 'rgba8', ('\205\255\205\255'):rep(32*32))
local henry = love.graphics.newImage(henryData)
local suckData = love.sound.newSoundData(1)
local suck = love.audio.newSource(suckData, 1)

-- Begin literal copy
function collision(x1,y1,w1,h1, x2,y2,w2,h2)
    return x1 < x2+w2 and x2 < x1+w1 and y1 < y2+h2 and y2 < y1+h1
end

function increaseScore()
            score = score + 100
end
-- End literal copy


function love.load()
    local dust
    
-- Begin literal copy except for the syntax fix of = -> ==
    for i = 1, numberofDust do
        dust = {}
        dustSize = 1.5

        if next(listofDust) == nil then
            dust.x = love.math.random(20, love.graphics.getWidth() - 50)
            dust.y = love.math.random(20, love.graphics.getHeight() - 50)
            table.insert(listofDust,dust)
        else
            for a, v in ipairs(listofDust) do

                        dust.x = love.math.random(20, love.graphics.getWidth() - 50)
                        dust.y = love.math.random(20, love.graphics.getHeight() - 50)

                        if not collision(dust.x, dust.y, dustImg:getWidth()*(1/dustSize), dustImg:getHeight()*(1/dustSize), v.x, v.y, henry:getWidth()*0.25, henry:getHeight()*0.25) then
                            table.insert(listofDust,dust)
                        end
            end
        end
    end
-- End literal copy

end

function love.draw()
  local sucka

-- Begin literal copy
    for v = #listofDust, 1, -1 do
        if collision(posX, posY, henry:getWidth()*0.25/2, henry:getHeight()*0.25/2, listofDust[v].x, listofDust[v].y, dustImg:getWidth()*(1/dustSize), dustImg:getHeight()*(1/dustSize)) then
            table.remove(listofDust,v)
            increaseScore()
            sucka = suck:clone()
            sucka:setVolume(0.2)
            sucka:play()
        end
    end
-- End literal copy

  love.graphics.draw(henry, posX, posY)
  for i = 1, #listofDust do
    love.graphics.draw(dustImg, listofDust[i].x, listofDust[i].y)
  end
  love.graphics.print(score)
end
RNavega
Party member
Posts: 385
Joined: Sun Aug 16, 2020 1:28 pm

Re: Spawning items/checking collision

Post by RNavega »

pgimeno wrote: Tue Dec 03, 2024 11:26 am I tried adding glue code around the OP's snippets, but not having the parameters, it was all guesswork and it got stuck on that loop.
That's a lot of work! Thanks for that.

Re-reading it, I think the OP wants to do a "reset stage" kind of thing: you play the game and collect (delete) objects on the stage, and when a timer or something else finishes, the stage is reset and all objects are randomly scattered again. If the amount of objects on stage is less than what it should be, then replenish as many objects as needed.

I think this variation would do it:

Code: Select all

function safeReposition(dust, dustSize)
    local collided = false
    local attempts = 3
    local testX, testY
    repeat
        testX = love.math.random(20, love.graphics.getWidth() - 50)
        testY = love.math.random(20, love.graphics.getHeight() - 50)
        collided = collision(
            testX, testY, dustImg:getWidth()*(1/dustSize), dustImg:getHeight()*(1/dustSize),
            v.x, v.y, henry:getWidth()*0.25, henry:getHeight()*0.25
        )
        attempts = attempts - 1
    until not collided or attempts == 0
    dust.x = testX
    dust.y = testY
end


function resetStage(listOfDust, numberOfDust)
    local totalSurvivingDusts = #listOfDust
    -- Reposition any items already on the list.
    for index = 1, totalSurvivingDusts do
        local preexistingDust = listOfDust[index]
        safeReposition(preexistingDust, 1.5)
    end
    -- Create more items to complete the list if needed.
    -- Only runs if 'totalNewDusts' is positive and non-zero.
    local totalNewDusts = numberOfDust - totalSurvivingDusts
    for i = 1, totalNewDusts do
        newDust = {x = 0, y = 0}
        safeReposition(newDust, 1.5)
        table.insert(listOfDust, newDust)
    end
end
Post Reply

Who is online

Users browsing this forum: Amazon [Bot] and 3 guests