Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Design Talks - Custom Runtime Events
Started by roaminggamer May 31 2018 11:45 AM

* * * * * 3 votes
42 replies to this topic
[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,594 posts
  • Corona SDK

In this post I'd like to talk about what I call 'custom' Runtime Events.
 
This is an example of what I mean:

local coinsLabel = display.newText( "0", display.contentCenterX, 100 )

function coinsLabel.onCoins( self, event )
   self.text = event.coins
end; Runtime:addEventListener( "onCoins", coinsLabel )

function coinsLabel.finalize(self)
   Runtime:removeEventListener("onCoins", self)
end; coinsLabel:addEventListener("finalize")

Later, in any module or un-connected piece of code, I can do this to update the 'coinsLabel':
 

Runtime:dispatchEvent( { name = "onCoins", coins = 20 } )

After this code runs, the 'coinsLabel' will show 20.

Note: The 'finalize' listener is used to ensure the Runtime event listener is removed when the label is destroyed. Otherwise, the 'dead' object might receive 'onCoins' events incorrectly at a later time causing a crash or error.

 

 
SSK2 Sidenote
Please note, I don't actually write my code as shown above.  Instead, I use SSK2 helpers: 
https://roaminggamer.github.io/RGDocs/pages/SSK2/globals/#runtime-improvements
 
Using SSK2, my code really looks like this:

local coinsLabel = display.newText( "0", display.contentCenterX, 100 )

function coinsLabel.onCoins( self, event )
   self.text = event.coins
end; listen( "onCoins", coinsLabel )

function coinsLabel.finalize(self)
   -- SSK2's "ignoreList()" removes all listed events at once and safely
   ignoreList( { "onCoins", "enterFrame" }, self ) 
end; coinsLabel:addEventListener("finalize")

... then later

post( "onCoins", { coins = 20 } ) -- shorthand for "Runtime:dispatchEvent()"

This code is not significantly different, but I find it much easier to type and easier to read.  Additionally, the use of SSK2's ignoreList() function is safer and better than a series of calls to Runtime:removeEventListener().

 

 

 

Why Do I Use Custom Events?

So, what is the big deal?  

 

The big deal (for me) is this allows me to:

  • Make much of my non-core code 'event' based.
    • Core code is basically game logic.
    • Non-core is stuff like scoring, playing sounds, dispatching ads requests, etc.
  • Keep my code separated.  

The last reason is most important.  As I noted above, once the event listener is set up, code anywhere else in my game can dispatch an event and it doesn't have to know about the label.  There is no need for a reference to it or any such ugliness.  Simply dispatch the event and 'Violla!' the label is updated.

 

While the application of this concept to a 'score label' is vaguely interesting, it becomes much more interesting when applied to complex pieces of code like your ad manager, the sound manager, etc.

 

I will talk more about ads later, but for completeness I'll give a more interesting example of sound code now.

 

SSK2 Sound Manager Example

 

SSK2 includes a basic "Sound Manager".  It automatically listens for the event 'onSound'

 

I generally use it like this in my games:

-- Register sounds; Uusually in main.lua
ssk.soundMgr.addEffect( "coin", "sounds/sfx/coin.wav")
ssk.soundMgr.addEffect( "gate", "sounds/sfx/gate.wav")
ssk.soundMgr.addEffect( "died", "sounds/sfx/died.wav")
...

Later, I can dispatch sound events anywhere I need them:

post( "onSound", { sound = "coin" } )

As you can probably tell, this equates to super easy sound management and coding.

 

 

 

What About You?

I'd like to close this (long) post with some questions for you, the readers:

 

1. Do  you use 'custom' events?

 

2. If, "Yes", what do you use them for?

 

3. If, "No", are you thinking about using them now?

 

Please answer if you can and share any other thoughts you may have.  


Edited by roaminggamer, 31 May 2018 - 11:49 AM.


[TOPIC: post.html]
#2

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

Not yet but i get your points and might for my next project



[TOPIC: post.html]
#3

cyberparkstudios

[GLOBAL: userInfoPane.html]
cyberparkstudios
  • Contributor

  • 573 posts
  • Corona SDK

1. Yes. I do now, after reading a while back something you must have posted about custom events..  until then I knew nothing about them, but as soon as I saw what you posted about them,  I thought, this could be a great tool.  I just wish I knew about these when I made my tower defense game; way back when.

 

2. I recently put a game on google play, my last game I published, called 'Mad Pirates'. A  slot machine app.  I use them extensively in that game.  And I will have to look but I am fairly sure I also used them in another game I am 'days' away from publishing.

 

Had to do a lot of 'hack code' and work a rounds in my 'Tanks & Towers' tower defense game to communicate between all the objects created by a hierarchy of modules. The custom events would have saved a lot of time and frustration... if I had known about them back then.

 

'finalize' is something I have 'stupidly' avoided for some unknown reason. I have it on my very long list of 'to follow up on' stuff, because I wasn't sure of it's exact purpose and proper use.  Your note above about finalize, is very helpful. thanks.

 

I have not given it a lot of thought to it, but I do wonder, what is the breaking point.. at what point is there too many custom events.

 

Bob



[TOPIC: post.html]
#4

SGS

[GLOBAL: userInfoPane.html]
SGS
  • Corona Geek

  • 2,120 posts
  • Corona SDK

I use a similar mechanism in DC2.  So I show an overlay (my select a building screen) which allows the player to drag a building off a ribbon.  This then terminates the overlay and then in my main scene I create a new object that is the building they dragged in the overlay.  To make this seamless I dispatch an event ( a begin touch) to the new created object so it appears like you've dragged an image from the overlay into the parent scene.

 

Note: to achieve this I've had to make major changes to the open source storyboard code and this is, AFAIK, impossibile in composer.



[TOPIC: post.html]
#5

ponywolf

[GLOBAL: userInfoPane.html]
ponywolf
  • Contributor

  • 273 posts
  • Corona SDK

It actually a little cleaner using the colon ":" notation, instead of passing self...  I use this almost exclusively and add enterFrame listeners to the same object.  I'll also use a new() function to return an instance so you can spin up as many coinLabels as you want.

local coinsLabel = display.newText( "0", display.contentCenterX, 100 )

function coinsLabel:onCoins( event )
   self.text = event.coins
end

Runtime:addEventListener( "onCoins", coinsLabel )

function coinsLabel:finalize()
   Runtime:removeEventListener("onCoins", coinsLabel)
end

coinsLabel:addEventListener("finalize")


[TOPIC: post.html]
#6

ponywolf

[GLOBAL: userInfoPane.html]
ponywolf
  • Contributor

  • 273 posts
  • Corona SDK

For fun, here's an example of a "life bar" module that can have multiple instances and has functions like damage() and heal()... Adding EventListener code to this would be pretty easy...

-- Heart bar module

-- Define module
local M = {}

function M.new( options )

	-- Default options for instance
	options = options or {}
	local max = options.max or 3
	local spacing = options.spacing or 8
	local w, h = options.width or 64, options.height or 64

	-- Create display group to hold visuals
	local instance = display.newGroup()
	local hearts = {}
	for i = 1, max do
		hearts[i] = display.newImageRect( "scene/game/img/icon/heart.png", w, h )
		hearts[i].x = (i-1) * ( (w/2) + spacing )
		hearts[i].y = 0
		instance:insert( hearts[i] )
	end
	instance.count = max
  instance.anchorChildren = true

	function instance:damage( amount )
		instance.count = math.min( max, math.max( 0, instance.count - ( amount or 1 ) ) )
		for i = 1, max do
			if i <= instance.count then
				hearts[i].alpha = 1
			else
				hearts[i].alpha = 0.2
			end
		end
		return instance.count
	end
  
  function instance:alterMax(newMax)
    local nextHeartIndex = #hearts+1
    hearts[nextHeartIndex] = display.newImageRect( "scene/game/img/icon/heart.png", w, h )
		hearts[nextHeartIndex].x = (nextHeartIndex-1) * ( (w/2) + spacing )
		hearts[nextHeartIndex].y = 0
		instance:insert( hearts[nextHeartIndex] )
    max = newMax
	end
  
  function instance:fullHeal()
    instance.count = max
    for i = 1, max do
      hearts[i].alpha = 1
    end
	end

	function instance:heal( amount )
		self:damage( -( amount or 1 ) )
	end

	function instance:finalize()
		-- On remove, cleanup instance 
	end
	instance:addEventListener( "finalize" )

	-- Return instance
	return instance
end

return M


[TOPIC: post.html]
#7

sporkfin

[GLOBAL: userInfoPane.html]
sporkfin
  • Contributor

  • 635 posts
  • Corona SDK

Great topic @roaminggamer

 

I am not currently using custom events but I plan to start. . . now!



[TOPIC: post.html]
#8

maximo97

[GLOBAL: userInfoPane.html]
maximo97
  • Contributor

  • 231 posts
  • Corona SDK

I used them in the past. They look fantastic and allow us to save code.

My thoughts are only two:

 

1.Do they affect performance?

2.Entering too many could make the code less understandable(I do not think, however, another opinion is always a pleasure)



[TOPIC: post.html]
#9

remiduchalard

[GLOBAL: userInfoPane.html]
remiduchalard
  • Contributor

  • 306 posts
  • Corona SDK

Hello,

 

I have read somewhere but I don't remember where. We can create listener on value. (a function is call when a value is updated).

If someone has seen something like this, can he reply in this topic?

 

1 - I never used custom listener, all my function, all my value can be access from everywhere (expect for useless value) but it's not a good solution if many people work on the same code.

 

2 - I will use custom listener because you convince me and I discover that with this topic. It will help me to win a lot of time. To dispatch information it's look very interesting 

 

 

Can someone tell me if both listener we be call with this event?

local coinsLabel = display.newText( "0", display.contentCenterX, 100 )
function coinsLabel:onCoins( event )
   self.text = event.coins
end ; Runtime:addEventListener( "onCoins", coinsLabel )

local myObject2={}
function myObject2:onCoins( event )
   print("Something")
end ; Runtime:addEventListener( "onCoins", myObject)

Runtime:dispatchEvent( { name = "onCoins", coins = 20 } )


[TOPIC: post.html]
#10

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

There is one aspect to all of this i'd like to mention, time spent coding.

 

Every coder has his own habits and techniques, and while it is great to learn new techniques and see new ways to do things, it can come at the cost of spending more time coding. Some more complex setups can make the code less readable for the given coder, for others maybe not. 

 

What I try to say is that unless the new way brings better performance and/or solves a problem, sometimes its just faster to code the way we are used to, often at the cost of typing more code, but not neccessarily slower development or performance.

 

In the end its about the product we make, not the code structure in itself.

 

I am sure many much more proficient than me can detect and fine tune methods and techniques to squeeze out extra performance but its not always worth if the products runs fine on all required devices. Not every project pushes device limitsand needs to be coded in the most efficient way.

 

There I said it...waiting for the s*storm  :)



