Is there a lua data structure that works like a display group, but without the coordinate shifting?

I have a bunch of display objects on the screen (call them enemies). It’s useful to put them in a display group - that way I can iterate through the group, find out how many enemies are left, and check when all enemies are gone.

The display group is nice because I can just remove the object (through removeSelf() or whatever) and it automatically removes it from the group, and re-indexes all the other objects in the group.

But I don’t actually need the other features of a display group, and it screws up the physics engine if things are in different groups. I just need some kind of structure that keeps track of objects without my explicitly adding or removing them. [import]uid: 49372 topic_id: 9344 reply_id: 309344[/import]

The only kind of data structure Lua offers is tables, but those are extremely flexible and can be used for all kinds of purposes. For example, you can use pairs() to iterate through the table without knowing all their indexes or the size of the table or anything:
http://www.learn-corona.com/2010/10/iterating-over-a-lua-table-efficiently/

You can even use display objects as their own indexes in the table, which I explain here:
http://developer.anscamobile.com/code/tables-lua-dictionaries-and-arrays

You will need to explicitly add and remove objects however. It’s probably simplest to create a remove() function that handles niling the table value and removing any associated sounds or other memory, and then just call that remove() function. [import]uid: 12108 topic_id: 9344 reply_id: 34132[/import]

This is exactly what I was looking for - thanks! Using the display objects as their own indexes is a great idea, and makes an incredible clean solution for keeping track of similar objects.

But I don’t think I need to explicitly remove objects, do I? Since when I remove the object using removeSelf(), I’m essentially setting the index of the table to nil (since the index - the object itself - doesn’t exist any more). Is that correct?

Also, I found I can’t find the number of items in the table:

[lua]squares = {}

for i=1,5 do
local square = display.newRect(15*i, 50, 10, 10)
squares[square] = square
end

print (#squares) – “0”
print table.maxn(squares) – “0”[/lua]

I suppose I could create a “for k, v in pairs(squares) do” loop and then just count the items using an external local variable, but that seems kind of stupid… isn’t there a way to find the number of items in the table?
[import]uid: 49372 topic_id: 9344 reply_id: 34159[/import]

But I don’t think I need to explicitly remove objects, do I? Since when I remove the object using removeSelf(), I’m essentially setting the index of the table to nil (since the index - the object itself - doesn’t exist any more). Is that correct?

Unfortunately that’s not how it works. removeSelf() doesn’t set object references to nil:
http://developer.anscamobile.com/content/application-programming-guide-graphics-and-drawing#Variable_References

Also, I just found this article about a relevant situation that just confuses me:
http://lua-users.org/wiki/GarbageCollectingWeakTables

I’m trying but I can’t sort out what they are talking about.

As far as the table size issue, that’s a pretty annoying omission from Lua that other’s discuss:
http://lua-users.org/wiki/LuaTableSize

I would make a custom add() function in addition to remove() and both increment/decrement a variable for the table’s size. [import]uid: 12108 topic_id: 9344 reply_id: 34162[/import]

Why are you using the reference to the display object as a hash?

[lua]squares = {}

for i=1,5 do
squares[i] = display.newRect(15*i, 50, 10, 10)
end

print (#squares) – 5[/lua] [import]uid: 51516 topic_id: 9344 reply_id: 34233[/import]

A couple things:

  1. “squares” is not a reference to a display object, that is a table with display object references in it. squares[1] would be a reference to a display object.

  2. Putting a pound symbol in front of a table reference is Lua syntax for returning the continuous length of the table.

What’s tricky here though is that “continuous length” is not the size of the table (ie. how many entries are in the table.) What it does is count up integer indexes from 1 until nil. So if the table had indexes 1 2 3 5 6 that would make the pound symbol return 3.

The maxn function returns the highest integer index so that would be 6.

That’s still not the size of the table though, because indexes into the table don’t have to be integers. As far as I know there is no command in Lua to get the size of the table, only commands for dealing with integer indexes. Seems like a pretty glaring omission to me. [import]uid: 12108 topic_id: 9344 reply_id: 34281[/import]

@jhocking:

Thanks for the explanations, that makes sense now. It’s strange, since Lua tables are so flexible and powerful, it seems like they encourage non-numerical indexes… and yet the table size functions rely on pretty standard indexes to work.

Your idea of keeping track of the number of items using custom add() and remove() functions seems like it would work just fine, though, good idea.

@seth.dev.ios:

Using the reference to the display object as a hash has advantages in my case, since they’re enemies… I create and delete them at different times (often based on collision or touch events or timers), so it becomes a pain to keep track of numerical indexes, re-index them, etc. This way, it makes for a very clean removal in an event handler, for example, since I don’t need to look up the index of the object I’m handling - the “self” is the index. [import]uid: 49372 topic_id: 9344 reply_id: 34287[/import]

@jhocking: I was talking about “square” not “squares”

What it does is count up integer indexes from 1 until nil.
Not true:

[lua]squares = {}

for i=1,5 do
squares[i] = display.newRect(15*i, 50, 10, 10)
end

print( “Size:”, #squares) – 5

squares[3] = nil
collectgarbage(“collect”) – just for fun

print( “Size:”, #squares) – 5[/lua] [import]uid: 51516 topic_id: 9344 reply_id: 34293[/import]

I was talking about “square” not “squares”

The code you posted only had “squares” not “square”. *shrug*

Not true:

oh, I must be mis-remembering that. So what does # do? And what does maxn() do? [import]uid: 12108 topic_id: 9344 reply_id: 34296[/import]