Showing stimuli independently based on time and responses

Edit: To put this problem simply, I need to replace a word on the screen with a new word from an array when either a participant responds by pressing the spacebar or when 4 seconds is up, whichever comes first. The word replacement needs to happen in the same routine (so the keyboard press cannot end the routine).

I am attempting to create a dual-task experiment where on one half of the screen, a video plays continuously while on the other half of the screen, words appear. As the video plays, the user has four seconds to respond with the keyboard to the word that appeared. The next word appears when they respond or when the 4 seconds is up. The video needs to continue to play the entire time this is occurring without starting over. However, the video may terminate if the user presses an on-screen button. The routine should end when the video is over or when the button is pressed.

The main issue is that in the regular builder, I cannot seem have a user response terminate one stimuli without terminating the other. I have been working in the coder and searching the forum, and believe I have come up with the logic for what I need, but I am not sure how to best implement it.

The experiment currently has two routines for bringing the stimuli in. The first routine uses code to read in the words and put them in an array, then randomly shuffles them for presentation. The second routine does the same for the video files. Then, the routine that shows the stimuli is in a loop called “trials”, which is presenting both stimuli with seperate timing. However, the word disappears after 4 seconds if there is no response, but then that side of the screen stays blank until the time for the video is up, rather than presenting another word. If there is a response to the word, it ends the entire routine (so a new video starts playing).

The logic that I have come up with would be as follows, and it would go in the looped routine under the frames tab (note that I have made up variable names based on what I am looking for, this is no type of actual code).

while currentTime <= videoTime 
  if wordResponse = True:
    showNextWord
  if wordTime = 4:
    showNextWord

If this logic is correct, suggestions on how to actually implement it would be appreciated. If there is an easier way to do this, please let me know.

Thank you!

Hi @cpat3, you could still use the builder for this, but implement some code as a component. I am not so familiar with Python code so I can just give you a rough idea of how I would do it:

  1. In the text component of the word stimulus, set the text to “set every frame” and use a variable.
  2. Add a code component that does the following:
    A) Begin of routine: shuffle your stimuli into arrays like you’re already doing, set a counter to 0, use the counter to select the first entry of the word array for the text component, start a clock
    B) Every frame: check if the clock is > 4, if so raise the counter by 1 and restart the clock from 0, if not, check if a key was pressed, if so, raise the counter by 1 and restart the clock from 0. Ultimately use the updated counter to select the next entry in the word array to be displayed.
  3. Let the end of the video end the routine.

Hope that helps!

Thanks so much, that was very helpful! I’m going to post my code and what I did here in case anyone comes across this in the future.

I used the youtube video tutorials from Dr. Ozubko to create the stimuli arrays. The word array is called word_stim and the index is cur_word.

In the begin routine tab, I have

#open excel file
inbook = xlrd.open_workbook(in_file)
insheet = inbook.sheet_by_index(0)

#arrays to hold stimuli
word_stim = []
time = []

#loop through the rows in the file
for rowx in range(1, num_items+1):
    #read in an entire row
    row = insheet.row_values(rowx)
    word_stim.append(row[0])
    time.append(row[2])
    

#randomize the stimuli
random.shuffle(word_stim)

#create variable to get time in routine
timer = core.Clock()
currentT = timer.getTime()

#create keyboard variable
kb = keyboard.Keyboard()

Then on each frame, I have

#get current time
currentT = round(timer.getTime())

#loop from above logic
if currentT >= 4 or kb.getKeys(['space']):
    cur_word = cur_word + 1
    timer.reset()

Note that its important to get the current time on each frame, not at the beginning or end of a routine.

At the end of the routine, I included code to increase the index of the video files array and the stimulus time array by one.

In the builder itself, the duration of the word is set to $time[stim_time] so that it disappears when the video is done playing (otherwise the words keep going and the video disappears and the routine doesn’t end).

*Edited after I solved the issues I was having on my own