[TOPIC: post.html]
#11

remiduchalard

[GLOBAL: userInfoPane.html]
remiduchalard
  • Contributor

  • 306 posts
  • Corona SDK

Here it comes  :)

Depend of what game you make. At the beginning of my project a TD, with 30 units on the map, the game run at 5fps at the end of the dev, I add a lot of effects, interactions and a lot of other stuf the game can run at 30fps with a few hundreds units on the map

 

I agree that the most of the time we don't care about code optimization. But for critical function who are call thousand of time per seconde need to be optimize. To keep a good productivity, we have to keep in mind how many time it will be call, does improvement provide a major time execution?



[TOPIC: post.html]
#12

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,373 posts
  • Corona SDK

i'd favor "judicious use" of such techniques (either Runtime.dispatchEvent or a DIY pub/sub system).

 

there's a decision point in here somewhere, else you run the risk of making EVERYTHING message-based and calling NOTHING directly.  (though, heck, maybe some would even prefer that)

 

i'd probably not use it for the "coin label" scenario, instead i'd have a "hud.coins" class/instance and just call it's "update" method directly, as the code that acquires coins is probably probably relatively "close" to the code that owns the hud in the hierarchy, and ought to have direct access to it.

 

but i might use it for something like a long-running (async) network request - say i'm querying a NIST server for real time, or awaiting the result of an IAP purchase, then broadcast with result when it returns, for whoever wanted it - potentially cleaner than keeping a reference to some callback function fe.

 

