Catching Raised Events Twice

I’ve been very busy with the development of my new game, Discbord.

One of the things I’ve had to do recently is pretty up the bare-bones GUI into something a little more attractive. Me being me, this meant creating a reusable object for text-based buttons. It also meant using Corona’s custom events to take care of signalling to the app when a button has been tapped. The problem was that I found the events were being “captured” by event listeners in different storyboard* scenes.

Let’s say I had a main menu with 3 text buttons to click on; Classic, Options, Help. The main menu has an event listener that listens for the event the buttons raise when clicked on. As the event is raised against the Runtime object, it means that the one event listener in the main menu catches the events that any of the buttons fire. In order for me to know which button has raised the event I added a “command” item to the event table returned to the listener. I then interrogate this value to know which button was pressed. The code below shows how the event listener in the main menu works.

local function textButtonTapped(event)

   if event.command == "onClassic" then
      -- Open Classic Menu
   end

   if event.command == "onOptions" then
      -- Open Options screen
   end

   if event.command == "onHelp" then
      -- Open Help screen
   end

   return true
end

Let’s assume the Classic button was clicked. This screen has some options on it too, for which I use more text-based buttons. Again, I have an event listener set up against the Runtime object.

local function textButtonTapped(event)

   if event.command == "onClassic" then
      -- Run the game in Classic mode
   end

   if event.command == "onBack" then
      -- Go back to the main menu screen
   end

   return true

end

The problem I was having was that the main menu screen would trap the event when the Classic button was tapped, but as soon as the Classic screen was displayed the event would also get trapped by that screen’s textButtonTapped event.

It took an age for me to realise what was happening. In the first screen, when the textButtonTapped event fires, the code to handle moving to a new screen runs and the “return true” code is never fired. This meant that as far as Corona was concerned the event hadn’t been handled. Because of this, when the Classic screen appeared it also immediately trapped the event.

The solution I used was to use timers to run the code I wanted. By using a timer it gave Corona the chance to continue execution to the “return true” statement and so Corona considered the event handled.

local function handleOnClassic()

   -- Open Classic menu

end

local function onTextTapped(event)

   if event.command == "onClassic" then
      -- Using a timer means that Corona continues execution
      -- after the line below is executed
      timer.performWithDelay(15, handleOnClassic, 1)
   end

   -- This code is now run as execution has continued to this point
   return true

end

This solved my problem and stopped Corona from catching one event multiple times.

I’m now investigating whether my use of the Runtime object is the best method or not. But whether it is or not, I still learned a valuable lesson about how Corona handles events.

* I mean Corona’s built-in storyboard system.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: