Exiting Code into Routine/Loop

Hello,

I have my task coded in Python, which I’ve integrated into PsychoPy using builder. I’d like it to be as a five-second routine in builder and then repeat as a series of trials. The same task would be repeated 20 times, forming one overall larger trial. I have attached an image of the desired routine/loop for reference.

Currently, as it is, the task exits through pygame.quit() and win.flip(), but both of these exit the entire task, rather than exiting back to the loop. Currently, after the 5 seconds, the screen remains blank white and won’t load into the next routine.

If anyone could help me adjust the code so that it can be integrated into the loop 20 times in PsychoPy please, I would be most appreciative!

Here is the entire, albeit lengthy, code:

import pygame, sys
from pygame.locals import *
import random, time
import math
import os
import csv
import time
from psychopy.core import CountdownTimer

os.environ['SDL_VIDEO_CENTERED'] = '1'
pygame.init()
SCREEN_WIDTH, SCREEN_HEIGHT = pygame.display.Info().current_w, pygame.display.Info().current_h
pygame.joystick.init
pygame.joystick.get_count()
print ("Joystick Count", pygame.joystick.get_count())
pygame.init()

pygame.font.init

size = [SCREEN_WIDTH,SCREEN_HEIGHT-50]
#SCREEN_WIDTH = 1000
#SCREEN_HEIGHT = 1000
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
screen = pygame.display.set_mode(size, pygame.RESIZABLE)

global Trial
Trial = random.randint(1,2)
print('Condition', Trial)
#CALIBRATION_SPEED = (input('Enter multiplier value'))
 
pygame.display.set_caption("Task")
 
# Loop until the user clicks the close button.
done = False
 
clock = pygame.time.Clock()
 
# Starting position of the silhouette
rect_x = 50
rect_y = 50
 
# Speed and direction of rectangle
rect_change_x = 5
rect_change_y = 5
 
# font
pygame.font.init
font = pygame.font.Font(None, 32)

pygame.display.flip()
screen.fill(BLACK)

# Draw the rectangle
pygame.draw.rect(screen, RED, [rect_x, rect_y, 50, 50])

# Move the rectangle starting point
rect_x += rect_change_x
rect_y += rect_change_y

#Setting up FPS 
FPS = 60
FramePerSec = pygame.time.Clock()
#Other Variables for use in the program
#SCREEN_WIDTH = 1000
#SCREEN_HEIGHT = 1000
SPEED = 5
SCORE = 0
COLLISION_SCORE = 0

#Setting up Fonts
font = pygame.font.SysFont("Verdana", 40)
font_small = pygame.font.SysFont("Verdana", 20)

background = pygame.image.load("N:\Task Development\Stimuli/trial.jpeg")

#delay after the instruction screen
pygame.time.wait(1000)

timer = pygame.time.get_ticks()
timer2 = timer + 5000

#TASK GAME WINDOW SIZE
DISPLAYSURF = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.RESIZABLE)
DISPLAYSURF.fill(WHITE)
pygame.display.set_caption("EEG Task")
pygame.mixer.init()

class Enemy(pygame.sprite.Sprite):
      def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("N:\Task Development\Stimuli/greendot.png")
        self.rect = self.image.get_rect()
        self.rect.center = ((SCREEN_WIDTH/2), 0)
      def move(self):
        global SCORE
        self.rect.move_ip(0,SPEED)
        if (self.rect.bottom > SCREEN_HEIGHT-10):
            SCORE += 1
            #pygame.mixer.Sound("D:\Pygame Project\Stimuli/spawn.wav").play()
            self.rect.top = 0
            self.rect.center = ((SCREEN_WIDTH/2), -SCREEN_HEIGHT)
        global COLLISION_SCORE

class Enemy2(pygame.sprite.Sprite):
      def __init__(self):
        super().__init__() 
        self.image = pygame.image.load("N:\Task Development\Stimuli/greendot.png")
        self.rect = self.image.get_rect()
        self.rect.center = ((SCREEN_WIDTH/2), 0)
      def move(self):
        global SCORE
        self.rect.move_ip(0,(-SPEED))
        if (self.rect.top < 10):
            SCORE += 1
            #pygame.mixer.Sound("N:\Task Development\Stimuli/spawn.wav").play()
            self.rect.top = 0
            self.rect.center = ((SCREEN_WIDTH/2), SCREEN_HEIGHT)
        global COLLISION_SCORE

