Why multiple sprites respond to a single TouchDown event?

Hello, I have two imagesprites in a canvas in a way that the first one (the smaller) overlaps partially with the second one (the larger).

I have set z=2 for the smaller and z=1 for the larger, so that the smaller is always drawn on top.

Everything fine until this point. However, when I tap on the screen, both sprites respond to the TouchDown event at the same time. I would expect that only the sprite on top would process the event. Also I wonder if the App Inventor engine calls the TouchDown function of the sprites in a specific order which depends on the z coordinate, or is just randomly.

Any hint on how could I accomplish that only one the upper-sprite TouchDown function is executed?

Thank you.

Please provide a more detailed explanation of what you are trying to achieve,
what you have done so far, what works, what doesn’t work…

Please show your relevant blocks,
if relevant, your data or lists,
screenshots of the Designer screen or app in action,
so we can see what you are trying to do…

Right Click in Blocks Editor and select “Download Blocks as Image”
for the best image of your blocks.

I tried this with Balls, and the lowest (1) Z got the one and only touchDown event at
their intersection.

cannibalism.aia (2.5 KB) Capture

Unfortunately, the docs at http://ai2.appinventor.mit.edu/reference/components/animation.html#Canvas
say nothing about which direction of the Z influences touch priority.

By the way, if you do dragging, you should read

ABG, I appreciate the examples provided! Specially, I was surprised to see that the mechanism to “protect against sprite cannibalism” implemented in the Puzzles example is exactly the same that I implemented in my app. It took me 3 days work to find the right solution after trying different strategies :wink:

I am attaching my own example FriedEgg to showcase the issue that I was trying to explain. The difference I can realise against the Balls example is that it is using the Any ImageSprite.TouchDown procedure. However, I do not understand why in the Balls example only one sprite receives the event, while in this case all the sprites receive the event.

Please note that the order of the notifications you can see on screen is in reverse order, as every time that a MessageDialog is popped up, it is covering the preceding ones. From my experience, I always noticed that the sprites with lower Z will receive the event first. In this specific case: Plate (Z=1), Egg (Z=2), Fork (Z=3). But of course my conclusion does not have any scientific base.

I still would be very interested in receiving only one single event for the sprite on top, i.e. the Fork. Once the Fork is moved away, then I would expect that the Egg receives the event. And finally, if the Egg is moved away as well, the Plate would receive the event.

I hope now it is easier to understand what I meant.

Thanks



FriedEgg.aia (251.6 KB)

The problem is with your instrumentation,
the message boxes stack.

See this sample with your Sprites and a log list …
(video demo at https://www.loom.com/share/1e2018b8e5e04875bc97c1bfb3857ee4)

Capture FriedEggABG.aia (252.8 KB) log when any ImageSprite TouchDown when btnClear Click

1 Like

ABG, thank you for the improvements performed on the example. Really nice!

So you confirm that the issue with the duplicated events exists. Or maybe it is not an issue, if someone can confirm that it was designed to work in this way.

Then we only need to know why in the Balls example above, only one sprite receives the event and not the two.

Best regards,
David

Unfortunately, I can't remember where this has been discussed before.

A quick look at original materials in the free book does not help either.

I would program pessimistically, applying the same global variable technique to TouchDown as was used to Dragged, to capture the first Sprite component touchedDown, holding it until TouchUp.

ABG, thanks again for your help.

I tried to develop a pattern so that anyone having the same needs that me can use it in their projects. I hope you like it, even when the number of blocks in the end has been greater than I had expected :sweat_smile:

In summary, I accumulate all the TouchDown events in a list. 100 milliseconds after the first event, I purge the events in the list and I choose only the one with the greatest Z. Finally, I execute a “false” AnyImageSpriteTouchDown procedure that works exactly as I needed. If you would like to use this pattern, here is where you would insert your blocks.

In the screenshot, you can see that when the user touches the spikes of the fork (it is the exact coordinates where the 3 sprites overlap), only the fork processes the event.

Note that this pattern is thread-safe only by the fact that AI2 uses a single-threaded model, see this paper: EVENTS-FIRST PROGRAMMING IN APP INVENTOR. Otherwise, I would have not known how to protect the list variable with mutual exclusion (I imagine this is not possible in AI2).

Regards,
David



FriedEggV2.aia (254.7 KB)

1 Like

Thanks for posting, it’s another tool for our toolbox!

Both balls should receive touchdown events if intersection of two balls is touched. The behavior is by design. And event for the one with lower Z value should fire first. @ABG I think your screen was full when you touched the intersection of two balls and there was not enough space to show the touchdown event for the ball on top.

Yours is the first reply from MIT I've seen on this topic.
Are you up to filling in the hole in the doc page for Canvas, Ball, Sprite regarding Z order and multiple Event order?

Thank you very much. That was a great help. I have been building an app involving 7 ball sprites on 7 different levels and when they overlapped confusion reigned. Now they work fine since I have implemented your solution. Well done.