I’m trying to figure out how to organize my data and identify which object was clicked on from an array.
I have 10 ships in a table, and in the table I have a field called shipGraphic. I attach an event for each of them as I iterate, and they respond when clicked, but I’d like to know which ship was clicked on. Am I making sense?
Here’s my simple code I’m fiddling with. I’d love to have it say “Hey, you clicked on ship 2!”.
[code]
local touchShip = function( event )
if “ended” == event.phase then
print(“We touched a ship!”)
– But I’d like to know which ship out of my array was clicked?
end
end
shipTable = {}
– So we’re making a table of tables…not sure if this is the route to go
for i=1,10 do
– Create our table within our table
shipTable[i] = {}
– Give the ship a name
shipTable[i].name = "Ship: "…i
– Load a graphic into our “shipGraphic” field
shipTable[i].shipGraphic = display.newRect( 0,0,10,20 )
– Place our ship randomly and set a rotation…
shipTable[i].shipGraphic.x = math.random(0,300)
shipTable[i].shipGraphic.y = math.random(0,300)
shipTable[i].shipGraphic.rotation = math.random(0,359)
– Attach the ship graphic to an event
shipTable[i].shipGraphic:addEventListener( “touch”, touchShip )
end
[/code] [import]uid: 11636 topic_id: 4425 reply_id: 304425[/import]
Ah, but the event.target is the graphic located IN my table. I need to access the table element CONTAINING the shipGraphic…or can I name a display object? That would work fine too… [import]uid: 11636 topic_id: 4425 reply_id: 13802[/import]
Runtime error
…8kphv6kHJelCfGyHAHTr++++TI/TemporaryItems/3/main.lua:3: attempt to concatenate field ‘parent’ (a table value)
stack traceback:
[C]: ?
…8kphv6kHJelCfGyHAHTr++++TI/TemporaryItems/3/main.lua:3: in function <…8kphv6khjelcfgyhahtr> ?: in function <?:214> Hehehehehe. I do have a workaround sorta:
<br>shipTable = {}<br>-- So we're making a table of tables...not sure if this is the route to go<br>for i=1,10 do<br> -- Create our table within our table<br> shipTable[i] = {}<br> -- Load a graphic into our "shipGraphic" field<br> shipTable[i] = display.newRect( 0,0,10,20 )<br> -- Give the ship a name<br> shipTable[i].name = "Ship: "..i<br> -- Place our ship randomly and set a rotation...<br> shipTable[i].x = math.random(0,300)<br> shipTable[i].y = math.random(0,300)<br> shipTable[i].rotation = math.random(0,359)<br> -- Attach the ship graphic to an event<br> shipTable[i]:addEventListener( "touch", touchShip )<br>end<br>
By making the actual shipTable[i] a Rect or Image by using this:
Wow this is a trip coming from C#. LUA is pretty flexible, I come from the OOP camp of the whole “has a” VS “is a”…and in this case my shipArray[i] “is a” display.newRect!!! That’s cool! [import]uid: 11636 topic_id: 4425 reply_id: 13805[/import] </…8kphv6khjelcfgyhahtr>
wow that is a neat trick I’ll have to try in my project.
To explain why that works, a Rect object IS a table. In Lua there aren’t separate objects and arrays; you do OOP in Lua by using tables as objects. Thus, when you type “shipTable[i] = display.newRect(0, 0, 10, 20)” you are basically making your shipTable object inherit from the Rect object, and the subsequent lines add new properties to the inherited ones.
(incidentally, doing “shipTable[i] = {}” is a waste of time because that creates one table, and then in the next line you create another table. The first table loses its reference and eventually gets cleaned up by the garbage collector) [import]uid: 12108 topic_id: 4425 reply_id: 13848[/import]
Well I’m pretty new to Corona myself so I’m not 100% sure I got that right. But I do know that OOP in Lua is really based on using tables like objects, so I’m pretty sure that is what’s happening. The way to really check for certain (and what I’m planning to do tonight) is use “for i,v in ipairs(shipTable[i]) do print(v) end” and see what the output is. [import]uid: 12108 topic_id: 4425 reply_id: 13869[/import]
Oh man thanks for trying that and giving me this great idea! Once your post made me realize Image objects are tables just like everything else in Lua, I figured I should be able to add new functions to Images because in Lua functions can be passed around just like variables. I just tested it and sure enough that works. sweet!
Now I’m going to do OOP in Lua by treating every class as a decorator that adds new methods on to other objects.
If I want to make a moving character, I’ll just go Mover.decorate(character)
If I also want that character to attack, the next line will be Attacker.decorate(character)
and so on [import]uid: 12108 topic_id: 4425 reply_id: 14075[/import]
Well glad I could help! Even if it was by accident! Hahaha!
Seriously, your idea sounds very OOP and modular.
Would you share some code? Even if it’s just debug text happening for a modular function, I’d like to see what you’re talking about!! Maybe in a separate thread since this one’s getting long!!! Hahaha!
Best,
Mario
[import]uid: 11636 topic_id: 4425 reply_id: 14078[/import]
The decorator approach I’m using is even more modular and avoids copy-pasting functions into multiple places, but the general idea is clearly how other people are doing things already. [import]uid: 12108 topic_id: 4425 reply_id: 14112[/import]
This shows off the techniques I was talking about for doing OOP in Lua by adding functions to tables. Tell me if you can understand this example or if I need to strip it down even further to expose the concepts.
(The controls are on Level1 the entities react when you tap the screen. On Level2 the entities don’t pay any attention to input. On both levels there’s a small button in the top corner to return to the menu.)
Unfortunately I can’t be sure I’m handling all the memory correctly and there aren’t any leaks. As I ask about in this other thread, I don’t know if the buttons or scene transitions are leaking: http://developer.anscamobile.com/forum/2010/12/15/memory-leak-uilua
ADDITION:
To the guy who downloaded this right after I posted it last night, this morning I realized I forgot to localize the math functions in order to optimize them, so I made that tiny change and re-uploaded the file.
Damn jhocking you’re a madman!! I’ve watched your updates flow in while I was at work the past couple days cracking up! You haven’t stopped! I’m gonna settle in and have a look at the code soon.
Corona is damned addicting! It’s SO much easier and faster to get stuff up and going than other frameworks!!! Let’s tear into the LUA awesomeness!
I just updated the download again because I hadn’t done an example of multiple inheritance. So I added a third level where the entities have the floating behavior from Level 2 and react to taps like Level 1. If you look in the code, you can see that this was done by simply having both decorator lines for the entities instead of only one decorator.
This is turning into a useful little coding sample/game template so eventually I’ll probably write up a tutorial around it. I first want to settle if their are any memory management problems in this code. [import]uid: 12108 topic_id: 4425 reply_id: 14460[/import]
I love programming when I’m being really productive, so Lua is like crack to me. Python was my favorite language for this very reason, but I think I may have a new favorite. [import]uid: 12108 topic_id: 4425 reply_id: 14479[/import]
Using that there seems to be a tiny leak when switching scenes. Every time you go to a level and then back to the menu, there’s about 4kb more memory consumed than last time on the menu. As pointed out above, my first guess here is that I’m removing the buttons wrong and that is causing a leak, so the first thing I’m going to try now is removing the buttons and seeing if the leak is still there.
Once I sort out this small leak I’m going to write up a tutorial about this methodology and post it in Code Exchange.
ADDITION: Alright well there’s definitely memory leaks from the buttons because after removing all the children using this line the memory usage goes down
for i=self.button.numChildren, 1, -1 do self.button[i]:removeSelf() end
I still have some memory leaking but clearly I’m going in the right direction. It is so odd to me that I can’t find any descriptions anywhere about how to remove buttons; surely I’m not the first person who’s needed to remove buttons in Corona?
ADDITION2: I eventually tracked down the remaining tiny memory leak to addBody() commands as described in that other thread. Now I’m curious if this leak happens on device too or only affects the simulator, but unfortunately I am unable (or at least don’t know how) to check that.
This may be a bug in Corona that’s simply not been noticed before because the leak is so tiny. Anyway, because the leak is so tiny and because this seems to be a bug in Corona itself and not my code, I think I will go ahead and post this to Code Exchange as a tutorial about one simple approach to OOP. [import]uid: 12108 topic_id: 4425 reply_id: 15181[/import]
The simplest change, would be to stuff a pointer to your shipTable in the display object’s table, which will be available as event.target.shipTable:
shipTable[i].shipGraphic.shipTable = shipTable[i]
Alternately, you could use a closure if you don’t want to sully up someone else’s table:
shipTable[i].shipGraphic:addEventListener( "touch", function(event)
return touchShip(event, shipTable[i])
end )
--8
local touchShip = function( event, shipTable )
if "ended" == event.phase then
print("We touched " .. shipTable.name .. "!")
end
end
Inheritance is overrated; prefer composition wherever it makes sense. [import]uid: 57138 topic_id: 4425 reply_id: 35173[/import]
I’ve started to think inheritance is overrated too but note that the approach I took has a lot more runtime flexibility than what you normally think of as “inheritance,” so it may be worth looking at my code. In the comments of my Code Exchange post I discussed this with a few people.
Specifically, I took advantage of Lua’s type flexibility (ie. there are no types) and first-class functions to do a decorator methodology without all of the scaffolding you usually need for that sort of design pattern. For example, my “multiple inheritance” example isn’t really creating a new class, but rather applying two different decorators to one object.
While this isn’t the only difference, a major advantage of composition over inheritance is the runtime flexibility composition gives you. Building objects using decorators also gives you that kind of flexibility. You aren’t locked in to a complex lineage of functionality, you just stick functionality modules onto objects on the fly. [import]uid: 12108 topic_id: 4425 reply_id: 35293[/import]