in short, i'd consider a message system when the publisher can't be reasonably expected to "know" who the subscriber(s) are, otherwise it's just unnecessary overhead.



[TOPIC: post.html]
#13

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,594 posts
  • Corona SDK

I used them in the past. They look fantastic and allow us to save code.

My thoughts are only two:

 

1.Do they affect performance?

2.Entering too many could make the code less understandable(I do not think, however, another opinion is always a pleasure)

 

1. Everything has a performance impact and this could to if not used carefully.   That said, I've tested into the thousands of distinct listeners that just wake and do nothing as a test and saw no problems.  So, the mechanism itself is pretty efficient.

 

2. I would disagree with this point.  Properly architected, a game using this technique is easier to understand for me.   As long as you avoid bad names, cascading events, and over kill I think you'll be fine.

 

Note: @davebollinger has some great insights above (below your post) on this that I agree with.



[TOPIC: post.html]
#14

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,594 posts
  • Corona SDK

Answers INLINE

 

 

Hello,

 

I have read somewhere but I don't remember where. We can create listener on value. (a function is call when a value is updated).

If someone has seen something like this, can he reply in this topic?

 

Lua allows you to watch variables an I I can find the code for it I'll post back a link here.  As I recall this involves some smart use of the metamethods _index and _newindex (as well as perhaps others).

 

