Removing an object from a table question

Got it! Thanks for all your help!

I somewhere had a reference to objects, so they didn’t get cleared the right way, when being removed. I now have implemented the code RoamingGamer suggested (Thanks a LOT for this!) and will make the changes to the complete game in the next days. It now works fine regarding the memory and the system memory is now steady because when an enemy is getting destroyed or removed the memory clears.

The answer to your question is on the API page:

This event is delivered to a display object when …  removed … This is useful if you have cleanup …

In the code above, all enemies have a finalize listener attached, so when they are deleted it executes and they remove their reference from the enemies table.

Open up a blank project and put this in main.lua to help you understand.

local obj = display.newCircle( 100, 100, 10 ) function obj.finalize( self ) print (" Deleting object ", self, " @ ", system.getTimer() ) end obj:addEventListener("finalize") print("Created and set up object ", obj, " @ ", system.getTimer() ) display.remove(obj)

Thank you!

Thanks!!!


compare and contrast essay sample

I saw a post from RoamingGamer the other day which mentioned he would use the object itself as the key in the table. Then you can just remove it by doing myTable[myObject] = nil, and use in pairs to iterate over the table instead of a for loop.

Don’t remove the destroyed enemy but replace it with the last enemy within your array.

I.e.

[lua]

local numEnemies = #myEnemies

myEnemies[deleteIdx] = myEnemies[numEnemies]

myEnemies[deleteIdx].index = deleteIdx – update the index to the new slot

myEnemies[numEnemies] = nil

[/lua]

This way, the removal is a constant time operation, all entities but the one moved into the free slot keep their index and the moved one gets the new index.

Nice!

Thats a bit too generalized info which can result in many different scenarios, which I doubt anyone will sit down and type out.

A more specific problem situation and code sample is likely to let people give a more short and targetted response.

Unless you get RG on it, he’s probably gona write you an essay on the subject  :slight_smile:

Thanks for you help!

@Michael This looks like a very easy to implement solution, but I have some bullets moving around which will have a ref to the enemy they are aiming at which makes this a little bit hard to implement with the existing code.

@nick_sherman I will look into this!

so what do I have to do to get the length for this table then?

Example: when doing this… #Enemy I always get 0 now!

How can I get the length of this new table using the objects itself?

That’s as simple, just add a list of bullets to update to each enemy. The update/handling of the array is basically the same.

Whenever a bullet selects an enemy, add it to the list, and remove it when you destroy the bullet (or it follows another target).

On destruction of the enemy, update each bullet in the list and on destruction of a bullet, update the list in the enemy.

You don’t need to know the length of the table, you just iterate over it using k,v in pairs.

so doing

for k,v in pairs (Enemy) do ... end

should do the job, right? But how can I now get the correct Enemy from the table to do the collision detection?

Is it via

for ...      Enemy[v] end

is this giving me the Enemy I want to check with?

Or is it Enemy[k] or something else?

And how do I delete later?

?

In this instance both k and v will represent the enemy - the key is the enemy, the value is also the enemy.

I’m late to the party, but I suggest not using numeric indices unless order of calculations matters.

i.e. do this:

local enemies = {} local function makeEnemy( ... ) -- args up to you local enemy display.new ... code to make enemy enemies[enemy] = enemy -- Index by enemy not a number function enemy.finalize(self) enemies[self] = nil end; enemy:addEventListener("finalize") return enemy end ... later local anEnemy = makeEnemy() -- Now it is in the enemies table display.remove( anEnemy ) -- Now it is not. Automatically.

Tip:  For small tables (those with around a few thousand entries or less) there is a negligible speed difference between numerically indexed and object indexed tables.

For games, I never choose an indexing system based on speed.  I choose it based upon how it affects my game mechanics and on whether it makes coding hard or easy.

By the time you have enough object references in your table where speed of iteration is a problem, you’ll be out of memory from creating all those objects.

I don’t think table iterations should have anything to do with your speed, although I do think a numerically indexed table is the wrong way to go.

More likely to be affecting your speed are these things (in order of likelihood):

  • The rendering
  • The calculated collision test you mentioned.
  • The transitions

Question:   How are you doing your (within radius) collision detection calculation.

Please tell me you’re using squared lengths. i.e I hope you are not using math.sqrt() in this test.

In fact, please show you’re algorithm.

Here is an example that shows:

  1. How to efficiently do a within radius calculation minus the square root calc one might normally use.

  2. How rendering display objects dominates over the choice of loop indexing and iteration

  3. Re-inforces #2 with the use of ‘fake’ objects to show how a large table of tables is fast to iterate over.

https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2018/10/efficiencyTest.zip

To test this, first run the demo with ‘useRealObjects’ set to ‘true’.  Tap right side of screen to increase max objects, left to decrease.

Slowly increase till your FPS dips and stays below 60.  Note the ‘target’ number of the left bottom.

Repeat with  ‘useRealObjects’ set to ‘false’ (this uses tables so it looks boring).  Notice how at the same target number your FPS is still fine?

https://www.youtube.com/watch?v=439lAISwYko&feature=youtu.be

Wow thanks!

My collision code I am using is optimized and not the problem. no math functions… just a position check based on distances of objects to each others.

But I’m doing this check inside a for loop which is going to all the enemies.

Now with using the pairs version for the ref table the game is faster in higher levels a lot! BUT: I get lags when enemies are spawned.

Is there a way to use some faster alternate version to something like this without the slow pairs?

for k,v in pairs (Enemyreflist) do ... end

How many objects are you iterating over per frame?  Try to give an exact maximum count or at least a pretty-sure count.

I’m asking because in my experience pairs() is plenty fast so I have to wonder if there is some other issue going on.