Just adding to my previous comment, what I meant was is it OK to broadcast small detail? For example in Ardentkids blog he has an example where the mouse broadcasts that he has appeared, would it be OK to extend this so that he broadcasts his X and Y positions so that the cat knows where he is? Not making a game myself, I am just trying to sort things out in my head… Thanks… [import]uid: 184705 topic_id: 36309 reply_id: 144554[/import]
Hi Craig,
i’m glad that you found everything useful.
for your question, using events is the way event-driven applications communicate, and Corona SDK is an event-driven framework. as such, you should think about using events whenever you can.
consider the Runtime event “enterFrame”. if you “subscribe” to this event then your callback is going to get called on every new frame which could be 20-60 times per second !
also you can pass around as much information as you like, you just need to put it inside of the custom event structure:
local custom\_event = {
name="button\_limit\_event", -- having 'name' is the most important part
message = "this is the big message", -- strings
reference = self, -- other objects
color = { 255, 168, 158 } -- tables
}
cheers,
dmc [import]uid: 74908 topic_id: 36309 reply_id: 144579[/import]
Hi Craig,
This doesn’t answer your specific question, but have you read and worked through the recent Lua-OOP methodology by Omid Ahourai? I know that he put a considerable amount of work into writing up and detailing this, but I haven’t tested it myself. Anyway, here’s the link:
Best regards,
Brent [import]uid: 200026 topic_id: 36309 reply_id: 144286[/import]
Thanks Brent, I had looked at this tutorial earlier in my travels but it was too confusing… However I decided to follow your advice and look at it again… I have found it much easier to consume since having ago at Jonathan Beebe’s tutorial, the concepts don’t seem so foreign to me…
Thanks again…
PS Can anyone tell me what “…” means in line 10 of enemy.lua [import]uid: 184705 topic_id: 36309 reply_id: 144389[/import]
hi Craig,
to answer your question, using a single function to remove your buttons is fine. as a good rule of thumb, objects should be created and destroyed at the same “context level” in an app. you have done this in your code example by creating and destroying the buttons at the same level, ie, in main.lua at the App level, so this is good.
however, to promote better programming practices, this function shouldn’t be global. currently destroyButtons() is called from within a button object thus must be global. that breaks OO because you have given your buttons an “awareness” of their parent or surroundings which they shouldn’t have. in OO, the button class should only know about its world and nothing else.
so what we need to do is just improve upon how the destroyButtons() is called.
enter events and listeners
probably the biggest benefit of events is to “decouple” different parts of an application. meaning we can still have communication, but if no one is listening then it doesn’t matter because nothing is going to break.
in your case we can create a custom event to achieve the same effect as the global method call, improve encapsulation within the app, and increase the re-usability of your button objects. win, win, win !
note that only Corona objects can be used to broadcast events. so the challenge in setting this up with your button class is that the Corona object (the newRect) isn’t at the top level of the button object, but rather located at the property ‘myRectangle’. so you have to take this into consideration.
here is your code re-worked. i have slightly moved around some of the code and added comments.
[lua]
– main.lua
local buttons = require(“button”) – require button class
local allButtons = {} – table to hold all the buttons
– this function isn’t a bad idea, but don’t think of it as global
– in fact, let’s make it local to force correct programming
– we need to pre-declare this because of removeEventListener()
local destroyButtons
destroyButtons = function()
print( “got button limit event, destroy all buttons” )
for i = #allButtons, 1, -1 do
local button = allButtons[#allButtons]
– must use the Corona object !!
button.myRectangle:removeEventListener( ‘button_limit_event’, destroyButtons )
button:kill()
allButtons[#allButtons] = nil
end
allButtons = nil
end
– this function to explicitly “show” that there is balance in the app.
– ie, create and destroy now have equal counterparts at this level
local createButtons = function()
for t = 1, 3 do --loops to create buttons
for i = 1, 3 do
local button = buttons.new(i * 55, t * 55) --create button
allButtons[#allButtons + 1] = button
– initialize, add the button listener
button:init()
– listen for button limit, must be on Corona object !
button.myRectangle:addEventListener( ‘button_limit_event’, destroyButtons )
end
end
end
createButtons()
[/lua]
[lua]
– button.lua
local button = {}
local button_mt = { __index = button }
local function myRectListener (event, self) – button listener
self.counter = self.counter + 1
self.myRectangle.strokeWidth = self.myRectangle.strokeWidth + 1 – do something with the counter
print(self.counter)
– difference here is that we’re creating a custom event
– to send out when our limit is reached and NOT calling
– the destroyButton() function directly.
if self.counter == 4 then
print (“Our limit has been reached, tell someone”)
– create our custom event
local e = {
name=“button_limit_event”
}
self.myRectangle:dispatchEvent( e )
end
end
function button.new(xloc,yloc)
local button ={}
button.myRectangle = display.newRect(xloc, yloc, 50, 50)
button.myRectangle.strokeWidth = 1
button.myRectangle:setFillColor(140, 140, 140)
button.myRectangle:setStrokeColor(180, 180, 180)
button.counter = 0 – counter to store how many times the button has been pressed
return setmetatable( button, button_mt )
end
function button:init()
self.myRectangle:addEventListener(“tap”,function(event) myRectListener(event,self) end) – add a lister to button
end
function button:kill()
self.myRectangle:removeEventListener(“tap”,function(event) myRectListener(event,self) end) – remove the listener
self.myRectangle:removeSelf()
self.myRectangle = nil
end
return button
[/lua]
note that i didn’t call the custom event “destroy_buttons”, because in a way that also implies that the button class knows what is supposed to happen when it sends the event. the issue is that some other app could re-use this button class but want to interpret the action of the event differently, ie, NOT delete the buttons. so, events should only state the facts of what happened.
a concrete example of this is the “tap” event on a Corona object. the event isn’t called “play_sound” because that’s just an action that the higher-level app will perform once it receives the event. the base event is the button saying “hey, someone just tapped me”. that’s it. playing a sound is one action on the event. another app could change the color of the background, or get JSON data from a server.
this is a small detail, but i think helpful when architecting software, especially if you are others are supposed to re-use parts of the code.
cheers,
dmc
ps, the removeEventListener() in your button class won’t actually work. you should read this thread to find out why.
https://developer.coronalabs.com/forum/2013/01/26/advanced-oop-removeeventlistener-question
[import]uid: 74908 topic_id: 36309 reply_id: 144452[/import]
the three dots in the method call represents a variable number of arguments to a function. the dots at line 10 are related to the dots at line 7. ie, new(…) is accepting a variable number of args, and instance:initialize(…) is just passing them along, whatever they may be.
[lua]
– accept a variable number of arguments, using ‘…’
function myMethod( … )
– pass our incoming args to another method
– we don’t know what they are or how many
anotherMethod( … )
end
[/lua]
there is more information here:
http://www.lua.org/pil/5.2.html
cheers,
dmc [import]uid: 74908 topic_id: 36309 reply_id: 144455[/import]
WOW… Thank you so much… I have just read about custom events in Ardentkids blog, and was wondering if these might be used… It is awesome that you took the time to redo my code, I am really ‘starting’ to get an idea of how it works in Corona/Lua…
Do these custom eventlisteners have much overhead? Is it OK to due them for everything, or should they be saved for bigger tasks?
Thanks heaps… Really appreciate it!
Craig [import]uid: 184705 topic_id: 36309 reply_id: 144498[/import]
Just adding to my previous comment, what I meant was is it OK to broadcast small detail? For example in Ardentkids blog he has an example where the mouse broadcasts that he has appeared, would it be OK to extend this so that he broadcasts his X and Y positions so that the cat knows where he is? Not making a game myself, I am just trying to sort things out in my head… Thanks… [import]uid: 184705 topic_id: 36309 reply_id: 144554[/import]
Hi Craig,
i’m glad that you found everything useful.
for your question, using events is the way event-driven applications communicate, and Corona SDK is an event-driven framework. as such, you should think about using events whenever you can.
consider the Runtime event “enterFrame”. if you “subscribe” to this event then your callback is going to get called on every new frame which could be 20-60 times per second !
also you can pass around as much information as you like, you just need to put it inside of the custom event structure:
local custom\_event = {
name="button\_limit\_event", -- having 'name' is the most important part
message = "this is the big message", -- strings
reference = self, -- other objects
color = { 255, 168, 158 } -- tables
}
cheers,
dmc [import]uid: 74908 topic_id: 36309 reply_id: 144579[/import]