Event Listener?

Say I was to send a message to a collection so my levels switch depending on score. Ive tried a lot of things but none of them are working, Paraphrasing ive tried things along the line of
if score == 250 then
msg.post etc…

But none of them are working. Is there a way I can setup an eventlistener or something that can track when the score does something and send a message out?

Put the check in the update function of whatever is responsible.

function update(self, dt)
    check_score()
end

or

function update(self, dt)
    if score >= 250 then
       ...
    end
end

You want to check for if score is >= 250 more likely not that it is exactly 250, and you will want a check to only send a single message.

Maybe I don’t understand where the problem is. If you post a more complex example of what’s not working we can better help.

3 Likes

You probably also only want to check for changes happening to the score, and only sending the message when such a change has brought the score over one of these levels. If the score is only incremented and this doesn’t happen for too many things, something like this could work:

function init(self)
    self.score_levels = {250, 500}
end

local notify(self, score)
    -- for each listener:
         msg.post(listener, "score_reached", {score = score})
end

local function incr_score(self, value)
    self.score = self.score + value
    local next_level = self.score_levels[1]
    while (next_level and next_level <= self.score) do
         notify(self, next_level)
         table.remove(self.score_levels, 1)
         next_level = self.score_levels[1]
    end
end
4 Likes

I would recommend to not do this check every frame but instead only check when the score is increased. Wasting cycles checking a value that rarely changes (or maybe it does?) seems like a bad idea.

3 Likes

Thanks @Pkeod @Ragnar_Svensson and @britzl. There wasnt an issue with the listener, I just wasnt sure how to go about doing one, this helped me but I have a few questions.

self.score_levels = {250, 500}
What does this line mean? Why is the 500 there?

msg.post(listener, "score_reached", {score = score})
And is the listener on its own script, or is it placed in the script that takes care of passing and receiving score info?

local function incr_score(self, value) self.score = self.score + value local next_level = self.score_levels[1] while (next_level and next_level <= self.score) do notify(self, next_level) table.remove(self.score_levels, 1) next_level = self.score_levels[1] end end
trying to understand this part as well, kind of confused.Might I also suggest this be a good topic to cover in the tuts? I dont think I seen it there the other day when I was looking, unless I overlooked. it would be nice to have one that explains how to do this!
Thanks

The self.score_levels shows you the score for two levels. Level 1 has a score of 250 and level 2 has a score of 500.

I’m not sure what you mean in your second question. If I understand the code the post is to any listener that needs to know which score is reached. Personally I would isolate the score code to a script that handles higher level things like that and send out messages based upon what happens when the score is hit.

2 Likes

so when you say it shows the scores for level 1 and 2, basically it waits for those scores to be reached on those specific levels? And is what is “next_level”? would that be a collections name?

It’s in reference to Ragnar’s code above. It sets the target score to the next score listed in the table once the previous score has been reached.

1 Like

okay im still kind of confused how the Even Listener works… Is there a basic example that will give me an idea of what I should do with my situation? I saw a few lua event listeners online, but still confused on how I should really go about making one with defold

When you add points to your score that’s when you should detect if the score is high enough, and then if it’s high enough you can do whatever else you need to do such as changing levels. Ragnar’s example is good. This answers your original question as you stated it.

Post a full example of the source you are attempting to get to work, or post a zip of entire project and say where problem is.

(Thanks @Pkeod!)

Here you go @Hakim_A, because you asked so nicely. :wink:
You essentially have three options, depending on your game and preference.

  1. The thing keeping level score is the central thing so it does not need to be sent off, it takes any decisions what to do internally. Other things send it messages to increment the score by directly addressing it. (e.g. msg.post("/my_central_thing#script", “inc_score”, {added_score = 100}) I prefer doing things in one place until I see a reason to break things apart, or know more where the game is going and what I need.
  2. The thing keeping level score knows which thing needs to be notified. In my previous example, listener would result in something like “/the_other_thing#script”.
  3. Other things register to be notified about changes to the level score, e.g. that it passed known limits like in my example. The things need to be able to address the score keeper. That would look like this:

In the thing that registers itself:

msg.post("/score_keeper#script", "register_me")

In the thing keeping scores:

function on_message(self, message_id, message, sender)
  if message_id == hash("register_me") then
    -- self.listeners was initialized to an empty table in the init function
    table.insert(self.listeners, sender) -- note that sender will be the thing that posted the message above
  end
end

Then self.listeners would be iterated in my example where it said – for each listener, just like an ordinary lua table. There is a ton of examples how to iterate tables. (hint: ipairs) Note that I intentionally chose ridiculous names so you can replace them with things that makes more sense for your situation.

2 Likes