Object start time on key press?

OS: Win10
PsychoPy version: 3.0.2
Standard Standalone?: Y, I think so
What are you trying to achieve?: To have one of three images appear depending on button press (left, right, down)

Disclaimer: Super amateur level programmer. Only worked with pascal and c++ at an entry level previously so my understanding of python is extremely limited. Talk to me as if I were the village idiot.

What did you try to make it work?: First I read somewhere to set the image objects to load from the start but have their opacity turned to 0, then have them appear using a code like this
(shock0-2 are objects containing one image each)
(Begin routine)

Shock0.opacity = "0" #start shock0 invisible
Shock1.opacity = "0" #start shock1 invisible
Shock2.opacity = "0" #start shock2 invisible

if event.getKeys('down'): # if down key pushed,
    Shock0.opacity = "1.0" # make shock0 appear
 elif event.getKeys('left'): # if left key is pushed
    Shock1.opacity = "1.0" # make shock1 appear
 elif event.getKeys('right'): # if right key is pushed
    Shock2.opacity = "1.0" # make shock2 appear

But that didn’t work. I don’t have the error saved unfortunately, so I’m sure that I did something wrong. Now when I try to run it the stimulus doesn’t start at all. It immediately crashes with no generated output before I get to enter participant ID. So at the moment everything is just commented out for the time being.

Then I was thinking if there is a possibility to connect the start time of each image to which button is being pressed instead. And here I am. Tried looking up online resources but couldn’t find anything.

If possible I want to be able to solve it all in the builder, trying to avoid actual coding as much as possible for the time being.

Thank you in advance

Hi @mothos, I am guessing you received an error for attempting to set the opacity using a string - you will want to use int or float, e.g.,

if event.getKeys('down'): # if down key pushed,
    Shock0.opacity = 1.0 # make shock0 appear
# etc

Hi @mothos,

you also do not want to have all your code under “Begin Routine” but want to separate it:

  • “Begin Routine”: Initialize opacity values
  • “Each Frame”: Check for button press and change opacity values accordingly.

You can download the following psyexp and look at the code:

mothos.psyexp
shock0.jpg
shock1.jpg
shock2.jpg

Hello, and thank you @dvbridges and @frank.papenmeier! Your solutions definitely helped and put me in the right direction, and your assistance is greatly appreciated!

My project, however, doesn’t seem to respond to the button presses very quickly. The test version you sent me was very fast by comparison. No idea what is causing the slowdown.

The project itself is a setup constructed to send fake electric shocks to no real participant. Preferably I would have one button-pressed evoked image to stay present for the duration of the loop with no other input accepted after the first one.
From what I understand for that to work, I need to, in my key settings, select Store: First Key, and untick Discard Previous?

I will attach the relevant project files. Please put all pictures in a folder named “images”
AggPrototypeRetaliationTest.psyexp (30.5 KB)

Shock0 Shock1 Shock2

I think the problem is the way you have combined the event module with the keyboard component. You are better off using one or the other, so I would use keyboard component. You are saving all keys in the keyboard component, and that will affect the logic below, because ‘down’ and ‘left’ may always be true if both keys are pressed within the trial. You are better off using “last key” and if you really want to save all keys, add them to a list and save that list in your datafile. If this is not acceptable, let us know and we can change things. For now, try “last key” in your keyboard component, and replace your code in the “Every Frame” tab of the “Retaliation” routine code component with:

if 'down' == RetaliationKey.keys: # if down key pushed,
    Shock0.opacity = 1.0 # make shock0 appear
    Shock1.opacity = 0 # make shock1 invisible
    Shock2.opacity = 0 # make shock2 invisible
elif 'left' == RetaliationKey.keys: # if left key is pushed
    Shock1.opacity = 1.0 # make shock1 appear
    Shock0.opacity = 0 # make shock0 invisible
    Shock2.opacity = 0 # make shock2 invisible
elif 'right' == RetaliationKey.keys: # if right key is pushed
    Shock2.opacity = 1.0 # make shock2 appear
    Shock0.opacity = 0 # make shock0 invisible
    Shock1.opacity = 0 # make shock1 invisible
1 Like

It works! You were absolutely right.
“Last key” is fine so I switched back to that per your recommendation.

Massive thanks!