1 - I never used custom listener, all my function, all my value can be access from everywhere (expect for useless value) but it's not a good solution if many people work on the same code.

 

2 - I will use custom listener because you convince me and I discover that with this topic. It will help me to win a lot of time. To dispatch information it's look very interesting 

 

I suggest doing some small experiments before pushing this into a major project.

 

 

Can someone tell me if both listener we be call with this event?

 

Yes, both coinsLabel and myObject2 will both 'hear' the event and process it.

local coinsLabel = display.newText( "0", display.contentCenterX, 100 )
function coinsLabel:onCoins( event )
   self.text = event.coins
end ; Runtime:addEventListener( "onCoins", coinsLabel )

local myObject2={}
function myObject2:onCoins( event )
   print("Something")
end ; Runtime:addEventListener( "onCoins", myObject2) -- YOU HAVE A TYPO HERE; I fixed it

Runtime:dispatchEvent( { name = "onCoins", coins = 20 } )


[TOPIC: post.html]
#15

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,594 posts
  • Corona SDK

@anaquim - You are correct and I've said it before.  You should stick with what you know and are comfortable with.

 

That said, this is more of an exploratory discussion.  My hope is to learn something from other community members while sharing something about the way I do things.

 

Knowing if what I'm doing is foreign is helpful too as I hope to produce more templates, starters, etc. and if I do something that users find 'weird' I may end up not helping them or myself.



[TOPIC: post.html]
#16

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,594 posts
  • Corona SDK

Sorry for the re-quote.  I try to avoid this, but sometimes it is easier to be sure the OP knows what I'm replying to.

 

Responses INLINE

 

i'd favor "judicious use" of such techniques (either Runtime.dispatchEvent or a DIY pub/sub system).

 

Agreed.  All coding decisions and architecture should be planned and used in an informed way.  To be clear, I'm not addovating anyone change over to this, but rather trying to introduce the concept to folks, because as I expected this is quite new to many.

 

there's a decision point in here somewhere, else you run the risk of making EVERYTHING message-based and calling NOTHING directly.  (though, heck, maybe some would even prefer that)

Agreed.  This would be a terrible idea unless you are coding a simulator of some sort and then you'd probably centralize and gather messages instead of distributing them to all objects.  The  function lookup and calling overhead would start to get too high otherwise.

 

i'd probably not use it for the "coin label" scenario, instead i'd have a "hud.coins" class/instance and just call it's "update" method directly, as the code that acquires coins is probably probably relatively "close" to the code that owns the hud in the hierarchy, and ought to have direct access to it.

 

Sorry about that.  My 'coin scenario' was a terrible choice.  I don't every do things like that actually.  As you rightly point out it is a poor target for this technique.  I chose it as an example because it was familiar.  In retrospect I should have made a more realistic example.  Hopefully the sound example was more inline with meaningful and useful usage.

  :)

 

For further elaboration, I handle coins (currency) and HUDS as follows:

  • Track the coins in a common module or using persist.
  • Manually update HUDs as needed from some local game logic. 

 

