Page 1 of 1
Using a Repeat
Posted: Sun Jul 14, 2013 5:16 am
by JeffO2013
Hi everyone,
I'm having a problem with a repeat loop. I have some code that right now is inside openCard and I need it to start running as soon as the card opens (there are no other events to start the ball rolling) but I need it to repeat until a certain condition is met. This code includes several functions and commands. The issue I'm having is the code seems to run through one time but fails to repeat. A simplified version is listed below (pretty much the same functionality without some of the unnecessary functions; both this code and the longer version get stuck at the same spot).
Code: Select all
global counter
on openCard
put 0 into counter
repeat with counter = 0 to 4
set the visible of img "RED X.png" to false
set the visible of img "GREEN CHECK.png" to false
keyDown
add 1 to counter
end repeat
end openCard
on keyDown theKey
if theKey is k then
set the visible of img "RED X.png" to true
pass keyDown
else if theKey is d then
set the visible of img "GREEN CHECK.png" to true
pass keyDown
else
end if
end keyDown
I've tried several different versions of the repeat loop (using an exit repeat and this counter version) and nothing has worked so far.
Thanks for the help!
Jeff
Re: Using a Repeat
Posted: Sun Jul 14, 2013 5:45 am
by Simon
Hi Jeff,
Not exactly clear on what you are trying to do.
The on keyDown message is sent when an actual key is pressed, you have it in your loop, not sure but is it because you want it included during the loop? Or what you'll get is the image turning not vis to vis (but way faster than a user has time to respond to).
I'd check into "send" command rather than using a loop. That way other messages can be sent.
Repeat loops are common and easy to understand but with a little more effort the "send " command is actually a good friend.
repeat until a certain condition is met
Thats a "repeat until" but I suppose you've seen that in the dictionary.
I guess, ask more questions and someone could give you more help.
Simon
Re: Using a Repeat
Posted: Sun Jul 14, 2013 12:38 pm
by Klaus
HI Jeff,
looks like you wnat to "flash" the two images (show/hide them a couple of times) when the card opens, right?
In that case:
1. Even if your script would work, you would not see anything, since Livecode is to fast unless you force a little delay!

