Help needed with spawning and removing objects from tables.

Hey guys,

Basically what I want to do is spawn an object off screen on the left side and have it scrolled to the right. The player then tries to touch them to break them before they reach the end.

So…I can do all that. I’m getting a problem when they reach the end and I want them removed.

I can also do that if the user DOESN’T touch any of them along the way.

I read this article and it helped me understand how to spawn them http://blog.anscamobile.com/2011/09/how-to-spawn-objects-—-the-right-way/

But he didn’t go over the right way to remove them.

But here’s my code for the spawner:

[lua]local imageTable = {“asteroidsmall.png”,“asteroid02.png”, “asteroid03.png”, “asteroid01.png”};

local AsteroidTable = {};
local function createAsteroid()

local a = mRandom(1,4);

local asteroid = display.newImage(imageTable[a]);
asteroid.x = -cWidth + 50;
asteroid.y = mRandom(20, cHeight - 20)
physics.addBody(asteroid, “kinematic”, {density = 0, friction = 0, bounce = 0});
AsteroidTable[#AsteroidTable + 1] = asteroid;
asteroidGroup:insert(asteroid);
asteroid:setLinearVelocity(200, 0);

function touched (e)
if e.phase == “began” then

table.remove(AsteroidTable, asteroid.index)
asteroid:removeSelf();
asteroid = nil
print(“Astroid got clicked!”)

end

end
asteroid:addEventListener(“touch”, touched);

print (#AsteroidTable);

return asteroid;
end

timer.performWithDelay(1000, createAsteroid, 4);[/lua]

So that code works by itself. And the following code works by itself if the user doesn’t click more than 1 asteroid:

[lua]local function removeAsteroid()

if(#AsteroidTable >= 1) then

for i=#AsteroidTable, #AsteroidTable, -1 do

if AsteroidTable[i].x > cWidth then

AsteroidTable[i]:removeSelf();

AsteroidTable[i] = nil;

table.remove(AsteroidTable, i);

end

end

end

end


Runtime:addEventListener(“enterFrame”, removeAsteroid);[/lua]

If the user clicks more than 1 asteroid I get this error:

lua:89: attempt to compare number with nill

Which equals line 7 from the above code.

So if I watch them all leave the screen then they all get removed when the last one goes by, so that part works on it’s own.

It’s when I try to get rid of them by touching them before they get to the end that it seems to mess up the table.

I feel like it might be something really easy, but I’ve been struggling with this for the past few days and I’m not experienced at all. Most of this code is from googling how to do this and seeing other examples here in the forums.

Any help with this would be greatly appreciated and you might also help me get rid of my headache!
[import]uid: 123298 topic_id: 23425 reply_id: 323425[/import]

Shouldn’t line 5 read

for i=1, #AsteroidTable, -1 do

not

for i=#AsteroidTable, #AsteroidTable, -1 do [import]uid: 84637 topic_id: 23425 reply_id: 93878[/import]

Hey Danny,

Changing it to 1 doesn’t seem to remove any of them once they leave the screen.

I also have this running at the very bottom:

[lua]---------------------------------------------------------
local function showLength()
print(#AsteroidTable);
end

Runtime:addEventListener(“enterFrame”, showLength);[/lua]

The way I had it before shows the count go up to 4 when the are all created then when the last asteroid scrolls of the screen it counts down from 4 to 0.

Changing it to 1 keeps the count at 4.

Also when I click on the first 2 the count goes down to 2. And there’s only 2 asteroids left in the table, when I start clicking on the last 2 the error pops up…

I just tested it with 10 spawn and 20 spawn.

Something is going on when I hit only 2 asteroids left, when I go to click on the second to last the error pops up.

…man, I really hope I’m explaining it correctly and isn’t too confusing. [import]uid: 123298 topic_id: 23425 reply_id: 93882[/import]

I think it should actually be

[lua]for i=#AsteroidTable, 1, -1 do[/lua]

You want to count backwards. So you’re starting at the high number and going down.

-Mark [import]uid: 117098 topic_id: 23425 reply_id: 94082[/import]

Thanks for the help guys!

I figured it out last night after crap load of coffee.

So what was going on is the asteroids in the table kept getting shifted every time I clicked on one. If I had spawn 4, clicked on the first one then 1 got removed and then 2 became 1, 3 became 2 and 4 became 3 and that was throwing off the table count.

What was throwing it off from that blog post about spawning objects the right way was this:

[lua] --Automatically set the table index to be inserted into thenext available table index
object.index = #object.objTable + 1

–Give the object a custom name
object.myName = "Object : " … object.index

–Insert the object into the table at the specified index
object.objTable[object.index] = object[/lua]

This doesn’t work in my scenario. Because I was removing some of them while new ones were being created and that totally changes the #objTable.

Let’s say I wanted to make 10 spawn every 2 seconds.

As soon as one asteroid spawned I wanted it to shoot through the screen. It would have the index of 1. Because the asteroid.index = #AsteroidTable + 1

So asteroid 2 should have an index of 2.

Well, if 2 asteroids were already created and I clicked and removed asteroid 2. The next asteroid spawn that should have index 3 now has index 2 because when you remove a key they all shift forward so the index of all of them were being shifted because they relied on the length of the table. And this was really throwing off the count and confusing the hell out of me.

So I did some research and changed my code to this for the spawner:

[lua]local imageTable = {“asteroidsmall.png”,“asteroid02.png”, “asteroid03.png”, “asteroid01.png”};

local AsteroidTable = {};

local function createAsteroid()

local a = mRandom(1,4);
local indexCount = 0;

local asteroid = display.newImage(imageTable[a]);
asteroid.x = -cWidth + 50;
asteroid.y = mRandom(20, cHeight - 20)
physics.addBody(asteroid, “kinematic”, {density = 0, friction = 0, bounce = 0});
asteroid.index = indexCount + 1;
AsteroidTable[#AsteroidTable + 1] = asteroid;
asteroidGroup:insert(asteroid);
asteroid:setLinearVelocity(700, 0);

indexCount = indexCount + 1;

local function touched (e)
if e.phase == “began” then

table.remove(AsteroidTable, asteroid.index)
asteroid:removeSelf();
asteroid = nil

return
end
end
asteroid:addEventListener(“touch”, touched);

–print (#AsteroidTable);

return asteroid;
end

timer.performWithDelay(1000, createAsteroid, 50);[/lua]

This way no matter the length of the AsteroidTable each asteroid would have the correct index because of this
indexCount increasing every time a new spawn was created.

And this for when they get off screen:

[lua]local function removeAsteroid()

if(table.getn(AsteroidTable) >= 1) then

for i=1, table.getn(AsteroidTable) do

if AsteroidTable[i].x > cWidth + 100 then
AsteroidTable[i]:removeSelf();
AsteroidTable[i] = nil;

table.remove(AsteroidTable, i);

return
end

end

end

end


Runtime:addEventListener(“enterFrame”, removeAsteroid);[/lua]
…now after proofreading it I got really confused again and don’t even if that is what the problem was.

It works now though.

I also don’t know why:

AsteroidTable[i]:removeSelf();
AsteroidTable[i] = nil;
table.remove(AsteroidTable, i);

is the opposite on the touch event or the for loop. I kept getting errors if I tried to make them the same

So anways, apologize if this is a lengthy post, tried to explain it as well as I thought what was going on in case another noob like me was having this same issue.
[import]uid: 123298 topic_id: 23425 reply_id: 94087[/import]