but i might use it for something like a long-running (async) network request - say i'm querying a NIST server for real time, or awaiting the result of an IAP purchase, then broadcast with result when it returns, for whoever wanted it - potentially cleaner than keeping a reference to some callback function fe.

 

in short, i'd consider a message system when the publisher can't be reasonably expected to "know" who the subscriber(s) are, otherwise it's just unnecessary overhead.

I didn't understand this last part.  In this case the publisher is entirely ignorant of the subscribers.   

 

I have experimented with more-formalized and  other standalone solutions, but found them unnecessary as Runtime was perfectly capable of handling this for a reasonable number of subscribers.

 

.



[TOPIC: post.html]
#17

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,373 posts
  • Corona SDK

>>I didn't understand this last part.  In this case the publisher is entirely ignorant of the subscribers. 

 

Read my "publisher" as whoever did Runtime:dispatchEvent, read my "subscriber" as whoever did corresponding Runtime:addEventListener.  (just a habit i've adopted, as almost everyone else in the gamedev world uses pub/sub design pattern terms)

 

The useful case imo is when the "publisher" is abstracted to the degree that it doesn't "know" (ie, does not maintain state) of who originally initiated the request.  Because, otoh, if you "know" the direct path to a method, then use it.

 

Network operations make a reasonable example -- let's say you have a generic NetworkSupport module (don't care what you call it), capable of submitting network requests and returning network results on behalf any generic "customer" (ie, any random code that needs network data is a "customer" of the NetworkSupport module as "provider").

 

All the network module "knows" (internally, across an async request/receive) is it that it got a network response, no idea "who" originally requested it.  So it wants to relay it (by "publishing" a message) to whoever initiated the original request (who has "subscribed" to that topic, aka "is listening for that event" in Corona-speak).



[TOPIC: post.html]
#18

davebollinger

[GLOBAL: userInfoPane.html]
davebollinger
  • Corona Geek

  • 1,373 posts
  • Corona SDK

The  function lookup and calling overhead would start to get too high otherwise.

 

Exactly.  reductio ad absurdem:

local EntireCoronaAPIEvented = {
	requestNewRect = function(self, event)
		local rect = display.newRect(unpack(event.params))
		Runtime:dispatchEvent({ name="receiveNewRect", value=rect })
	end,
	requestNewImage = function(self, event)
		local image = display.newImage(unpack(event.params))
		Runtime:dispatchEvent({ name="receiveNewImage", value=image })
	end,
	-- et al, ad nauseum, for the entire api
}
Runtime:addEventListener("requestNewRect", EntireCoronaAPIEvented)
Runtime:addEventListener("requestNewImage", EntireCoronaAPIEvented)
-- et al, ad nauseum, for the entire api

local AGameEntityClass = {}
AGameEntityClass.__index = AGameEntityClass
function AGameEntityClass:new()
	local instance = setmetatable({},self)
	-- aka:  instance.view = display.newRect(100,100,50,50)
	Runtime:addEventListener("receiveNewRect", instance)
	Runtime:dispatchEvent({name="requestNewRect", params={100,100,50,50}})
	return instance
end
function AGameEntityClass:receiveNewRect(event)
	self.view = event.value
	Runtime:removeEventListener("receiveNewRect", self)
end

local entity = AGameEntityClass:new()



[TOPIC: post.html]
#19

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

@Dave
Now that async example makes sense and is definitivly something i will use in my current project cause not being able to just return the value on answer received can be quite a troublemaker when the app uses alot of them
Thanks!

[TOPIC: post.html]
#20

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,457 posts
  • Corona SDK

Hi,

 

This is a topic close to my heart. Almost all my projects are event driven (a throwback from my Flash days). I don't use Runtime events though, I build event dispatching directly into my modules using this technique:

 

Module:

--#############################################################################
--# Evented Module
--#############################################################################
local _M = {}

function _M:doSomething()
  self:dispatchEvent({name="SomeEvent", value=20, target=self})
end

function _M:somethingElse()
  print("Hi!")
end

return setmetatable(_M, { 
  __index = system.newEventDispatcher() 
})

Usage:

--#############################################################################
--# Contrived Evented Module Test
--#############################################################################
local eventedMod = require("eventedMod")