2. You are calling "keydown" but without any parameter, so your "keydown" handler will not do anything!
3. I don't think that you need "counter" as a global variable!
Do something like this:
Code: Select all
on opencard
# X flashes:
repeat 5
lock screen
hide img "RED X.png"
hide img "GREEN CHECK.png"
unlock screen
## Experiment with the delay a bit:
wait 200 millisecs with message
lock screen
show img "RED X.png"
show img "GREEN CHECK.png"
unlock screen
end repeat
end opencard
Check these great learning resources:
http://www.hyperactivesw.com/revscriptc ... ences.html
Best
Klaus
Re: Using a Repeat
Posted: Sun Jul 14, 2013 5:24 pm
by JeffO2013
Hi Simon and Klaus,
To clairify - I wrote my last post at around 2 am - I want the card to execute all of the functions and commands listed above the keyDown and then stop until it receives a key press from the user, then execute anything listed after the keyDown (just checking to see if the condition is met) then restart from the top (if the condition is not met).
So I need the program to display some images, wait for the user to press a button, then based on the button press display a certain image and either exit the openCard (it'll go to the next card) or restart from the openCard.
Here's the complete openCard code from the original program
Code: Select all
on openCard
set the visible of img "GREEN CHECK.png" to false //makes green check invisible
set the visible of img "RED X.png" to false //makes the red x invisible
put the milliseconds into tStartMilleseconds
put true into sTrack //set sTrack to true //seconds are being tracked
// picks a target image, a response image, and a distractor image, then places them in the correct image holders
send interTrialInterval to me in 2 milliseconds //used to set the interval between trials, also executes the necessary functions to
//set the card up properly
set the filename of img "target" to targetArray[arrayNumber]
keydown //needs to wait for user input and judge whether input was correct (green check) or incorrect (red x) and display the
//appropriate image
moveToNextPhase // checks to see if the user has met the conditions to move to the next phase - if so, then go to the next card, if
//not then repeat from the beginning of open card
end openCard
so far the program picks appropriate images and places them in the appropriate spots, makes the red x and green check invisible on openCard, takes user input and evaluates it correctly and then displays the red x or green check appropriately, but doesn't restart from the beginning like it should.
Hope this clarifies.
Thanks!
Jeff
Re: Using a Repeat
Posted: Sun Jul 14, 2013 6:05 pm
by dunbarx
Hi.
Just inexperience, that you mixed in a few language elements that do not sync together. This goes away with practice.
You need to wait (and I mean "wait") until a key is pressed, or call a function that checks for that condition. Your choice.
in either case, read about the "keysDown" function. If you still have trouble integrating that into your procedure, write back.
Craig Newman
Re: Using a Repeat
Posted: Sun Jul 14, 2013 6:37 pm
by Simon
Hi Jeff,
Wish I could see what is in your "moveToNextPhase" script, but:
I suggest you use a global and remove keyDown and moveToNextPhase also I'm going to assume that the moveToNextPhase is a counter, say after 10 images it moves to the next card
golbal gConditionMet
on preOpenCard
put "" into gConditionMet
end preOpenCard
on keyDown theKey
if theKey is k then
set the visible of img "RED X.png" to true
moveToNextPhase
pass keyDown
else if theKey is d then
set the visible of img "GREEN CHECK.png" to true
moveToNextPhase
pass keyDown
end if
end keyDown
on moveToNextPhase
add 1 to gConditionMet
if gConditionMet <= 9 then
openCard
else
put "" into gConditionMet
go to next card
end moveToNextPhase
I "think" thats the logic you want. If not keep detailing
Simon
Re: Using a Repeat
Posted: Sun Jul 14, 2013 8:45 pm
by JeffO2013
Hi Simon,
the moveToNextPhaseCode looks like this
Code: Select all
on moveToNextPhase
if correctResponse is 15 then
go to next card
else
go to openCard
end if
end moveToNextPhase
the keyDown contains this
Code: Select all
on keyDown theKey
if theKey is k then
if vRandomLocation is 2 then
set the visible of img "GREEN CHECK.png" to true
add 1 to correctResponse
go to moveToNextPhase
else
set the visible of img "RED X.png" to true
put 0 into correctResponse
end if
pass keyDown
else if theKey is d then
if vRandomLocation is 1 then #get location of correct response
set the visible of img "GREEN CHECK.png" to true
add 1 to correctResponse
go to moveToNextPhase
else #If response is incorrect
set the visible of img "RED X.png" to true
put 0 into correctResponse
end if
pass keyDown
else
end if
end keyDown
What I tried to have happen is the program evaluates the key press as either correct or incorrect based on the variable vRandomLocation which is also used to decide which position images are placed in (left or right in this case). If the user response is correct it shows a green check, adds one to correctResponse, and goes to moveToNextPhase where it evaluates if the user got 15 correct response in a row. If the user response is incorrect it shows a red x puts 0 into correctResponse and then waits for the user to input a correct response before restarting from the openCard and doing everything again. Right now it displays the images correctly and takes the user input and evaluates it correctly and displays the green check or red x appropriately, but doesn't go back to the openCard to execute again.
You can ignore the code in the first post: that's where I was playing around with it in a simpler version of the program to see if I could get it to work there, but no such luck. The rest of the code I posted is from the actual program I'm working on.
Craig, I've played around some with 'wait' but I'm wondering now if it would be easier to try and have this work without a repeat loop (or if it will work without a repeat loop).
And you are correct about the inexperience. I'm trying to teach myself how to do this as I go. I have no previous coding experience, so I really appreciate everyone's help.
Jeff
Re: Using a Repeat
Posted: Sun Jul 14, 2013 9:20 pm
by dunbarx
You should try as many methods as you can. The danger for new users is that, being so eager to get through the process, that they never take the time to download the roses.
"Wait" has a dicey reputation, in that it ties up the engine. This may not be an issue if the intent is to force the user to press a key, and if they do not, well, too bad; we can outwait you. The more modern method is to send a message in time, but that is more than you need here. That last is far more versatile, however. You will soon see.
Try "wait". Try something else.
Craig
Re: Using a Repeat
Posted: Sun Jul 14, 2013 9:52 pm
by Simon
Ahh
There is an error in moveToNextPhase.
Craig doesn't like it when I just hand over the code, and he is right, half the fun of LC (programming in general I guess) is the AHA moments. Makes me feel all warm and fuzzy.
Take a good look at "go" in the dictionary, is it what you want?
Do you know how to drop breakpoints (little red dots in the script editor) and step through your code? If you use that and watch the "msg" variable it will give you a hint.
Simon
Re: Using a Repeat
Posted: Sun Jul 14, 2013 10:09 pm
by JeffO2013
Got It!
I both love and hate when it is something simple.
I have to remember that go to used to point to cards or URL's.
It works like I want it to now guys.
Thanks a Lot!
The new code for openCard (this will change further for my program, but trying to build it in steps)
Code: Select all
on OpenCard
set the visible of img "GREEN CHECK.png" to false
set the visible of img "RED X.png" to false
put the milliseconds into tStartMilleseconds
put true into sTrack //set sTrack to true (seconds are being tracked
send interTrialInterval to me in 2 milliseconds // advance the seconds function
set the filename of img "target" to targetArray[arrayNumber]
end OpenCard
The keyDown code now looks like this:
Code: Select all
on keyDown theKey
if theKey is k then
if vRandomLocation is 2 then
set the visible of img "GREEN CHECK.png" to true
add 1 to correctResponse
moveToNextPhase
else
set the visible of img "RED X.png" to true
put 0 into correctResponse
end if
pass keyDown
else if theKey is d then
if vRandomLocation is 1 then #get location of correct response
set the visible of img "GREEN CHECK.png" to true
add 1 to correctResponse
moveToNextPhase
else #If response is incorrect
set the visible of img "RED X.png" to true
put 0 into correctResponse
end if
pass keyDown
else
end if
end keyDown
and the moveToNextPhase code looks like this:
Code: Select all
on moveToNextPhase
if correctResponse is 15 then
go to next card
else
openCard
end if
end moveToNextPhase
I'm also open to any other suggestions on making the code shorter and more concise.
Thanks again everyone!
Jeff
Re: Using a Repeat
Posted: Mon Jul 15, 2013 5:12 am
by dunbarx
Simon.
I just want a new user to sweat a bit. You know it is good for them. Sometimes a solution can be just handed over (we have both done that) but that is usually in cases where that user is already well along, and an outright gift is not going to divert too much from the effort of learning.
I know you like to play with this as much as I do.
You're all right.
Craig