How would you print() out or find out the index of an object?
For example, if I spawned 20 random rock objects on screen into an array RockTable = {};
<
Invert the table:
function table_invert(t)
local u = { }
for k, v in pairs(t) do u[v] = k end
return u
end
You can then use the inverted table to find the index.
I find this function so useful that it goes into my permanent "Lua utilities" libraries.
The simplest way is to add an "index" property to each rock:
RockTable = {}
for i=1,20 do
local rock
-- do your thing that generates a new 'rock' object
rock.index = #RockTable + 1
RockTable[rock.index] = rock
end
If you use a touch listener method, you can retrieve the rock this way:
function touchListener( event )
local rock = event.target
local rockIndex = rock.index
-- ...
end
It is true that you can maintain a second table with indices, but I find my method cleaner - when it is time to remove things, you only have to worry about one table, the main one.
I have a question though: why do you need to retrieve that index? In most cases, well designed event listener functions are enough, you don't need to "find" your objects. Of course I lack information on what you are trying to do, but it is possible that you are over-complicating things.
you could do something like this to save you some trouble of constantly looping over a table to find the index...
RockTable = {}
RockIndicies = {}
for i = 1, 20 do
idx = #RockTable + 1
RockTable[idx] = rock
RockIndicies[rock] = idx
end
then when you need to know the index, you can just use the rock you have to index RockIndices to quickly get it. If you 'delete' a rock, you'd want to make sure to remove it in both places.
Unfortunately you'd need to brute the table, to my knowledge. Although, to know that one was clicked, wouldn't you need to be looping them in some way anyway; and therefore already know the index?
Edit
Oh, unless Corona has some sort of callback event for clicking. I've never used it, I've got experience in Lua though.
You could maybe do a backwards reference, like so:
Rocks = {a rock, a rockB, a rockC}
RocksB = {[a rock] = 1, [a rockB] = 2, [a rockC] = 3}
Then just say rockNum = RocksB[rock]
I'm pretty certain that should work but I can't guarantee it, worth a try though.
Edit2
The brute method would look somewhat like:
function getRock(rock)
for _,v in pairs(rocks) do
if (v == rock)
return _
end
end
return "Rock does not exist."
end
There's another way you can do it, using metamethods. [Edited to allow you to remove values too]
t = {} -- Create your table, can be called anything
t.r_index = {} -- Holds the number value, i.e. t[1] = 'Foo'
t.r_table = {} -- Holds the string value, i.e. t['Foo'] = 1
mt = {} -- Create the metatable
mt.__newindex = function (self, key, value) -- For creating the new indexes
if value == nil then -- If you're trying to delete an entry then
if tonumber(key) then -- Check if you are giving a numerical index
local i_value = self.r_index[key] -- get the corrosponding string index
self.r_index[key] = nil -- Delete
self.r_table[i_value] = nil
else -- Otherwise do the same as above, but for a given string index
local t_value = self.r_table[key]
self.r_index[t_value] = nil
self.r_table[key] = nil
end
else
table.insert(self.r_index, tonumber(key), value) -- For t[1] = 'Foo'
self.r_table[value] = key -- For t['Foo'] = 1
end
end
mt.__index = function (self, key) -- Gives you the values back when you index them
if tonumber(key) then
return (self.r_index[key]) -- For For t[1] = 'Foo'
else
return (self.r_table[key]) -- For t['Foo'] = 1
end
end
setmetatable(t, mt) -- Creates the metatable
t[1] = "Rock1" -- Set the values
t[2] = "Rock2"
print(t[1], t[2]) -- And *should* proove that it works
print(t['Rock1'], t['Rock2'])
t[1] = nil
print(t[1], t[2]) -- And *should* proove that it works
print(t['Rock1'], t['Rock2'])
It's more versatile as you can copy the t
value and take it with you; it also means that you only have to play around with the one variable most of the time - hopefully should reduce the likelihood of you trying to access the wrong thing.