--add listener
local function onEvent(evt)
  print(evt.value)
  evt.target:somethingElse()
end
eventedMod:addEventListener("SomeEvent", onEvent)

--test call
eventedMod:doSomething()

--remove listener
eventedMod:removeEventListener("SomeEvent", onEvent)

---

 

Another technique is using a "master" dispatcher:

--#############################################################################
--# Main Controller
--#############################################################################
local events = system.newEventDispatcher()
local score = require("score")
local entity = require("entity")

--pass master dispatcher to modules (internals not shown)
score:init(events)
entity:init(events)

--something dispatched from entity
events:addEventListener("EntityScored", function(evt)
  --dispatch to anyone listening for the event
  events:dispatchEvent({name=evt.name, value=evt.value})
end)

-- ...

Using this technique it's simple to listen for/dispatch events from any module, anywhere, without them needing to know about each other intimately. This is of course a pseudo example.

 

Reference: https://docs.coronalabs.com/api/library/system/newEventDispatcher.html

 

-dev


[TOPIC: post.html]
#21

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

Hi dev,

Looks great and I just wish I understood it better.

Metatables and using _ before variables isnt something I have grasped yet.

Also object oriented programming using 30log, which I know you favor, is on my to do (and try to understand) list  ;)



[TOPIC: post.html]
#22

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,594 posts
  • Corona SDK

@dev - I'm out of 'likes' for the day, so...

 

LIKE :)



[TOPIC: post.html]
#23

anaqim

[GLOBAL: userInfoPane.html]
anaqim
  • Contributor

  • 770 posts
  • Corona SDK

You can have one of mine RG  :)



[TOPIC: post.html]
#24

cyberparkstudios

[GLOBAL: userInfoPane.html]
cyberparkstudios
  • Contributor

  • 573 posts
  • Corona SDK

I think having these 'design' talks are great.  The bottom line is - as it always has been - there are a dozen ways to do this or that.  There are always tradeoffs - efficiency versus time - repeatability of code - code size - etc.
 
Like all tools; use the correct tool where needed...  don't use a hammer to screw in a screw - unless of course it works. 
 
Lets try a 'very simple' example, and see what approach some may have to this :
 
1 a generic tower defense game:  10 towers and 50 enemies.
2. each enemy has a life, image, speed, and position it is on the screen, along a set of waypoints (the path).
3. each tower has an image, aim direction and firing state
4. bullets
 
Assume 3 modules (lua files)  (main.lua, tower.lua,  enemy.lua)
 
Which approach might you take:
1. use a game loop in main.lua checking each tower(object) to see if each enemy(object) is in range and each enemy to see if it is spawned, dead or at end of path. 
 
2. use game loop in main.lua but to manage a few limited things, and create enterFrame events in the tower and the enemy modules for each of the towers or enemies created. Let the objects manage themselves, at least for most things... 
If doing it this way, what method would you use to have those objects communicate back to main.lua that is managing the overall gameplay.
 
3. use only one module create all objects (towers and enemies) via tables in the main.lua, avoiding any communication issues between modules. I think this is fine, when it is a very small super simple game, but I tend to lean toward modular (pseudo oop) when a game is even a little complex.
 
4. some other approach?
 
 
note: I believe any and all the methods and ideas mentioned above, by way-more-expereinced developers then I, likely will all work fairly at the same efficiency; at least for such a simple game. But I am curios which approach (regarding custom events) some of you may think better in this type of game.
 
 
In my tower defense game I did years ago, I did not know about custom events, and I had lots of towers and enemies on screen at one time, so I had to do a fair number hacks and work arounds to keep the gameLoop manageable. I think in my case custom-events could have been helpful. I am going to re-do my tower defense game and look at using custom events.
 
Thanks RoamingGamer and to all for this helpful discussion.
 

 

Bob


[TOPIC: post.html]
#25

Develephant

[GLOBAL: userInfoPane.html]
Develephant
  • Corona Geek

  • 1,457 posts
  • Corona SDK

Hi,

 

I generally find events useful when I know that I have multiple subsystems that need to be notified. I think every programmer has their own best methods, but I am an abstraction junkie, so events are a good fit for me.

 

I don't generally use events to perform an action, rather respond to one.

 

-dev




[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]