class Player(pygame.sprite.Sprite):
    def __init__(self):

        super().__init__()
 
        # Variables to hold the height and width of the block
        width = 10
        height = 15
 
        # silhouette image
        self.image = pygame.image.load("N:\Task Development/Stimuli/reddot.png")
        
 
        # Fetch the rectangle object that has the dimensions of the image
        self.rect = self.image.get_rect()
 
        # Set initial position of silhouette
        self.rect.x = SCREEN_WIDTH/2-80
        self.rect.y = SCREEN_HEIGHT/2

        # joystick count
        self.joystick_count = pygame.joystick.get_count()
        if self.joystick_count == 0:
            # No joysticks!
            print("Ben, check the USB connection you doughnut!")
        else:
            # Use joystick #0 and initialize it
            self.my_joystick = pygame.joystick.Joystick(0)
            self.my_joystick.init()
 
    def move(self):
        
        if self.joystick_count != 0:
 
            # joystick pos
            horiz_axis_pos = self.my_joystick.get_axis(0)
            vert_axis_pos = self.my_joystick.get_axis(1)
 
            # Move x and y, * speed 
            self.rect.x = self.rect.x+int(horiz_axis_pos*int(CALIBRATION_SPEED))
            self.rect.y = self.rect.y+int(vert_axis_pos*int(CALIBRATION_SPEED))

#Setting up Sprites        
P1 = Player()
E1 = Enemy()
E2 = Enemy2()

#Creating Sprite Groups
enemies = pygame.sprite.Group()
enemies.add(E1)
enemies.add(E2)
all_sprites = pygame.sprite.Group()
all_sprites.add(P1)
all_sprites.add(E1)
all_sprites.add(E2)

#Adding a new User event (speed up)
INC_SPEED = pygame.USEREVENT + 1
pygame.time.set_timer(INC_SPEED, 1000)

#Game Loop
while True:       
    #Cycles through all events occuring      
    for event in pygame.event.get():

        if event.type == QUIT:
            continueRoutine = False
            #win.flip()
            #sys.exit()
        timer_codes = CountdownTimer(3)
        if timer_codes.getTime() > 2:
            for line in range(1, 2):
                dev.activate_line(lines = line)
            timer_codes.reset()

    DISPLAYSURF.blit(background, (0,0))
    scores = font_small.render(str(SCORE), True, BLACK)
    DISPLAYSURF.blit(scores, (10,10))

    COLLISION_SCORE2 = COLLISION_SCORE/20
    
    cscores = font_small.render(str(COLLISION_SCORE2), True, BLACK)
    DISPLAYSURF.blit(cscores, (SCREEN_WIDTH-60, 10))

    #Moves and Re-draws all Sprites
    for entity in all_sprites:
        entity.move()
        DISPLAYSURF.blit(entity.image, entity.rect)
        

    #To be run if collision happens
    if pygame.sprite.spritecollideany(P1, enemies):
        pygame.mixer.Sound("N:\Task Development\Stimuli/scream.wav").play()
        COLLISION_SCORE += 1

    timer = pygame.time.get_ticks()
    if timer > timer2:
        pygame.display.update()
        pygame.mixer.Sound("N:\Task Development\Stimuli/scream.wav").play()
        for entity in all_sprites:
                entity.kill()
 
        # Creates a new file
        with open('Participant Scores.csv', 'a+') as file:
            file.write('\n')
            file.write("Trial Number" + "," + Trial + "," + "Score" + ',' + ',' + (int(COLLISIONSCORECONV)))
            file.write((str(COLLISIONSCORECONV)))

    pygame.display.update()
    FramePerSec.tick(FPS)

Thank you very much in advance!
Ben

There are a few things that could be going on here. You’re basically putting a pygame window in front of the PsychoPy-controlled pyglet one, as far as I can tell, and I really have no idea what that will do, but it doesn’t surprise me that you have trouble switching back and forth between them. At a glance you might try pygame.display.quit() rather than just pygame.quit() but I don’t know if that will solve all of the underlying issues.

I’m curious, what’s your goal in using the builder? It seems like you can do everything as a stand-alone python script, maybe borrowing a couple of the psychopy libraries through import. You would need to build your own loop structure, but you’re already recording data and managing the display entirely through your own code anyway. Is there a subsequent task you’re trying to incorporate?