class GameScene: def __init__(self, color): self.color = color self.snakes = [] self.fruit = Fruit() self.kb_handler = KeyboardHandler() def add_snake(self, snake): self.snakes.append(snake) def update_actors(self): for snake in self.snakes: direction = self.kb_handler.update() snake.move(direction) self.detect_colision(snake, direction) def detect_colision(self, snake, direction): for piece in snake.body: if (piece == self.fruit.pos): snake.pontuation += 1 snake.eat(direction) self.fruit.newPos() cont = 0 for other_piece in snake.body: if (piece == other_piece): cont += 1 if (cont >= 2): sys.exit() if (0 > piece[0] < 800 or 0 > piece[1] < 600): snake.colide()
def checkPelletEvents(self): pellet = self.pacman.eatPellets(self.pellets.pelletList) if pellet: self.eat_sound.set_volume(0.2) self.eat_sound.play() self.pelletsEaten += 1 self.score += pellet.points if self.pelletsEaten == 25 or self.pelletsEaten == 150: if self.fruit is None: self.fruit = Fruit(self.nodes, self.sheet, "cherry") if self.pelletsEaten == 75: if self.portal is None: self.portal = Portal(self.nodes, self.sheet) if self.portal2 is None: self.portal2 = Portal(self.nodes, self.sheet) if self.pelletsEaten == 125: if self.portal3 is None: self.portal3 = Portal2(self.nodes, self.sheet) if self.portal4 is None: self.portal4 = Portal2(self.nodes, self.sheet) self.pellets.pelletList.remove(pellet) if pellet.name == "powerpellet": self.ghosts.resetPoints() self.ghosts.freightMode() if self.pellets.isEmpty(): self.pacman.visible = False self.ghosts.hide() self.pause.startTimer(3, "clear") self.flashBackground = True
def __init__(self): # initialize the objects we are going to need self.window=Window() self.body= Body() # attaches body to head self.head= Head(self.body) self.fruit=Fruit() self.scoreboard= ScoreBoard() # Main gmae loop while True: # updates the game constantly self.window.screen.update() # listen for key press self.window.screen.listen() # treats keypress self.window.screen.onkey(self.head.go_up, "Up") self.window.screen.onkey(self.head.go_down, "Down") self.window.screen.onkey(self.head.go_right, "Right") self.window.screen.onkey(self.head.go_left, "Left") self.head.move() self.checks_collision() time.sleep(self.delay)
def __init__(self): pygame.init() self.screen = pygame.display.set_mode((716, 793 + 60)) pygame.display.set_caption("Pacman Portal") self.bricks = Group() self.shields = Group() self.powerpills = Group() self.qpills = Group() self.maze = Maze(self.screen, self.bricks, self.shields, self.powerpills, self.qpills, brickfile='square', mazefile='images/pacmanportalmaze.txt', shieldfile='shield', powerpill='powerpill') self.increase = False self.scoreboard = Scorebord(self.screen, self) self.pacman = Pacman(self.screen, self.scoreboard, self) self.play_button = Button(self.screen, "PLAY GAME", 80 / 100) self.score_button = Button(self.screen, "HIGH SCORES", 90 / 100) self.menu = Menu() self.audio = Audio() self.fruit = Fruit(self.screen) self.blinky = Blinky(self.screen, self.pacman, self.scoreboard) self.inky = Inky(self.screen, self.pacman, self.scoreboard) self.pinky = Pinky(self.screen, self.pacman, self.scoreboard) self.clyde = Clyde(self.screen, self.pacman, self.scoreboard) self.oportal = Portal('o', self.pacman) self.bportal = Portal('b', self.pacman) self.active = False self.pause = False
def __init__(self, width, height, rows=20): pygame.init() pygame.font.init() self.width = width self.height = height self.rows = rows self.score = 0 self.entities = [] self.spacing_x = self.width // self.rows self.spacing_y = (self.height // 10 * 9) // self.rows self.game = True self.clock = pygame.time.Clock() self.score_font = pygame.font.Font(None, 50) with open(os.path.join("snake-game", "high_score.txt"), "r") as file: self.high_score = int(file.read()) self.snake = Snake(body=[], rows=self.rows) self.entities.append(self.snake) self.fruit = Fruit(rows=self.rows) self.entities.append(self.fruit) pygame.display.set_caption("Snake Game") self.window = pygame.display.set_mode((self.width, self.height)) self.score_surface = pygame.Surface((self.width, self.height // 10)) self.game_surface = pygame.Surface((self.width, self.height // 10 * 9)) self.game_loop()
def play(self): while not self.game_over: self.clock.tick(self.FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: self.game_over = True break if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.game_over = True break if event.key in (pygame.K_LEFT, pygame.K_RIGHT, pygame.K_DOWN, pygame.K_UP): self.direction = self.dir[event.key] self.snake.move(self.direction, self.width, self.height, self.status_height) if self.snake.collision(): self.show_game_over() pygame.time.delay(3000) continue if self.snake.eat(self.fruit): self.fruit = Fruit(self.snake, self.width, self.height, self.status_height) self.score += 10 if len(self.snake.snake) % 5 == 0: self.level += 1 self.FPS += 10 self.screen.fill((0, 0, 0)) self.screen.fill((0, 0, 255), (0, 0, self.width, 15)) self.show_status() self.fruit.draw(self.screen) self.snake.draw(self.screen) pygame.display.flip()
def update_fruit(self): snake_head = self.__snake.get_head_position() if self.__fruit.has_been_eaten(snake_head[0], snake_head[1], snake_head[2]): # nao sei porque, mas tick nao aparece preenchido aqui self.__tick.increase_velocity() self.__add_tail = True self.__fruit = Fruit()
def __init__(self): super().__init__() # Snake settings self.snake = Snake(self.screen) # Snake bots settings self.snake_bot = SnakeBot(self.screen) self.snake_bot_2 = SnakeBot(self.screen) # Fruits settings self.fruit = Fruit(self.screen)
def update(self): self.delta_time = pygame.time.get_ticks() - self.last_frame_ticks self.last_frame_ticks = pygame.time.get_ticks() self.spawn_timer -= self.delta_time if self.spawn_timer <= 0: self.spawn_timer = 10000 if len(self.fruits) == 0: fruit = Fruit(self.game_master) fruit.rect.center = (self.fruit_spawn_position_x, self.fruit_spawn_position_y) self.fruits.add(fruit) for fruit in self.fruits: fruit.update()
def __init__(self): min = Point(0, 10) max = Point(self.width - 1, self.height - 1) pyxel.init(self.width, self.height, caption=self.title, fps=18) pyxel.load("my_resource.pyxres") self.snake = Snake(self.width / 2, self.height / 2) self.fruits = [ Fruit(min, max, 8), Fruit(min, max, 9), Fruit(min, max, 10) ] self.direction = Direction() self._reset() pyxel.run(self.update, self.draw)
def play(self): while not self.game_over: self.clock.tick(self.FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: self.game_over = True break if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.game_over = True break if event.key in (pygame.K_LEFT, pygame.K_RIGHT, pygame.K_DOWN, pygame.K_UP): if abs(self.direction - self.dir[event.key]) != 2 or len( self.snake.snake) == 1: self.direction = self.dir[event.key] self.snake.move(self.direction, self.width, self.height) if self.snake.collision(): self.game_over = True pygame.font.init() font = pygame.font.SysFont("Arial", 36) text = font.render("Game over", 1, (255, 255, 255)) place = text.get_rect(center=(self.width // 2, self.height // 2 - 20)) font2 = pygame.font.SysFont("Arial", 18) text2 = font2.render('Score: {}'.format(self.score), 1, (255, 255, 255)) place2 = text2.get_rect(center=(self.width // 2, self.height // 2 + 10)) self.screen.blit(text, place) self.screen.blit(text2, place2) pygame.display.flip() pygame.time.delay(2000) continue if self.snake.eat(self.fruit): self.fruit = Fruit(self.snake, self.width, self.height) self.score += 10 if len(self.snake.snake) % 5 == 0: self.FPS += 10 self.screen.fill((0, 0, 0)) self.fruit.draw(self.screen) self.snake.draw(self.screen) pygame.display.flip()
def restart(): global points, is_dead, snake_obj, fruit_obj points = 0 is_dead = False snake_obj = Snake() fruit_obj = Fruit()
def checkPelletEvents(self): pellet = self.pacman.eatPellets(self.pellets.pelletList) if pellet: self.pelletsEaten += 1 self.updateScores(pellet.points) self.ghosts.resetPoints() if (self.pelletsEaten == 70 or self.pelletsEaten == 140): if self.fruit is None: self.fruit = Fruit(self.nodes, self.sheet, self.level) self.pellets.pelletList.remove(pellet) if pellet.name == "powerpellet": self.ghosts.freightMode() if self.pellets.isEmpty(): self.pauseTime = 3 self.nextLevelAfterPause = True self.flash_background = True
def generate_food(self): while True: x = random.randint(0, self.max_column) y = random.randint(0, self.max_row) if self.snake.is_colliding(x, y): break self.add(Fruit(x, y))
def __init__(self): pygame.init() # screen size self.height = 720 self.width = 1280 self.arena_h = 680 self.arena_w = 1280 # crating screen and loading textures self.screen = pygame.display.set_mode((self.width, self.height)) pygame.display.set_caption("Snake by Lukasz Ciesluk") self.background = pygame.image.load("images/background.jpg").convert() # ticking variables self.clock = pygame.time.Clock() self.dt = 0.0 self.start = datetime.datetime.now() self.dt1 = 0.0 # score counter self.score = 0 # speed of the snake self.v = 14.0 self.snake = Snake(self) self.food = Fruit(self) self.text = Text(self) # game loop while True: self.events() self.ticking() self.snake.eat(self.food, self) self.food.put_fruit() self.snake.crush(self.food, self) self.screen.fill((0, 0, 0)) self.draw() self.food.draw() self.snake.draw() self.text.draw(self.score, self.dt1) pygame.display.flip()
def addFruit(self, fruitInt, xpos, vspeed, foodType, iD): xpos += self.width / 2 food = Fruit(self, type=foodType, xpos=xpos, randFruitInt=fruitInt, vspeed=vspeed, fruitID=iD, side='right') self.fruitsOpp.append(food)
def __init__(self): self.game_over = False self.width = 500 self.height = 500 self.status_height = 15 self.screen = pygame.display.set_mode((self.width, self.height)) self.clock = pygame.time.Clock() self.FPS = 10 self.snake = Snake(self.width, self.height, self.status_height) self.fruit = Fruit(self.snake, self.width, self.height, self.status_height) self.direction = 3 self.dir = { pygame.K_LEFT: 0, pygame.K_UP: 1, pygame.K_RIGHT: 2, pygame.K_DOWN: 3 } self.score = 0 self.level = 1
def main(): pg.init() settings = Settings() game_stats = GameStats() screen = pg.display.set_mode(settings.screen_size) title = 'Snake | Max score: ' + str(game_stats.max_score) + ' | Score: ' +\ str(game_stats.score) pg.display.set_caption(title) fruit = Fruit(settings, screen) snake = Snake(settings, screen) text = Text(screen, settings, 'GAME OVER') button = RestartButton(screen, settings) menu = Menu(screen) fps_controller = pg.time.Clock() while 1: if not settings.menu_passed: gf.start_game(screen, menu) gf.is_menu_passed(settings, menu) else: if not settings.game_over: gf.check_events(snake) gf.update(fruit, snake, game_stats, fps_controller, screen, settings) if not settings.fruit_on_screen: gf.update_caption(game_stats) gf.check_game_over(snake, settings) else: game_stats.update_max_score() text.draw() button.blit() pg.display.flip() if gf.is_button_pressed(button, settings): gf.restart_game(game_stats, snake, fruit, settings, screen) snake = Snake(settings, screen) fruit = Fruit(settings, screen)
def __init__(self): # Cria uma matriz 6x4x4 preenchida com 0s (ver manipulação na biblioteca numpy) self.__board = [[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]] self.__gpio_manager = GPIO_Manager() self.__snake = Snake() self.__fruit = Fruit() self.__mouse = Mouse(self.on_click) self.__tick = Tick(self.on_tick)
def get_fruits(self): """load images and store as hash map""" path = self.resource_path("fruits") fruit_names = listdir(path) for name in fruit_names: path = self.resource_path("fruits/" + name) image = pygame.image.load(path) image = pygame.transform.scale(image, (c.CARD_SIZE, c.CARD_SIZE)) fruit = Fruit(name, image) self.fruits.append(fruit)
def checkPelletEvents(self): pellet = self.pacman.eatPellets(self.pellets.pelletList) if pellet: sound = pygame.mixer.Sound('waka.mp3') sound.play() self.pelletsEaten += 1 self.score += pellet.points if (self.pelletsEaten == 70 or self.pelletsEaten == 140): if self.fruit is None: levelmap = self.level.getLevel() self.fruit = Fruit(self.nodes, self.sheet, levelmap["fruit"]) self.pellets.pelletList.remove(pellet) if pellet.name == "powerpellet": self.ghosts.resetPoints() self.ghosts.freightMode() if self.pellets.isEmpty(): self.pacman.visible = False self.ghosts.hide() self.pause.startTimer(3, "clear") self.flashBackground = True
def checkPelletEvents(self): #This section is in charge of checking if Pacman is on a pellet. pellet = self.pacman.eatPellets(self.pellets.pelletList) if pellet: self.pelletsEaten += 1 self.score += pellet.points if (self.pelletsEaten == 70 or self.pelletsEaten == 140): if self.fruit is None: self.fruit = Fruit(self.nodes, self.sheet) self.pellets.pelletList.remove(pellet) if pellet.name == "powerpellet": pass #self.ghosts.resetPoints() Ghost command, removed to get rid of ghosts #self.ghosts.freightMode() Ghost command, removed to get rid of ghosts if self.pellets.isEmpty(): self.pacman.visible = False #self.ghosts.hide() Ghost command, removed to get rid of ghosts self.pause.startTimer( 0.1, "clear" ) #Used to be 3, has been set to 0.1. No reset timer.
def start(self): if self.generate_config: self.write_default_config() raise NoStart() if self.config_file: path, config_file_name = os.path.split(self.config_file) self.load_config_file(config_file_name, path=path) # Do some stuff with the valid config from fruit import Fruit # Should print the name of the fruit f = Fruit(self)
def eat_pellets(self): pellet = self.pacman.eatPellets(self.pellets.pelletList) if (pellet): self.pellet_count += 1 if (self.pellet_count == 50 or self.pellet_count == 140) and self.fruit is None: self.fruit = Fruit(self.Nodes) self.pellets.pelletList.remove(pellet) if (len(self.pellets.pelletList) == 0): #if (self.pellet_count == 10): #debug mode (check next lvl immediately) self.ghosts.hide() self.pacman.visible = False self.pacman.lives = 0 self.pause.start(3, "dead") if pellet.name == "powerpellet": self.ghosts.reset_points() self.ghosts.fright() self.chase_music.stop() self.chase_music.play() pygame.mixer.music.pause() self.switch_music = True self.switch_time = 0
def launcher_menu(self): """商店入口""" oper = FruitOperate( [Fruit("苹果", 2, 3), Fruit("香蕉", 1, 5), Fruit("梨子", 6, 6)]) # 用于测试 while True: print("=" * 21 + "水果超市" + "=" * 21) for menu_order, menu_name in self.menu_dict.items(): print(menu_order + "." + menu_name) print("=" * 46) order = int(input("请输入要操作的序号:")) if order == 6: break elif order == 1: info_list = oper.query_all_fruit() print(self.parse_fruit_info(info_list)) elif order == 2: info_list = oper.query_single_fruit(input("请输入要查询水果的名字:")) print(self.parse_fruit_info(info_list)) elif order == 3: flags = oper.add_fruit(self.create_fruit( input("请输入要添加水果的信息:"))) print(self.parse_success_info(flags, 3)) elif order == 4: name = input("请输入要修改水果的名字:") if oper.judge_fruit_exist(name) is False: print("{}不在库中".format(name)) continue price = input("请输入要修改水果的价格(回车略过):") amount = input("请输入要修改水果的数量(回车略过):") flags = oper.modify_fruit(name, price, amount) print(self.parse_success_info(flags, 4)) elif order == 5: flags = oper.remove_fruit(input("请输入要删除水果的名字:")) print(self.parse_success_info(flags, 5)) print("=" * 21 + "再见" + "=" * 21)
def build_maze(self): if self.maze_blocks or self.pellets or self.fruits or self.power_pellets or self.shield_blocks: self.maze_blocks.empty() self.pellets.empty() self.power_pellets.empty() self.fruits.empty() self.shield_blocks.empty() if len(self.ghost_spawn) > 0: self.ghost_spawn.clear() y_start = self.screen.get_height() // 12 y = 0 for i in range(len(self.map_lines)): line = self.map_lines[i] x_start = self.screen.get_width() // 5 x = 0 for j in range(len(line)): co = line[j] if co == 'x': self.maze_blocks.add(Block(x_start + (x * self.block_size), y_start + (y * self.block_size), self.block_size, self.block_size, self.block_image)) elif co == '*': if randrange(0, 100) > 1: self.pellets.add(Block(x_start + (self.block_size // 3) + (x * self.block_size), y_start + (self.block_size // 3) + (y * self.block_size), self.block_size, self.block_size, self.pellet_image)) else: self.fruits.add(Fruit(x_start + (self.block_size // 4) + (x * self.block_size), y_start + (self.block_size // 4) + (y * self.block_size), self.block_size, self.block_size)) elif co == '@': self.power_pellets.add(Block(x_start + (self.block_size // 3) + (x * self.block_size), y_start + (self.block_size // 3) + (y * self.block_size), self.block_size, self.block_size, self.ppellet_image)) elif co == 's': self.shield_blocks.add(Block(x_start + (x * self.block_size), y_start + (y * self.block_size), self.block_size // 2, self.block_size // 2, self.shield_image)) elif co == 'o': self.player_spawn = [(i, j), (x_start + (x * self.block_size) + (self.block_size // 2), y_start + (y * self.block_size) + (self.block_size // 2))] elif co == 'g': self.ghost_spawn.append(((i, j), (x_start + (x * self.block_size), y_start + (y * self.block_size)))) x += 1 y += 1
def get_fruit(self): url = self._url + self._fruits_url + "/" + self._session response = requests.get(url=url, headers=self._header) if response.status_code == 400: return None, BagStatus.LOOKAHEAD_EXCEEDED elif response.status_code == 204: return None, BagStatus.NO_MORE_FRUITS fruit = json.loads(response.content.decode("utf-8")) key = "".join(fruit.keys()) value = fruit[key] fruit = Fruit(key, value) print("Retrieved fruit " + fruit.key) return fruit, BagStatus.OK
def gameInit(): # make variables global and make function access global variables global fruit global fruit_rect global snake global snake_body global fruit_eaten global eaten_fruit_position global score global display_score global set_timer fruit = Fruit(screen_width, screen_height) fruit_rect = fruit.get_rect() snake = Snake(screen_width, screen_height) snake_body = snake.get_body() fruit_eaten = False eaten_fruit_position = 0, 0 score = 0 display_score = False set_timer = False print('Game Initialized')
def test_recall_first_correct_trials_bright(self): # want to test this for manual and random config = {'fruit_to_remember': 'banana', 'manual': True, 'subarea': 2, 'alpha': 0.3, 'num_repeat_visible': 2, 'first_fruit_alpha': True} fruit = Fruit(config) fruit.pos_dict = {} for i in range(config['num_repeat_visible'] + 3): # print('key', fruit.new_subarea_key) # print('manual', fruit.manual) remember, trial_type = fruit.setup_recall_trial(i) # print remember, trial_type # fake what we do in setup_fruit_for_recall_trial if i == 0: fruit.pos_dict['foo'] = 1 # fake that we are saving fruit.new_subarea_key = None # no more moving self.assertEquals(trial_type, 'manual_bright') elif i < config['num_repeat_visible']: self.assertEquals(trial_type, 'repeat_bright') elif i == config['num_repeat_visible']: self.assertEquals(trial_type, 'repeat_alpha') else: self.assertEquals(trial_type, 'repeat')
def main(): apple = Fruit("Apple", 1.50, 3) banana = Fruit("Banana", 2.50, 1) book = Book(70, "The Witcher", "SNNF343249A") price_calculator = PriceCalculator() price_for_apples = apple.accept(price_calculator) price_for_bananas = banana.accept(price_calculator) price_for_books = book.accept(price_calculator)
def run_game(): # Initialize the game configuration pygame.init() ai_settings = Settings() screen = pygame.display.set_mode( (ai_settings.screen_width, ai_settings.screen_height)) pygame.display.set_caption("Snake_game") sn = Snake(ai_settings, screen) fr = Fruit(ai_settings, screen) stats = GameStats(ai_settings) sb = Score(ai_settings, screen, stats) while True: gf.check_event(sn) sn.update() gf.update_fruit(ai_settings, sn, fr, stats, sb) gf.update_screen(ai_settings, screen, sn, fr, sb)
def start(self): """ Start the experiment. """ # Load environment self.load_environment() self.fruit = Fruit(self.config) # print self.fruit # fruit not remembering all_fruit = self.config['fruit'] all_fruit.insert(0, self.config['fruit_to_remember']) num_fruit = self.config['num_fruit'] num_fruit.insert(0, 1) num_fruit_dict = dict(zip(all_fruit, num_fruit)) self.fruit.create_fruit(num_fruit_dict) self.new_trial() # print 'start' Experiment.getInstance().start()
def start(self): """ Start the experiment. """ # print 'start' # load the environment config = Conf.getInstance().getConfig() # Get configuration dictionary. self.load_environment(config) self.fruit = Fruit(config) all_fruit = config['fruit'] num_fruit = config['num_fruit'] if len(num_fruit) == 1: num_fruit = config['num_fruit'] * len(all_fruit) #print('new', num_fruit) num_fruit_dict = dict(zip(all_fruit, num_fruit)) self.fruit.create_fruit(num_fruit_dict) self.fruit.setup_gobananas_trial(self.trial_num) self.log_new_trial() Experiment.getInstance().start()
class BananaRecall: def __init__(self): """ Initialize the experiment """ # Get experiment instance. # print 'init' exp = Experiment.getInstance() # Set session to today's date and time exp.setSessionNum(datetime.datetime.now().strftime("%y_%m_%d_%H_%M")) print exp.getSessionNum() self.config = Conf.getInstance().getConfig() # Get configuration dictionary. # raise an exception here, because config is probably wrong on several accounts # if fruit to remember is none when trying to run bananaRecall if self.config['fruit_to_remember'] is None: raise Exception("fruit_to_remember in config file must have a value") # if on auto-pilot, make sure other configs make sense. if self.config.get('auto_pilot'): self.config['manual'] = False self.config['repeat_recall_fruit'] = False self.config['subarea'] = 10 self.config['first_fruit_alpha'] = False # print config['training'] # print 'load testing', config['testing'] # bring some configuration parameters into variables, so can change these # variables dynamically # list of all possible rewards self.beep_list = self.config['num_beeps'] # how much reward for current fruit self.num_beeps = 0 # toggle if got to fruit location, True means found fruit when wasn't visible, # False means was not looking for fruit # None means found fruit by collision (alpha was greater than 0) self.remembered_location = False # variable to track if we are checking to see if it is time for the avatar # to look for remembered location of fruit self.find_recall_fruit = False # variable to keep track of how long subject has to get to remembered fruit location self.recall_timer = 0 # trigger fruit flashing self.flash_timer = 0 # how long since last reward self.reward_timer = 0 # variable to hold changes in alpha until new trial self.new_alpha = None # variable to change distance goal for invisible recall fruit self.distance_goal = self.config['distance_goal'][1] # get rid of cursor # Models must be attached to self self.env_models = [] win_props = WindowProperties() # print win_props win_props.setCursorHidden(True) # base is global, used by pandaepl from panda3d # would be great to load this so it isn't just a global from nowhere, # but pandaepl makes it impossible base.win.requestProperties(win_props) # Get vr environment object vr = Vr.getInstance() # vr.cTrav.showCollisions(render) # Get avatar object, seems I can't actually see the collision node, ever # avatar = Avatar.getInstance() # collisionNode = avatar.retrNodePath().find('**/+CollisionNode') # collisionNode.show() # collisionNode.setTwoSided(True) # Register Custom Log Entries # This one corresponds to colliding with a fruit Log.getInstance().addType("Yummy", [("Fruit", basestring)], False) # Remembered where the banana was Log.getInstance().addType("Remembered", [("Distance", float)], False) # Reward Log.getInstance().addType('Beeps', [('Reward', int)], False) # Done getting reward, fruit disappears Log.getInstance().addType("Finished", [("Fruit", basestring)], False) # New Trial Log.getInstance().addType("NewTrial", [("Trial", int)], False) # Repeat Trial (only recall fruit is repeated) # If a trial is a repeat configuration Log.getInstance().addType("RepeatTrial", [("Repeat", int)], False) # log if a banana is alpha Log.getInstance().addType("Alpha", [("Alpha", basestring)], False) # Eye data Log.getInstance().addType("EyeData", [("X", float), ("Y", float)], False) self.fruit = None # initialize trial number, in bananaRecall, we are increasing the trial_num at the # beginning instead of the end, so start at -1, so trial_num starts at 0 self.trial_num = -1 # Handle keyboard events vr.inputListen('close', self.close) vr.inputListen("increase_reward", self.increase_reward) vr.inputListen("decrease_reward", self.decrease_reward) vr.inputListen("extra_reward", self.extra_reward) vr.inputListen("increase_alpha", self.change_alpha) vr.inputListen("decrease_alpha", self.change_alpha) vr.inputListen("override_alpha", self.override_alpha) vr.inputListen("toggle_repeat", self.toggle_repeat) vr.inputListen("toggle_manual", self.toggle_manual) vr.inputListen("increase_dist_goal", self.change_goal) vr.inputListen("decrease_dist_goal", self.change_goal) vr.inputListen("NewTrial", self.new_trial) vr.inputListen("subarea_1", self.change_subarea) vr.inputListen("subarea_2", self.change_subarea) vr.inputListen("subarea_3", self.change_subarea) vr.inputListen("subarea_4", self.change_subarea) vr.inputListen("subarea_5", self.change_subarea) vr.inputListen("subarea_6", self.change_subarea) vr.inputListen("subarea_7", self.change_subarea) vr.inputListen("subarea_8", self.change_subarea) vr.inputListen("subarea_9", self.change_subarea) vr.inputListen("subarea_0", self.change_subarea) vr.addTask(Task("frame_loop", lambda task_info: self.frame_loop(), )) # send avatar position to blackrock/plexon if self.config['sendData'] and LOADED_PYDAQ: vr.addTask(Task("sendAvatar", lambda task_info: self.send_avatar_daq())) # set up reward system if self.config['reward'] and LOADED_PYDAQ: self.reward = pydaq.GiveReward() else: self.reward = None # start recording eye position if self.config['eyeData'] and LOADED_PYDAQ: self.gain = self.config['gain'] self.offset = self.config['offset'] self.eye_task = pydaq.EOGTask() self.eye_task.SetCallback(self.get_eye_data) self.eye_task.StartTask() else: self.eye_task = None # send digital signals to blackrock or plexon if self.config['sendData'] and LOADED_PYDAQ: self.send_x_pos_task = pydaq.OutputAvatarXPos() self.send_y_pos_task = pydaq.OutputAvatarYPos() self.daq_events = pydaq.OutputEvents() self.daq_strobe = pydaq.StrobeEvents() else: self.daq_events = None def frame_loop(self): # self.find_recall_fruit means it is time to remember the position of the # fruit. The recall fruit might be visible at low alpha, or invisible, # either way, becomes fully visible when within distance_goal if self.find_recall_fruit: if self.fruit.alpha > 0: recall_dist = self.config['distance_goal'][0] else: recall_dist = self.distance_goal dist_to_banana = self.fruit.check_distance_to_fruit(self.config['fruit_to_remember']) # print('dist to banana', dist_to_banana) if dist_to_banana <= recall_dist: # print dist_to_banana # print 'found it!' self.found_banana() elif self.recall_timer: # print 'check recall timer', self.config['time_to_recall'] # check timer for looking for fruit if check_timer(self.recall_timer, self.config['time_to_recall']): self.recall_timer = 0 # if time is up, no longer checking to see if close to fruit self.find_recall_fruit = None # if flashing fruit, go for it, otherwise start over if self.config['time_to_flash']: print('flash fruit') self.flash_fruit() else: # when we time out, want to skip the banana, and go directly to # cherries. print('time up') self.fruit.fruit_models[self.config['fruit_to_remember']].setStashed(True) self.fruit.fruit_list.remove(self.config['fruit_to_remember']) self.fruit.get_next_fruit() elif self.flash_timer: # if we flashed the fruit to show where it was, check to see if it # is time to turn it off. if check_timer(self.flash_timer, self.config['time_to_flash']): self.new_trial() # check to see if reward timer is on, otherwise safe to give reward if self.reward_timer and check_timer(self.reward_timer, self.config['pulseInterval'] / 1000.0): self.reward_timer = 0 if not self.reward_timer and self.fruit.beeps >= 0: # we can give reward, since there is currently no reward timer going self.give_reward() def give_reward(self): # print 'give reward' # set reward timer self.reward_timer = time.clock() if self.reward: # print('beep', self.fruit.beeps) self.reward.pumpOut() else: print('beep', self.fruit.beeps) # if this is first reward, log that if self.fruit.beeps == 0: VLQ.getInstance().writeLine("Yummy", [self.fruit.current_fruit]) # print('logged', self.fruit.byeBanana) # print('fruit pos', self.fruit.fruitModels[int(self.fruit.byeBanana[-2:])].getPos()) if self.daq_events: self.daq_events.send_signal(200) self.daq_strobe.send_signal() # amount of reward can vary if self.fruit.current_fruit == self.fruit.config['fruit_to_remember'] and self.remembered_location: # extra reward # print self.fruit.current_fruit # print 'yes!' self.num_beeps = self.beep_list[0] else: # print self.beep_list[1] # print 'small reward' self.num_beeps = self.beep_list[1] # log which reward we are on VLQ.getInstance().writeLine('Beeps', [int(self.fruit.beeps)]) if self.daq_events: self.daq_events.send_signal(201) self.daq_strobe.send_signal() # increment reward self.fruit.beeps += 1 # if that was last reward if self.fruit.beeps == self.num_beeps: # reward is over # print 'reward over' self.fruit.beeps = None # if fruit visible, fruit disappears # new trial if we are out of fruit # or if we found recall fruit and are moving to location # for random, may want to check if this was an alpha or not? new_trial = False if self.find_recall_fruit is None: # print('either found alpha or remembered') # print('check to see if we are moving') self.fruit.change_alpha_fruit('off') self.remembered_location = False # after finding recall fruit, we may be re-starting, # if key press for new subarea or if not repeating if self.fruit.new_subarea_key or not self.fruit.repeat: new_trial = True self.fruit.disappear_fruit() # avatar can move Avatar.getInstance().setMaxTurningSpeed(self.config['fullTurningSpeed']) Avatar.getInstance().setMaxForwardSpeed(self.config['fullForwardSpeed']) # new fruit appears, either starting over or next fruit in stack if not self.fruit.fruit_list or new_trial: self.new_trial() else: self.fruit.get_next_fruit() def found_banana(self): # VLQ.getInstance().writeLine("Remembered", [dist_to_banana]) # change fruit alpha (make visible), and move so directly in front of avatar if self.fruit.alpha == 0: self.fruit.move_recall_fruit_to_avatar() self.fruit.change_alpha_fruit('on') self.remembered_location = True # no longer checking location self.find_recall_fruit = None def get_eye_data(self, eye_data): # pydaq calls this function every time it calls back to get eye data VLQ.getInstance().writeLine("EyeData", [((eye_data[0] * self.gain[0]) - self.offset[0]), ((eye_data[1] * self.gain[1]) - self.offset[1])]) def send_avatar_daq(self): avatar = Avatar.getInstance() # max voltage is 5 volts. Kiril's courtyard is not actually square, # 10 in one direction, 11 in the other, so multiply avatar position by 0.4 # to send voltage self.send_x_pos_task.send_signal(avatar.getPos()[0] * 0.2) self.send_y_pos_task.send_signal(avatar.getPos()[1] * 0.2) def send_new_trial_daq(self): self.daq_events.send_signal(1000 + self.trial_num) self.daq_strobe.send_signal() for model in self.fruit.fruit_models.itervalues(): # can't send negative numbers or decimals, so # need to translate the numbers # print i.getPos() translate_b = [int((model.getPos()[0] - self.config['min_x']) * 1000), int((model.getPos()[1] - self.config['min_y']) * 1000)] self.daq_events.send_signal(translate_b[0]) self.daq_strobe.send_signal() self.daq_events.send_signal(translate_b[1]) self.daq_strobe.send_signal() def new_trial(self): # print self.fruit.fruit_area # print 'new trial' self.flash_timer = 0 self.trial_num += 1 # can change alpha now # print('alpha in recall', self.new_alpha) if self.new_alpha is not None: self.fruit.alpha = self.new_alpha self.new_alpha = None self.find_recall_fruit = self.fruit.start_recall_trial(self.trial_num) # print('time to remember', self.find_recall_fruit) if self.find_recall_fruit: # this will only matter if there is fruit to remember self.recall_timer = time.clock() # print 'set timer', self.recall_timer # print('new trial', self.trial_num) if self.daq_events: self.send_new_trial_daq() def load_environment(self): load_models() # print self.config['environ'] for item in PlaceModels._registry: # print item.group # print item.name if self.config['environ'] in item.group: # print item.name item.model = self.config['path_models'] + item.model # print item.model model = Model(item.name, item.model, item.location) if item.callback is not None: # print 'not none' model.setCollisionCallback(eval(item.callback)) model.setScale(item.scale) model.setH(item.head) self.env_models.append(model) def flash_fruit(self): # print 'flash fruit' # flash where banana was, full alpha # turn on timer for flash self.fruit.change_alpha_fruit('on') self.flash_timer = time.clock() def increase_reward(self, inputEvent): self.beep_list = [x+1 for x in self.beep_list] print('increase reward, now:', self.beep_list) def decrease_reward(self, inputEvent): self.beep_list = [x-1 for x in self.beep_list] print('decrease reward, now:', self.beep_list) def extra_reward(self, inputEvent=None): # print 'yup' if self.reward: self.reward.pumpOut() def toggle_repeat(self, input_event): # toggle repeat self.fruit.repeat = not self.fruit.repeat # which is the opposite of repeat... print "Fruit is repeat:", self.fruit.repeat def toggle_manual(self, input_event): # toggle manual self.fruit.manual = not self.fruit.manual # if we are manually choosing fruit, always repeat # until a new place is chosen. if self.fruit.manual: self.fruit.repeat = True print "Fruit is manual:", self.fruit.manual def change_alpha(self, input_event): # print('change alpha') print input_event.eventName # print self.new_alpha if self.new_alpha is None: # print 'get alpha', self.new_alpha self.new_alpha = self.fruit.alpha if input_event.eventName == 'increase_alpha': self.new_alpha += 0.05 else: self.new_alpha -= 0.05 if self.new_alpha > 1.0: self.new_alpha = 1.0 elif self.new_alpha < 0.05: self.new_alpha = 0 print 'new alpha', self.new_alpha def override_alpha(self, input_event): # make alpha banana brighter self.fruit.change_alpha_fruit('on') def change_goal(self, input_event): # print('change alpha') print input_event.eventName if input_event.eventName == 'increase_dist_goal': self.distance_goal += 0.5 else: self.distance_goal -= 0.5 if self.distance_goal < 0.5: self.distance_goal = 0 print 'new distance goal', self.distance_goal def change_subarea(self, input_event): print('change subarea') # print input_event print input_event.eventName # print input_event.eventName[-1] # send this to fruit, to update position or subarea self.fruit.choose_recall_position(int(input_event.eventName[-1])) # print('banana', self.fruit.fruit_area) def start(self): """ Start the experiment. """ # Load environment self.load_environment() self.fruit = Fruit(self.config) # print self.fruit # fruit not remembering all_fruit = self.config['fruit'] all_fruit.insert(0, self.config['fruit_to_remember']) num_fruit = self.config['num_fruit'] num_fruit.insert(0, 1) num_fruit_dict = dict(zip(all_fruit, num_fruit)) self.fruit.create_fruit(num_fruit_dict) self.new_trial() # print 'start' Experiment.getInstance().start() def close(self, inputEvent): if self.eye_task: self.eye_task.StopTask() self.eye_task.ClearTask() Experiment.getInstance().stop()
def __init__(self, fruitName): Fruit.__init__(self) self.fruitName = fruitName
class GoBananas: def __init__(self): """ Initialize the experiment """ # Get experiment instance. # print 'init' exp = Experiment.getInstance() # exp.setSessionNum(0) # Set session to today's date and time exp.setSessionNum(datetime.datetime.now().strftime("%y_%m_%d_%H_%M")) print exp.getSessionNum() # I should go ahead and make config a class variable. Is in memory, because # it is a class variable in fruit, so doubling many variables here. self.config = Conf.getInstance().getConfig() # Get configuration dictionary. print 'environment: ', self.config['environ'] # print config['training'] # print 'load testing', config['testing'] # bring some configuration parameters into memory, so we don't need to # reload the config file multiple times, also allows us to change these # variables dynamically # base.setFrameRateMeter(True) # Models must be attached to self self.env_models = [] # num_beeps keeps track of reward for fruit we just ran into self.num_beeps = 0 # in case we haven't set reward for different fruit, make reward same for all fruit reward_list = self.config.get('num_beeps', 3 * len(self.config['fruit'])) if len(reward_list) == 1: reward_list = self.config['num_beeps'] * len(self.config['fruit']) elif len(self.config['fruit']) != len(reward_list): raise Exception("Fix the length of num_beeps!") self.beep_dict = dict(zip(self.config['fruit'], reward_list)) self.config.setdefault('go_alpha', None) # print self.beep_dict # cross_hair gets changed, so go ahead and make a new variable self.cross_hair = self.config['crosshair'] self.x_start_c = None self.x_stop_c = None if self.cross_hair: self.x_alpha = 1 # get rid of cursor win_props = WindowProperties() # print win_props win_props.setCursorHidden(True) # win_props.setOrigin(20, 20) # make it so windows aren't on top of each other # win_props.setSize(800, 600) # normal panda window # base is global, used by pandaepl from panda3d # would be great to load this so it isn't just a global from nowhere, # but pandaepl makes it impossible base.win.requestProperties(win_props) # print base.win.requestProperties(win_props) # base.setFrameRateMeter(True) # window2 = base.openWindow() # win_props.setOrigin(800, 200) # make it so windows aren't on top of each other # win_props.setSize(800, 600) # if no resolution given, assume normal panda window # window2.requestProperties(win_props) # # camera = base.camList[0] # camera.reparentTo(render) # # camera2 = base.camList[1] # camera.reparentTo(render) # Get vr environment object vr = Vr.getInstance() # vr.cTrav.showCollisions(render) # Register Custom Log Entries # This one corresponds to colliding with a banana Log.getInstance().addType("Yummy", [("Banana", basestring)], False) # Reward Log.getInstance().addType('Beeps', [('Reward', int)], False) # Done getting reward, banana disappears Log.getInstance().addType("Finished", [("Banana", basestring)], False) # New Trial Log.getInstance().addType("NewTrial", [("Trial", int)], False) # Aborted Trial Log.getInstance().addType("Aborted", ["Aborted"], True) # Eye data Log.getInstance().addType("EyeData", [("X", float), ("Y", float)], False) # If a trial is a repeat configuration Log.getInstance().addType("RepeatTrial", [("Repeat", int)], False) # log if a banana is alpha Log.getInstance().addType("Alpha", [("Alpha", basestring)], False) # initialize fruit_models self.fruit = None # initialize trial number self.trial_num = 0 # Handle keyboard events vr.inputListen('close', self.close) vr.inputListen("increase_reward", self.increase_reward) vr.inputListen("decrease_reward", self.decrease_reward) vr.inputListen("increase_bananas", self.increase_bananas) vr.inputListen("decrease_bananas", self.decrease_bananas) vr.inputListen("override_alpha", self.override_alpha) vr.inputListen("extra_reward", self.extra_reward) vr.inputListen("restart", self.restart) # set up task to be performed between frames, checks at interval of pump vr.addTask(Task("check_reward", lambda task_info: self.check_reward(), self.config['pulseInterval'])) if self.config['go_alpha']: self.find_alpha = True vr.addTask(Task("check_alpha", lambda task_info: self.alpha_frame_loop())) # send avatar position to blackrock/plexon if self.config['sendData'] and LOADED_PYDAQ: vr.addTask(Task("sendAvatar", lambda task_info: self.avatar_frame_loop())) # set up reward system if self.config['reward'] and LOADED_PYDAQ: self.reward = pydaq.GiveReward() else: self.reward = None # start recording eye position if self.config['eyeData'] and LOADED_PYDAQ: # gain and offset can be changed in the program self.gain = self.config['gain'] self.offset = self.config['offset'] self.eye_task = pydaq.EOGTask() self.eye_task.SetCallback(self.get_eye_data) self.eye_task.StartTask() else: self.eye_task = None # send digital signals to blackrock or plexon if self.config['sendData'] and LOADED_PYDAQ: self.send_x_pos_task = pydaq.OutputAvatarXPos() self.send_y_pos_task = pydaq.OutputAvatarYPos() self.send_events = pydaq.OutputEvents() self.send_strobe = pydaq.StrobeEvents() # self.send_events = None else: self.send_pos_task = None self.send_events = None def alpha_frame_loop(self): # check to see if subject has found the alpha fruit yet this trial if self.find_alpha: #print 'find the alpha banana' dist_to_banana = self.fruit.check_distance_to_fruit(self.fruit.alpha_fruit) if dist_to_banana <= self.config.get('distance_goal', 1): # turn on banana to full #print 'change alpha' self.fruit.change_alpha_fruit('on', self.fruit.alpha_fruit) self.find_alpha = False def avatar_frame_loop(self): avatar = Avatar.getInstance() # max voltage is 5 volts. Kiril's courtyard is not actually square, # 10 in one direction, 11 in the other, so multiply avatar position by 0.4 # to send voltage self.send_x_pos_task.send_signal(avatar.getPos()[0] * 0.2) self.send_y_pos_task.send_signal(avatar.getPos()[1] * 0.2) def check_reward(self): # Runs every 200ms # checks to see if we are giving reward (beeps is not None). # If we are, there was a collision, and avatar can't move and # banana hasn't disappeared yet. # After last reward, banana disappears and avatar can move. current_fruit = self.fruit.current_fruit if self.fruit.beeps is None: return elif self.fruit.beeps == 0: # just ran into it, log which banana VLQ.getInstance().writeLine("Yummy", [current_fruit]) # send signal if self.send_events: self.send_events.send_signal(200) self.send_strobe.send_signal() # log if alpha was turned on if self.fruit.fruit_models[current_fruit].retrNodePath().getTransparency(): # print 'alpha' alpha = self.fruit.fruit_models[current_fruit].retrNodePath().getColorScale()[3] VLQ.getInstance().writeLine("Alpha", [current_fruit + ' ' + str(alpha)]) # print('yummy', current_fruit) # print('banana pos', self.fruit.bananaModels[int(current_fruit[-2:])].getPos()) # determine how much reward we are giving self.num_beeps = self.get_reward_level(current_fruit) # Still here? Give reward! if self.reward: self.reward.pumpOut() # print('beep', self.fruit.beeps) else: print('beep', self.fruit.beeps) VLQ.getInstance().writeLine('Beeps', [int(self.fruit.beeps)]) if self.send_events: self.send_events.send_signal(201) self.send_strobe.send_signal() # increment reward self.fruit.beeps += 1 # If done, get rid of banana # print 'beeps', self.fruit.beeps # print 'extra', self.extra # print 'stashed', self.fruit.stashed if self.fruit.beeps == self.num_beeps: # banana disappears self.fruit.disappear_fruit() # if the list is empty, new trial if not self.fruit.fruit_list: self.trial_num += 1 if self.config['go_alpha']: self.find_alpha = True self.fruit.setup_gobananas_trial(self.trial_num) # logging for new trial self.log_new_trial() # avatar can move Avatar.getInstance().setMaxTurningSpeed(self.config['fullTurningSpeed']) Avatar.getInstance().setMaxForwardSpeed(self.config['fullForwardSpeed']) # reward is over self.fruit.beeps = None def get_reward_level(self, current_fruit): # current_fruit is going to have a number representation at the end to make it unique, # so don't use last three indices # print current_fruit # proof we can increase reward for alpha... # if self.fruit.fruit_models[current_fruit].retrNodePath().getTransparency(): # print 'alpha' reward = self.beep_dict[current_fruit[:-3]] if len(self.fruit.fruit_list) == 1: # last fruit reward *= self.config['extra'] return reward def get_eye_data(self, eye_data): # pydaq calls this function every time it calls back to get eye data VLQ.getInstance().writeLine("EyeData", [((eye_data[0] * self.gain[0]) - self.offset[0]), ((eye_data[1] * self.gain[1]) - self.offset[1])]) def log_new_trial(self): # print('new trial', self.trial_num) if self.send_events: self.send_events.send_signal(1000 + self.trial_num) self.send_strobe.send_signal() for model in self.fruit.fruit_models.itervalues(): # can't send negative numbers or decimals, so # need to translate the numbers translate_b = [int((model.getPos()[0] - self.config['min_x']) * 1000), int((model.getPos()[1] - self.config['min_y']) * 1000)] self.send_events.send_signal(translate_b[0]) self.send_strobe.send_signal() self.send_events.send_signal(translate_b[1]) self.send_strobe.send_signal() if self.fruit.repeat: self.send_events.send_signal(300) self.send_strobe.send_signal() self.send_events.send_signal(self.fruit.repeat_list[2]) self.send_strobe.send_signal() def load_environment(self, config): load_models() # print config['environ'] for item in PlaceModels._registry: # print item.group # print item.name if config['environ'] in item.group: # print item.name item.model = config['path_models'] + item.model # print item.model model = Model(item.name, item.model, item.location) if item.callback is not None: # print 'not none' model.setCollisionCallback(eval(item.callback)) # white wall is bright, and sometimes hard to see bananas, # quick fix. # model.nodePath.setColor(0.8, 0.8, 0.8, 1.0) model.setScale(item.scale) model.setH(item.head) self.env_models.append(model) if self.cross_hair: # Cross hair # color changes for cross_hair # to get it to change color, will need to implement a ray self.x_start_c = Point4(1, 1, 1, self.x_alpha) self.x_stop_c = Point4(1, 0, 0, self.x_alpha) self.cross_hair = TextNode('cross_hair') self.cross_hair.setText('+') text_node_path = base.aspect2d.attachNewNode(self.cross_hair) text_node_path.setScale(0.2) # cross_hair is always in center, but # need it to be in same place as collisionRay is, but it appears that center is # at the bottom left of the collisionRay, and the top right of the text, so they # don't have center in the same place. Makes more sense to move text than ray. # These numbers were scientifically determined. JK, moved around until the cross looked # centered on the ray # cross_hair_pos = Point3(0, 0, 0) # cross_hair_pos = Point3(-0.07, 0, -0.05) cross_hair_pos = Point3(-0.055, 0, -0.03) # print text_node_path.getPos() text_node_path.setPos(cross_hair_pos) def increase_reward(self, input_event): # increase all rewards by one self.beep_dict = {key: value + 1 for key, value in self.beep_dict.items()} def decrease_reward(self, input_event): # decrease all rewards by one self.beep_dict = {key: value - 1 for key, value in self.beep_dict.items()} def increase_bananas(self, input_event): pass def decrease_bananas(self, input_event): pass def override_alpha(self, input_event): # make alpha banana brighter self.fruit.change_alpha_fruit('on', self.fruit.alpha_fruit) def restart(self, input_event): # print 'current trial aborted, new trial started' self.trial_num += 1 self.fruit.setup_gobananas_trial(self.trial_num) def extra_reward(self, input_event): # print 'yup' if self.reward: self.reward.pumpOut() def start(self): """ Start the experiment. """ # print 'start' # load the environment config = Conf.getInstance().getConfig() # Get configuration dictionary. self.load_environment(config) self.fruit = Fruit(config) all_fruit = config['fruit'] num_fruit = config['num_fruit'] if len(num_fruit) == 1: num_fruit = config['num_fruit'] * len(all_fruit) #print('new', num_fruit) num_fruit_dict = dict(zip(all_fruit, num_fruit)) self.fruit.create_fruit(num_fruit_dict) self.fruit.setup_gobananas_trial(self.trial_num) self.log_new_trial() Experiment.getInstance().start() def close(self, input_event): if self.eye_task: self.eye_task.close() if self.send_events: self.send_events.close() self.send_strobe.close() if self.reward: self.reward.close() Experiment.getInstance().stop()