Skip to first unread message

Christopher Steele

unread,
Apr 24, 2017, 10:52:17 PM4/24/17
to MIT App Inventor Forum
I have created a match game that everything so far seems to be working great. However, I just ran into this issue that is making 0 sense to me. I have a method that controls the basic game engine, a method that reveals the card when you click on it, and a delay method. My GOAL is that you click two cards and they both reveal, if there is NOT a match, then they flip back. Obviously if there is a match, they stay. The code to handle BOTH of these behaviors is working. The problem is that when the cards are NOT a match, the second card actually never appears and then the first cards flips back. I figured a delay after the card is revealed would solve the trick, let both cards display for a few seconds, then flip back. So, I built a delay method that I have tested is delaying properly but when I put it in my code blocks, the programs behavior is not what you would expect. In simple terms:
-> Call game Engine method
---> Call reveal card method
---> execute code for game engine
-------> Delay method gets called BEFORE executing the code to re-hide the cards

Is what I have. BUT, that is not what it is doing. I click the first card, reveals just fine. Then I click the second card, nothing happens for two seconds and then the first card hides indicating that the end code of the engine had been executed. What does not make sense is, why doesn't the reveal method get executed on the second card? It's supposed to go sequentially right? When the game engine method gets called, the very first thing that should happen is the selected card should be revealed. I will post screenshots for visual clarification. Thanks for any help!


Ghica

unread,
Apr 25, 2017, 7:15:21 AM4/25/17
to MIT App Inventor Forum
Delay is BAD. NEVER ever use a delay procedure. This is because the threaded, event driven way of execution of App Inventor.
Use a clock when you need a delay.
Cheers, Ghica.

Evan Patton

unread,
Apr 25, 2017, 8:57:26 AM4/25/17
to MIT App Inventor Forum
To expand on Ghica's response a bit:

The code blocks are executed on what is called the UI (user interface) thread. When the blocks are executing, nothing else can occur on the display. This means that user interactions, such as clicking on buttons, redrawing, hiding, showing of components, etc. will all be halted until the blocks are finished executing. After the blocks execute, a refresh pass is made internally to update the display. Pending events that do happen during this time will be stored on the UI thread's message queue and will execute thereafter, at which point the blocks for those event handlers will fire, blocking the UI thread, and so on and so forth. In your delay procedure, you essentially spin in a loop, preventing the blocks code from returning so that Android cannot redraw the screen.

Using a clock addresses this problem by allowing other events to fire and the UI to redraw to maintain responsiveness to user input. When the clock's Timer event fires, you can then perform your UI updates and after the blocks have finished the UI will redraw.

Evan

Taifun

unread,
Apr 25, 2017, 9:36:29 AM4/25/17
to MIT App Inventor Forum

Christopher Steele

unread,
Apr 25, 2017, 3:10:45 PM4/25/17
to MIT App Inventor Forum
Thank you for your suggestions. I have removed the delay and implemented the clock solution suggestion. I followed the "wait" example that Taifun posted. However, I am still seeing the same behavior. I outputted the value of `TimerEnabled` so I could see the behavior. I click the first button, the image reveals and `TimerEnabled` is still false. That is correct. Now, the second button gets clicked. The button acts like its being clicked but doesn't reveal, immediately after, the first image is hidden again. `TimerEnabled` is then set to true. Then, after my timer wait, `TimerEnabled` changes back to false. Here's the updated code: 


Taifun

unread,
Apr 25, 2017, 3:19:56 PM4/25/17
to MIT App Inventor Forum
you might want to read again, what Evan explained earlier

Taifun 

Ghica

unread,
Apr 25, 2017, 4:42:07 PM4/25/17
to MIT App Inventor Forum
Funny. Apparently you still think that you can wait in this way. But you cannot. It just happens that the clock timer event happens at some point.
What you must do, is everything that comes after the call to the wait, move that to the clock.timer event block. This is the only place where you know that the wait is over.
Cheers, Ghica.

Christopher Steele

unread,
Apr 25, 2017, 8:54:54 PM4/25/17
to mitappinv...@googlegroups.com
Ok, I went back a re-read everyone's comments, your suggestions and linked articles. I was having a hard time wrapping my head around the concept but I think I understand now. Ultimately, Ghica's last comment helped get me over the hump. I finally got it working! It's probably not the prettiest but, for what I need it to do, it's working. This line in fturbak's post (thanks to Taifun for the reference) helped a lot: "As noted in the paper, effective programming in the context of these rules requires using some different programming idioms than one may use in other programming languages." So, I re-thought how I was handling (after I finally figured out what you all were trying to tell me) I pulled some logic out of my game_engine method, and destroyed that method. I then treated the combination of the button clicks and the timer method as the "game engine". It's all working great now. Thanks everyone!!

(I have one of the buttons in the screen shot so you can see how I am calling everything. I have a group of buttons elsewhere on the page but didn't feel the need to show them all)
Again, thank you ALL!!
Reply all
Reply to author
Forward
0 new messages