class question

I have a runtime listener and a collision listener for two objects. For the runtime listener the objects move to a point and as they arrive they are removed. For the collision listener as an object collides with another specific object then the first object is removed.

My issue is that with the collision it removes both objects even if only one has collided, but with the runtime it works correctly. What is the difference and why does this happen?

[code]

display.setStatusBar( display.HiddenStatusBar )
local physics = require(“physics”)
local side
local dudes = {}
math.randomseed(os.time())

physics.start()
physics.setGravity( 0, 0 )

local function makeDude()
side = math.random(2)
local dude = display.newRect(100, 100, 100, 100)

dudes[#dudes+1] = dude
physics.addBody(dude, { isSensor = true })
dude.myName = “dude”

end

local player = display.newRect(300,500,100,100)
player:setFillColor(255,0,0)
player.myName = “player”

local function touchlistener(touch)
local phase = touch.phase

local touchsquare

function removets()
touchsquare:removeSelf()
touchsquare = nil
end

if phase == “began” then
touchsquare = display.newRect(player.x - 75, player.y - 75, 150, 150)
touchsquare:setFillColor(0,0,255)
touchsquare.myName = “touchsquare”
physics.addBody(touchsquare, { density = 0.3 })
local resettimer = timer.performWithDelay(100, removets, 1)
end

end

player:addEventListener(“touch”, touchlistener)

local function listener(event)
for i, dude in pairs(dudes) do
if dude ~= nil then
if dude.x > player.x + 99 and dude.x < player.x + 101 and dude.y < player.y + 1 and dude.y > player.y - 1 then
dude:removeSelf()
dudes[i] = nil
elseif dude.x > player.x - 101 and dude.x < player.x - 99 and dude.y < player.y + 1 and dude.y > player.y - 1 then
dude:removeSelf()
dudes[i] = nil
elseif dude.x > player.x + 100 and dude.y > player.y then
dude.x = dude.x - 1
dude.y = dude.y - 1
elseif dude.x < player.x + 100 and dude.x >= player.x and dude.y > player.y then
dude.x = dude.x + 1
dude.y = dude.y - 1
elseif dude.x > player.x - 100 and dude.x < player.x and dude.y > player.y then
dude.x = dude.x - 1
dude.y = dude.y - 1
elseif dude.x <= player.x - 100 and dude.y > player.y then
dude.x = dude.x + 1
dude.y = dude.y - 1
elseif dude.x > player.x - 101 and dude.x < player.x - 99 and dude.y > player.y then
dude.y = dude.y - 1
elseif dude.x < player.x + 101 and dude.x > player.x + 99 and dude.y > player.y then
dude.y = dude.y - 1
elseif dude.x > player.x + 100 and dude.y < player.y then
dude.x = dude.x - 1
dude.y = dude.y + 1
elseif dude.x < player.x + 100 and dude.x >= player.x and dude.y < player.y then
dude.x = dude.x + 1
dude.y = dude.y + 1
elseif dude.x > player.x - 100 and dude.x < player.x and dude.y < player.y then
dude.x = dude.x - 1
dude.y = dude.y + 1
elseif dude.x <= player.x - 100 and dude.y < player.y then
dude.x = dude.x + 1
dude.y = dude.y + 1
elseif dude.x > player.x - 101 and dude.x < player.x - 99 and dude.y < player.y then
dude.y = dude.y + 1
elseif dude.x < player.x + 101 and dude.x > player.x + 99 and dude.y < player.y then
dude.y = dude.y + 1
elseif dude.y > player.y - 1 and dude.y < player.y + 1 and dude.x <= player.x - 100 then
dude.x = dude.x + 1
elseif dude.y > player.y - 1 and dude.y < player.y + 1 and dude.x > player.x - 100 and dude.x < player.x then
dude.x = dude.x - 1
elseif dude.y > player.y - 1 and dude.y < player.y + 1 and dude.x >= player.x + 100 then
dude.x = dude.x - 1
elseif dude.y > player.y -1 and dude.y < player.y + 1 and dude.x < player.x + 100 and dude.x >= player.x then
dude.x = dude.x + 1

end
end
end
end

Runtime:addEventListener(“enterFrame”, listener)

timer.performWithDelay(4000, makeDude, 2)

function onCollision( event )
for i, dude in pairs(dudes) do
if (event.object1.myName == “touchsquare” and event.object2.myName == “dude”) or (event.object2.myName == “touchsquare” and event.object1.myName == “dude”) then
print( "began: " … event.object1.myName … " & " … event.object2.myName )
dude:removeSelf()
dudes[i] = nil
end
end
end

Runtime:addEventListener( “collision”, onCollision )
[/code] [import]uid: 10903 topic_id: 7789 reply_id: 307789[/import]

So I think I figured out the specific removal part of the issue, but now I get this error related to the runtime listener that moves “dudes” around:

Runtime error
…ins/Pictures/design/coronadesign/classtest5/main.lua:51: attempt to compare number with nil
stack traceback:
[C]: ?

I have an if clause that states to move them only if “dude ~= nil” so why would this be an issue?

My updated code:

[code]

local physics = require(“physics”)
physics.start()
physics.setGravity( 0, 0 )

math.randomseed(os.time())
local dudes = {}

local player = display.newRect(300,300,100,100)
player:setFillColor(255,0,0)
physics.addBody(player, {isSensor=true})
player.type = “player”

local function makeDude()
local dude = display.newRect(math.random(0,640),math.random(0,960), 100, 100)
dudes[#dudes+1] = dude
dude.myName = “dude”
dude.type = “dude”
physics.addBody(dude, { isSensor = true })

dude.collision = onLocalCollision

collectgarbage(“collect”)
print("System Memory : "…collectgarbage(“count”))
print(“create”)

end

timer.performWithDelay(1000, makeDude, 0)

function onCollision( event )

if ( event.phase == “began” ) then
if (event.object1.type == “dude” and event.object2.type == “player”) or (event.object2.type == “dude” and event.object1.type == “player”) then
print( "began: " … event.object1.type … " & " … event.object2.type )
event.object2:removeSelf()
event.object2=nil

collectgarbage(“collect”)
print("System Memory : "…collectgarbage(“count”))
print(“removed”)
end
end

end

Runtime:addEventListener( “collision”, onCollision )

local function listener(event)
for i, dude in pairs(dudes) do
if dude ~= nil then
if dude.x > player.x + 99 and dude.x < player.x + 101 and dude.y < player.y + 1 and dude.y > player.y - 1 then
–dude:removeSelf()
–dudes[i] = nil
elseif dude.x > player.x - 101 and dude.x < player.x - 99 and dude.y < player.y + 1 and dude.y > player.y - 1 then
–dude:removeSelf()
– dudes[i] = nil
elseif dude.x > player.x + 100 and dude.y > player.y then
dude.x = dude.x - 1
dude.y = dude.y - 1
elseif dude.x < player.x + 100 and dude.x >= player.x and dude.y > player.y then
dude.x = dude.x + 1
dude.y = dude.y - 1
elseif dude.x > player.x - 100 and dude.x < player.x and dude.y > player.y then
dude.x = dude.x - 1
dude.y = dude.y - 1
elseif dude.x <= player.x - 100 and dude.y > player.y then
dude.x = dude.x + 1
dude.y = dude.y - 1
elseif dude.x > player.x - 101 and dude.x < player.x - 99 and dude.y > player.y then
dude.y = dude.y - 1
elseif dude.x < player.x + 101 and dude.x > player.x + 99 and dude.y > player.y then
dude.y = dude.y - 1
elseif dude.x > player.x + 100 and dude.y < player.y then
dude.x = dude.x - 1
dude.y = dude.y + 1
elseif dude.x < player.x + 100 and dude.x >= player.x and dude.y < player.y then
dude.x = dude.x + 1
dude.y = dude.y + 1
elseif dude.x > player.x - 100 and dude.x < player.x and dude.y < player.y then
dude.x = dude.x - 1
dude.y = dude.y + 1
elseif dude.x <= player.x - 100 and dude.y < player.y then
dude.x = dude.x + 1
dude.y = dude.y + 1
elseif dude.x > player.x - 101 and dude.x < player.x - 99 and dude.y < player.y then
dude.y = dude.y + 1
elseif dude.x < player.x + 101 and dude.x > player.x + 99 and dude.y < player.y then
dude.y = dude.y + 1
elseif dude.y > player.y - 1 and dude.y < player.y + 1 and dude.x <= player.x - 100 then
dude.x = dude.x + 1
elseif dude.y > player.y - 1 and dude.y < player.y + 1 and dude.x > player.x - 100 and dude.x < player.x then
dude.x = dude.x - 1
elseif dude.y > player.y - 1 and dude.y < player.y + 1 and dude.x >= player.x + 100 then
dude.x = dude.x - 1
elseif dude.y > player.y -1 and dude.y < player.y + 1 and dude.x < player.x + 100 and dude.x >= player.x then
dude.x = dude.x + 1

end
end
end
end

Runtime:addEventListener(“enterFrame”, listener)
[/code] [import]uid: 10903 topic_id: 7789 reply_id: 27684[/import]

Also, how would I remove the table id of the removed object so as to prevent a memory leak? [import]uid: 10903 topic_id: 7789 reply_id: 27685[/import]

Yeah I just figured that out a few seconds ago. To fix it I added a statement that checks if dude has an x position, and if not to remove the table id, which also solved the leak.

Thanks as always jmp.

Any thoughts on adding health to dudes? So if each has a health of 100, and a collision provides 50 damage how might one track that for each “dude” individually? [import]uid: 10903 topic_id: 7789 reply_id: 27690[/import]

Off the top of my head… One function is removing a dude with removeSelf but this is queued until before the enterframe. so dude briefly exists but he is just a table now not a display object. Therefore he has no “x” property. Hence the error. Let’s just call him a ghost dude stuck in limbo until he can be removed for good. You would need to check for x not being nil. Or give him a “dead” property in your collision and only check his x if dead==false (or alive==true , whatever suits you but basically not nil either)

Also why do you have this line
[lua]    dude.collision = onLocalCollision[/lua]

That function doesn’t exist anywhere in your code

As for removing him from the table either use a dictionary instead

[lua]dudes[dude] = dude[/lua]
in the first place

And then [lua]local dude = event.object2
dudes[dude]=nil
dude:removeSelf()[/lua]

or loop through your table looking for your dude to find what index he is at and use table.remove or whatever [import]uid: 6645 topic_id: 7789 reply_id: 27689[/import]

Well each dude has their own x and y so they can just as well have their own health

Ps I updated my post above to answer some other questions [import]uid: 6645 topic_id: 7789 reply_id: 27695[/import]

The onlocalcollision was just a remnant of a past failed solution that I forgot to take out. [import]uid: 10903 topic_id: 7789 reply_id: 27696[/import]

“Well each dude has their own x and y so they can just as well have their own health”

This just changed my life. I had no concept of this and it completely changes how I was solving this issue. Thank you so much! [import]uid: 10903 topic_id: 7789 reply_id: 27698[/import]

Display objects are essentially just tables {…} you can add any custom property you want to them basically [import]uid: 6645 topic_id: 7789 reply_id: 27699[/import]

By the way supposedly a straight for loop is twice as fast as pairs.
http://trac.caspring.org/wiki/LuaPerformance

Check test 9

I would need to test this, but you would either use dudes[i].x or local dude = dudes[i] ; dude.x etc

Probably the latter is faster there too if you are doing multiple operations on the dude as you don’t have to keep looking him up in the table as you have cached a local reference [import]uid: 6645 topic_id: 7789 reply_id: 27701[/import]