Help to synchronize Screen Updates and Events

Hi,

I have just recently started to work with the SDK and I have been banging my head over a design detail I just can’t seem to get right. I would really appreciate if someone could point me into the right direction with this.

In short:  How do you ensure screen updates if lots of events are flooding your app?

Details:   :unsure:

Basically I am trying to properly orchestrate touch events and screen updates. In my test code I have created a grid of spites (8x8) on the screen and capture the touch event on each of them. As the user is moving his finger across the screen, I test for a few conditions and if they are fulfilled, change frames on the spites.

This works all fine in the simulator but fails on an iPhone 4s. I instrumented the code and suspect that the problem is actually quite simple. I simply spend too much time handling the event and directly calling my spite:setFrame. As it seems the screen won’t get updated as I receive so many events that I spend all time in my own code. I also noticed that my enterFrame events are only called twice per second if swiping heavily. If I stop swiping over the screen, the screen updates catch up after a fraction of a second.

Pseudo code:

... local function changeSprite(sprite) sprite:setFrame(...) end local function testValidMove() -- takes microsecond in simulator, several ms in the device ... end function onTouch(event) if event.phase == "began" or event.phase == "move" do if (testValidMove(event.target)) do changeSprite(event.target) end end ... end

As it seems even function calls or simple if statements take about 20x as long as in the simulator and my code uses too much time in own code and gets flooded by the touch events if moving the finger fast across the screen.

Are there any design patterns in Corona to deal with requirements like this? I couldn’t find any. I was looking at timer.performWithDelay or other means to detach from the UI thread but so far I had no luck.

BTW I was also trying to find ways to throttle the simulator to be closer to the device experience but didn’t come across anything using the search. Surely there is some way to do that?

Thanks!

Hi @Danz,

As you indicate, you’re probably detecting a vast number of input points based on the “moved” event (it should be “moved” by the way, not “move”). This floods the detection system and slows the app down. What I suggest is that you find a way to filter out which events are processed… for example, if the sprite (on the grid) receives a touch event of either “began” or “moved”, you process that sprite change only once. Probably the best way is to simply set the sprite to “isHitTestable = false” after it receives a hit, which will void any further hits on it. Now, you’d have to re-establish sensory input on it after the “swipe” was done, possibly by detecting when the touch leaves the screen (“ended” phase) and then loop through all of your objects and set them back to “isHitTestable = true” so they sense the next swipe.

This is just one approach, but my point is, try to find some clever way to limit the touch events on the sprites and you should have no performance slag at all.

Hope this helps,

Brent

Thanks Brent,

I currently manually test and track if the sprite was already activated. I didn’t try isHitTestable as from the documentation it doesn’t look like it does what I need:

Allows an object to continue to receive hit events even if it is not visible. If true, objects will receive hit events regardless of visibility; if false, events are only sent to visible objects. Defaults to false.

Will further try throttling the events though.

Thanks,

Daniel

Hi Daniel,

Oops, you’re right… there’s that little gotcha with the “isVisible” thing. In that case, another option would be setting a custom property on the sprite like “canTouch”, or maybe better yet, just temporarily remove the event listener from it entirely, and re-establish it afterward.

Brent

Hi Brent,

Removing the event listener is probably not an option as I need to track if the user is swiping back over the same sprite. I already use custom properties to track the state of the object. That said I did notice that it takes almost 25ms (on the device) to handle all the logic between my touch detected and deciding if it is a valid touch. 

I am sure I can go now and refactor the code a fair bit to simplify that part. Didn’t realize it is going to be so performance critical.

Thanks for clarifying that this is the correct approach and I didn’t miss major design concepts of the SDK!

Daniel

Hi @Danz,

As you indicate, you’re probably detecting a vast number of input points based on the “moved” event (it should be “moved” by the way, not “move”). This floods the detection system and slows the app down. What I suggest is that you find a way to filter out which events are processed… for example, if the sprite (on the grid) receives a touch event of either “began” or “moved”, you process that sprite change only once. Probably the best way is to simply set the sprite to “isHitTestable = false” after it receives a hit, which will void any further hits on it. Now, you’d have to re-establish sensory input on it after the “swipe” was done, possibly by detecting when the touch leaves the screen (“ended” phase) and then loop through all of your objects and set them back to “isHitTestable = true” so they sense the next swipe.

This is just one approach, but my point is, try to find some clever way to limit the touch events on the sprites and you should have no performance slag at all.

Hope this helps,

Brent

Thanks Brent,

I currently manually test and track if the sprite was already activated. I didn’t try isHitTestable as from the documentation it doesn’t look like it does what I need:

Allows an object to continue to receive hit events even if it is not visible. If true, objects will receive hit events regardless of visibility; if false, events are only sent to visible objects. Defaults to false.

Will further try throttling the events though.

Thanks,

Daniel

Hi Daniel,

Oops, you’re right… there’s that little gotcha with the “isVisible” thing. In that case, another option would be setting a custom property on the sprite like “canTouch”, or maybe better yet, just temporarily remove the event listener from it entirely, and re-establish it afterward.

Brent

Hi Brent,

Removing the event listener is probably not an option as I need to track if the user is swiping back over the same sprite. I already use custom properties to track the state of the object. That said I did notice that it takes almost 25ms (on the device) to handle all the logic between my touch detected and deciding if it is a valid touch. 

I am sure I can go now and refactor the code a fair bit to simplify that part. Didn’t realize it is going to be so performance critical.

Thanks for clarifying that this is the correct approach and I didn’t miss major design concepts of the SDK!

Daniel