Leftover objects after setup()?

i have a little game that calls setup() from deep inside, to restart after someone wins. It’s Spacewar, and if two ships collide, both die. Sometimes in the restart, a ship explodes immediately. Debug prints tell me it is two ships of the same name, but different tables. There are only two ships, and the table of live ships contains two elements when the explosion happens: the extra ship is not in the table.

I am clearing the tables on startup and only create two ships, with two different names. Yet the collision is between two ships with the same name and different tables.

I assume this bug is mine, and even if there were a ship lying around uncollected, I don’t see how I could have gotten a handle on it. But I wanted to post the concern, in case ideas or questions may shed some light on one of those impossible things that happen to us before we find the bug.

Ideas? Thanks!

Thanks, Jmv. I don’t mind if they exist, since they are only seen if they are in my collections. Issue has to do with staying in the collections. See next.

OK, resolution. Cause not found but it was somewhere in here. :slight_smile:

Moved setup contents to initialize and called that. I really don’t think it’d hurt to call setup, there’s no invisible code in it afaics.

Also, and this is probably important, waited to call setup if GameOver is true, outside the draw loop.

Stopped fiddling with the lists while they were being iterated, instead having lists Adds and Deletes that are processed after the main lists are done iterating. Pro Tip: clear your Adds and Deletes after adding and deleting, lest you add again …

That seemed to fix it. So I’m not sure what was making it seem like there were only two ships in the list but someone saw another one but it went away. The old approach was obviously “wrong”, trying to delete from a table that’s in use.

So, not entirely satisfying but more obviously correct code works as intended.

Thanks for hints and ideas, they kept me improving until it went away. :slight_smile:

I havent read everything above, so maybe you already checked that, but when you do:

FlyingObjects[self] = nil.

then your object self is still there for some time, until garbage is collected. This may take seconds. To be sure it is removed immediately you must do:

FlyingObjects[self] = nil
collectgarbage()

I can’t see an obvious problem with your code, but I would follow the sequence of events very closely to track exactly what is happening.

Setting a table to nil should be sufficient to clear it (you can make sure by calling collectgarbage() immediately afterwards). If this doesn’t seem to be working, it suggests that something is happening in the wrong order.

Is calling setup going to stop the previous draw loop and start a new one? Since I’m calling setup from inside the draw() could I be running multiple instances of the program at the same time? Holding on to the same global tables, maybe?

Urrrk?

Hmm, I see an example of restarting that doesn’t call setup directly but has all the setup code in a function initialize() and calls that. That does sound safer, I’ll try that next … tomorrow. bedtime now :slight_smile:

Yes, I prefer not to call setup twice, but to put the initialisation code in its own function, and then call that from setup and draw as required. Safer.

Weird … here’s my setup: https://gist.github.com/RonJeffries/852904b3ea1e2b74354e

as you can see, it clears the FlyingObjects and Ships lists. Then it creates two ships and adds them. It also creates a sun and puts it in FlyingObjects. I’ve changed the code so that after the main draw, it deletes from Deletes and adds from Adds.

It’s also printing the table (id) and ship.name. (Ship.name is “Ship” + the x value of its color, so they wind up being Ship15 and Ship255. )

After a few runs I got the explosion on startup. Checking a trace of what collided, there was a ship15 colliding with another ship15. The index of one of them was (tada!) from a previous game.

In https://gist.github.com/RonJeffries/1798acf92f27730bfa23 we see the relevant code for collisions (in the Ship class). It loops through Ships (there are two Ships, remember) and does not try to collide with itself. (The double checking is a belt and suspenders left over, but it does never collide a ship with itself.)

Presently the first ship to notice collision removes itself. I expected the second guy to detect the collision as well but for some reason it does not. Since the first ship is not removed until the draw is over, it should still be there. However, it will have moved (the move completes, so that’s probably it. Anyway not germane to the bug.

We see that if the ship collides, it will add an Explosion and delete itself. Finally, in https://gist.github.com/RonJeffries/ec0c59bff34645670496 we see how it deletes old dead guys and adds in the new (explosions are added here, and missiles (not shown)).

Anyway, all this is more for reassurance than anything else. The fact from the printout is that the program is seeing a Ship that was created in a previous call to setup() and as far as I can tell it cannot possibly be in the tables because they are set to {}.

Makes me wonder if just calling setup() is really a safe way to restart the program … and I still don’t know where the bug is. I’ll do more when my battery recharges. :slight_smile:

Ideas still welcome! :slight_smile:

My explosion flings rotating chunks of ship and a little stick man out into space. It’s a real flying object. Then it times out and restarts the game. :slight_smile:

I suspect when objects are deleted they are not cleared, so if you got hold of an old pointer things might sort of work. I’m not sure where I’d be getting the old pointer. The delete / replace table will fix it, I’m betting … leaving a mystery wrapped in an enigma.

I would create a table that holds all the info about each object. Then have several loops in draw that checks for specific things. The first loop could check for “delete” and remove it. The second loop could check for any collisions and set “delete”. The third loop could check for “delete” and not shoot or collide with anything anymore. Not sure about everything you’re trying to do, but something along those lines. One table to hold all info and process thing in a certain order.

if you want to know what happens when you delete a class instance from within itself, you will need to look at how our implementation of Lua does this. The code is accessible (I don’t know where, but I think maybe on a forum thread).

If you want to show an animated explosion sequence when a ship is destroyed, this could be managed with an “explosion” table containing (x,y) and time of destruction for each dead ship, so you can play out an animation, maybe with a tween, and you could vary the explosion image (even by just flipping it vertically and horizontally, or changing its size, to create an impression of variation). Better than a static image.

yes it’s tempting. i can put key->nil or key->replacement. (i replace the ship with an Explosion when it’s destroyed, for example.

i suspect if i do that the bug may disappear. but i’d like to know what it is :slight_smile: i hate when i fix something without knowing what happened.

In other words, all objects stay alive until the end of each frame, then you clean up the bodies

ignatz, yes, thanks. not quite my thing … really all i’d need would be for the things to become inaccessible.

relatedly, one time in Smalltalk we did a thing where if an object got a doesNotUnderstand: aMessage we looked for any implementer of that message and used become: to become one of those and redispatched.

That got ugly in a hurry :slight_smile:

I would assume every object gets an equal chance to move/shoot/etc in each frame, which is reasonable because a frame is 1/60 of a second. So even if an object gets destroyed, it still has a chance to shoot another object or whatever in the same frame.

So I would hold a table of destroyed objects, and put object keys in there as you loop through your list of objects, and then destroy the objects in that table at the end of the draw cycle.

… imagine … you’re flying objects around, so your main:draw() is going over the list telling everyone to draw. some of the guys, when they draw, decide to kill someone. so they need to get that guy out of the list, or replaced in the list. sometimes death is mutual so they even remove themselves. (currently i let them draw one more time, which seems harmless).

also objects time out. bullets, for example. fly for N seconds and then kill themselves.

must think of good way to have a growing and shrinking list of flying objects. thoughts? i’m probably not the first person to need to edit a live list …

Also see

http://codea.io/talk/discussion/4593/how-to-get-an-instance-of-a-class-to-remove-itself-/p1

http://codea.io/talk/discussion/4776/how-to-get-an-instance-of-a-class-to-delete-itself-solved/p1

One more thing, maybe try calling the collectgarbage function after removing your object, to force immediate deletion. It does sound like you have zombie objects that won’t die.

There is a chance I’m deleting while someone is traversing the list. That could do weird things … but not create a second object. Must think what to do about that. Make a list of deletes / replaces maybe. Would be safer / better anyway.

Are you deleting a class instance from within itself? Ouch.

My preference would be to have a separate table containing objects to be deleted, and add the instance key to this table when you want it deleted.

The draw function can then use this table to do any deletion required when it runs next. This avoids getting an object to directly delete itself.