def spawnTileUI(self): elems = [] i = 0 for tile in self.tiles: if tile["type"] == "follow": elem = tile["ui_elem"] elem["key"] = f"Tile-{i}-UI" elem["position"] = [ -140, -self.TILE_UI_ELEM_HEIGHT * (i - (len([tile for tile in self.tiles if tile["type"] == "follow"]) - 1) / 2), ] elems.append(elem) i += 1 for i, spawned in enumerate(ScriptLoader.instance.loadElements(elems)): self.tiles[i]["ui_spawned"] = spawned self.tiles[i]["checker"].onSpawn() self.can_complete_box = visualFactory( name="Rectangle", width=6, height=6, fill="UI_tilebox_not_complete", stroke="#ffffff", stroke_width=0.1, zPos=5, position=(-138, -self.tileUIHeight / 2 + self.TILE_UI_PADDING / 2 + 3), ) self.line_reentry_box = visualFactory( name="Rectangle", width=6, height=6, fill="UI_tilebox_not_complete", stroke="#ffffff", stroke_width=0.1, zPos=5, position=(-128, -self.tileUIHeight / 2 + self.TILE_UI_PADDING / 2 + 3), ) ScreenObjectManager.instance.registerVisual(self.can_complete_box, "can_complete") ScreenObjectManager.instance.registerVisual(self.line_reentry_box, "line_reentry") ScriptLoader.instance.object_map["rescueBGMid"].scale = (1, self.tileUIHeight / self.TILE_UI_INITIAL_HEIGHT) ScriptLoader.instance.object_map["rescueBGMid"].calculatePoints() ScriptLoader.instance.object_map["rescueBGTop"].position = (-146.6, self.tileUIHeight / 2) ScriptLoader.instance.object_map["rescueBGBottom"].position = (-146.6, -self.tileUIHeight / 2) ScriptLoader.instance.object_map["rescueScoreSum"].position = ( -110, -self.tileUIHeight / 2 + self.TILE_UI_PADDING / 2, ) ScriptLoader.instance.object_map["touchesTitle"].position = ( ScriptLoader.instance.object_map["touchesTitle"].position[0], self.tileUIHeight / 2 - self.TILE_UI_PADDING / 2, ) ScriptLoader.instance.object_map["touchesCount"].position = ( ScriptLoader.instance.object_map["touchesCount"].position[0], self.tileUIHeight / 2 - self.TILE_UI_PADDING / 2, ) ScriptLoader.instance.object_map["touchesScore"].position = ( ScriptLoader.instance.object_map["touchesScore"].position[0], self.tileUIHeight / 2 - self.TILE_UI_PADDING / 2, ) self.touchesChanged()
def addResponse(self, message): # Handle if matches expected. Give a specific colour. self.given.append(message) if len(self.given) <= len( self.expected) and self.given[-1] == self.expected[ len(self.given) - 1]: col = self.GOOD_BG else: col = self.BAD_BG key = f"given-{len(self.given)}" text = visualFactory( **{ "name": "Text", "hAlignment": "l", "vAlignment": "baseline", "text": self.given[-1], "font_style": "fonts/Poppins-Regular.ttf", "fill": col, "font_size": 20, "position": [-95, 50 - 9 * len(self.given)], "zPos": 5, "key": key, }) self.object_keys.append(key) ScreenObjectManager.instance.registerVisual(text, key)
def loadElements(self, items): # Handle any programmatic color references. elements = [] from ev3sim.devices.base import initialise_device for item in items: assert "key" in item and "type" in item, f"Each item requires a key and type. {item}" if item["type"] == "visual": vis = visualFactory(**item) vis.key = item["key"] ScreenObjectManager.instance.registerVisual(vis, vis.key) self.object_map[item["key"]] = vis elements.append(vis) elif item["type"] == "object": devices = [] to_remove = [] for x in range(len(item.get("children", []))): if item["children"][x]["type"] == "device": devices.append(item["children"][x]) to_remove.append(x) for x in to_remove[::-1]: del item["children"][x] obj = objectFactory(**item) obj.key = item["key"] for index, device in enumerate(devices): # Instantiate the devices. initialise_device(device, obj, index) if item.get("physics", False): World.instance.registerObject(obj) ScreenObjectManager.instance.registerObject(obj, obj.key) self.object_map[obj.key] = obj elements.append(obj) return elements
def setUpAlien(self): self.alien_centre = ScriptLoader.instance.object_map["IR_BALL"] self.alien_radius = visualFactory( **{ "name": "Circle", "radius": self.spawn_radius, "stroke_width": 0, "zPos": 2.5, "sensorVisible": True, } ) ScreenObjectManager.instance.registerVisual(self.alien_radius, "alien-radius")
def initFromKwargs(self, **kwargs): self._rotation = 0 self.children = [] self.parent = None if 'visual' in kwargs: self.visual = visualFactory(**kwargs['visual']) self.position = kwargs.get('position', (0.5, 0.5)) self.rotation = kwargs.get('rotation', 0) for i, child in enumerate(kwargs.get('children', [])): child['key'] = kwargs['key'] + f'-child-{i}' self.children.append(objectFactory(**child)) self.children[-1].parent = self self.key = kwargs['key'] self.updateVisualProperties()
def initFromKwargs(self, **kwargs): self._rotation = 0 self.children = [] self.parent = None if "visual" in kwargs: self.visual = visualFactory(**kwargs["visual"]) self.position = kwargs.get("position", (0, 0)) self.rotation = kwargs.get("rotation", 0) for i, child in enumerate(kwargs.get("children", [])): child["key"] = kwargs["key"] + f"-child-{i}" self.children.append(objectFactory(**child)) self.children[-1].parent = self self.key = kwargs["key"] self.updateVisualProperties()
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.time_tick = 0 self.hover_rect = visualFactory( name="Rectangle", width=30, height=30, position=(0, 0), fill=None, stroke="#ff0000", stroke_width=1, zPos=20, ) self.hover_rect.key = "hover_rect"
def updateSelectPlacement(self): if self.selected_index is not None: hoverRect = visualFactory( name="Rectangle", width=30, height=30, position=( self.tile_offset[0] + 30 * self.selected_index[0], self.tile_offset[1] + 30 * self.selected_index[1], ), fill=None, stroke="#ff0000", stroke_width=1, zPos=20, ) hoverRect.customMap = self.customMap hoverRect.calculatePoints() if "hoverRect" in ScreenObjectManager.instance.objects: ScreenObjectManager.instance.unregisterVisual("hoverRect") ScreenObjectManager.instance.registerVisual(hoverRect, "hoverRect")
def postInstructions(self): self.words = [ f"{col} has r {self.COLORS[col][0]}, g {self.COLORS[col][1]}, b {self.COLORS[col][2]}" for col in self.chosen_colors ] self.words.insert(0, f"There are {self.n_colors} colours") self.show = self.words[:] for word in self.words: ScriptLoader.instance.postInput(word) self.loadThemeData() self.visible_text = pygame_gui.elements.UITextBox( html_text="<br> <br>".join(self.show), relative_rect=pygame.Rect( 1.7 * self._size[0] / 15 + self._size[0] / 2, 5 * self._size[1] / 20, 0.95 * self._size[0] / 2 - 1.7 * self._size[0] / 15, self._size[1] * 6 / 10, ), manager=self, object_id=pygame_gui.core.ObjectID("text_instructions", "instruction_text"), ) self.keys = [] for i, col in enumerate(self.chosen_colors): key = f"arrow-{i}" obj = visualFactory( **{ "name": "Rectangle", "width": 5, "height": 5, "fill": self.COLORS[col], "stroke": "#000000", "stroke_width": 0.1, "zPos": 2, "position": [17.5, 24 - 9.7 * i], "key": key }) ScreenObjectManager.instance.registerVisual(obj, key) self.keys.append(key)
def spawnPosition(self): for x in range(self.TARGETS[1]): if f"place-{x}" in ScreenObjectManager.instance.objects: ScreenObjectManager.instance.unregisterVisual(f"place-{x}") self.setBotPos() n_targets = random.randint(*self.TARGETS) offset = random.randint(0, 359) places = self.PLACES[:] random.shuffle(places) self.commands = [] for x in range(n_targets): distance = random.randint(20, 40) bearing = int(360 * x / n_targets + offset) % 360 self.commands.append((places[x], bearing, distance)) obj = visualFactory( **{ "name": "Image", "image_path": f"custom/Locations/ui/{places[x]}.png", "position": [ distance * np.cos(bearing * np.pi / 180), distance * np.sin(bearing * np.pi / 180) ], "fill": [ 255 * x for x in hsl_to_rgb(random.randint(0, 359), 1, 0.5) ], "scale": 1.3, "zPos": 3 }) ScreenObjectManager.instance.registerVisual(obj, f"place-{x}") self.restartBots() ScriptLoader.instance.postInput(str(n_targets)) for s, b, d in self.commands: ScriptLoader.instance.postInput(f"{s} is {d} away at {b} degrees.") location = random.randint(0, n_targets - 1) ScriptLoader.instance.postInput(f"Go to {self.commands[location][0]}")
def setUpGoal(self): self.alien = objectFactory( **{ "visual": {"name": "Image", "image_path": "custom/Social Distancing/ui/ship.png", "scale": 1, "zPos": 3}, "physics": True, "key": "target", } ) World.instance.registerObject(self.alien) ScreenObjectManager.instance.registerObject(self.alien, "target") self.distance_rect = visualFactory( **{ "name": "Rectangle", "width": 5, "height": 90, "fill": "#00ff00", "zPos": 3 } ) ScreenObjectManager.instance.registerVisual(self.distance_rect, "rect")
def startUp(self): super().startUp() self.posted = False self.ball = objectFactory( **{ "visual": {"name": "Circle", "radius": 2, "fill": "#000000", "zPos": 10}, "physics": True, "key": "falling_ball", "position": [0, 130], "friction": 0.75 } ) self.ball.shape.collision_type = self.BALL_COLLISION_TYPE World.instance.registerObject(self.ball) ScreenObjectManager.instance.registerObject(self.ball, self.ball.key) ended_cutoffs = [0] + self.CUTOFFS + [self.N_POINTS] sq_width = 200 / self.N_POINTS * 0.8 barricade_width = (200 - (sq_width * self.N_POINTS)) / self.N_POINTS for x in range(1, len(ended_cutoffs)): for y in range(ended_cutoffs[x-1], ended_cutoffs[x]): key = f"square_{y}" square = objectFactory( **{ "visual": {"name": "Rectangle", "width": sq_width, "height": 10, "fill": f"area_{x}_color", "zPos": 3}, "physics": True, "key": key, "position": [ 200 * (y + 0.5) / self.N_POINTS - 100, -70, ] } ) square.shape.sensor = True square.shape.collision_type = self.SQUARE_COLLISION_TYPE square.shape.sq_index = (x+1, y+1) World.instance.registerObject(square) ScreenObjectManager.instance.registerObject(square, key) num = visualFactory( **{ "name": "Text", "text": str(y+1), "font_style": "fonts/Poppins-Regular.ttf", "fill": "#000000", "font_size": 24, "position": [ 200 * (y + 0.5) / self.N_POINTS - 100, -70, ], "hAlignment": "m", "vAlignment": "m", "zPos": 5, "key": f"text_{y}", } ) ScreenObjectManager.instance.registerVisual(num, f"text_{y}") for y in range(self.N_POINTS + 1): key = f"barricade_{y}" barricade = objectFactory( **{ "visual": {"name": "Rectangle", "width": barricade_width, "height": 15, "fill": "#000000", "zPos": 3}, "physics": True, "static": True, "key": key, "position": [ y * 200 / self.N_POINTS - 100, -67.5, ] } ) World.instance.registerObject(barricade) ScreenObjectManager.instance.registerObject(barricade, key) for x in range(self.bumper_lines): more = x % 2 == 0 for y in range(self.double_spots // 2 + more): key = f"bumper_{x}_{y}" position = [ 200 / (self.double_spots + 1) * ((2*y+1) if more else (2*y+2)) - 100, -55 + (x+1) * self.bumper_y_distance, ] bumper = objectFactory( **{ "visual": {"name": "Circle", "radius": self.bumper_radius, "fill": "#000000", "zPos": 3}, "physics": True, "static": True, "key": key, "position": position, } ) World.instance.registerObject(bumper) ScreenObjectManager.instance.registerObject(bumper, key) ScriptLoader.instance.object_map["drop"].shape.sensor = True handler = World.instance.space.add_collision_handler(self.BALL_COLLISION_TYPE, self.SQUARE_COLLISION_TYPE) saved_world_no = World.instance.spawn_no def handle_collide(arbiter, space, data): if World.instance.spawn_no != saved_world_no: return a, b = arbiter.shapes if not hasattr(a, "sq_index"): a, b = b, a self.onFallen(a.sq_index) return False handler.begin = handle_collide
def respawn(self, difficulty): if difficulty == "Easy": n_actions = 5 opposite_chance = 0.3 reverse_chance = -0.0001 ranged_opposite_chance = -0.0001 elif difficulty == "Medium": n_actions = 10 opposite_chance = 0.2 reverse_chance = 0.2 ranged_opposite_chance = -0.0001 elif difficulty == "Hard": n_actions = 20 opposite_chance = 0.05 reverse_chance = 0.05 ranged_opposite_chance = 0.1 else: raise ValueError(f"Unexpected difficulty {difficulty}") self.actions = [ random.choice(list(self.MAPPING.keys())) for _ in range(n_actions) ] self.relative_ball_positions = [] mih, mah, miv, mav = 0, 0, 0, 0 ch, cv = 0, 0 for action in self.actions: dx, dy = self.MAPPING[action] ch += dx cv += dy self.relative_ball_positions.append((ch, cv)) mih = min(mih, ch) mah = max(mah, ch) miv = min(miv, cv) mav = max(mav, cv) self.bot_spawn_position = [ self.MIDDLE_COORD[0] + self.UNIT_DISTANCE * (-mih - mah) / 2, self.MIDDLE_COORD[1] + self.UNIT_DISTANCE * (-miv - mav) / 2, ] self.ball_positions = [( self.bot_spawn_position[0] + x * self.UNIT_DISTANCE, self.bot_spawn_position[1] + y * self.UNIT_DISTANCE, ) for x, y in self.relative_ball_positions] # Decide on the directives. self.directives = [[idx, action] for idx, action in enumerate(self.actions)] random.shuffle(self.directives) inserted_directives = [] for x in range(len(self.directives)): # Should there be a crazy directive at index x? if random.random() < opposite_chance: inserted_directives.append([x, "OPPOSITE", None]) elif random.random() < reverse_chance / (1 - opposite_chance): inserted_directives.append([x, "REVERSE", None]) elif random.random() < ranged_opposite_chance / ( 1 - opposite_chance - reverse_chance): length = random.randint(1, len(self.actions) - 1) position = random.randint(0, len(self.actions) - length - 1) inserted_directives.append( [x, "RANGED_OPPOSITE", (position, position + length)]) for idx, action, arg in inserted_directives[::-1]: if action == "OPPOSITE": for x in range(idx + 1): self.directives[x][1] = self.OPPOSITES[self.directives[x] [1]] elif action == "REVERSE": for x in range(idx + 1): self.directives[x][0] = len( self.actions) - self.directives[x][0] - 1 self.directives[x][1] = self.OPPOSITES[self.directives[x] [1]] elif action == "RANGED_OPPOSITE": for x in range(idx + 1): if arg[0] <= self.directives[x][0] <= arg[1]: self.directives[x][1] = self.OPPOSITES[ self.directives[x][1]] self.directives.insert(idx + 1, [action, arg]) self.words = [f"Here's how you get home in {len(self.actions)} steps:"] self.show = self.words[:] for d0, d1 in self.directives: if d0 == "OPPOSITE": self.words.append( "For everything I've said - I meant the opposite.") self.show.append( "For everything I've said - I meant the <b>opposite</b>.") elif d0 == "REVERSE": self.words.append( "For everything I've said - They were to go from home to here!" ) self.show.append( "For everything I've said - They were to go <b>from</b> home <b>to</b> here!" ) elif d0 == "RANGED_OPPOSITE": self.words.append( f"For all steps from {d1[0]+1} to {d1[1]+1}, I meant the opposite." ) self.show.append( f"For all steps from {d1[0]+1} to {d1[1]+1}, I meant the <b>opposite</b>." ) else: self.words.append(f"Step number {d0+1} is to go {d1}.") self.show.append(f"Step number {d0+1} is to go <i>{d1}</i>.") self.words.append("And then you're home!") self.show.append("And then you're home!") for word in self.words: ScriptLoader.instance.postInput(word) if hasattr(self, "visible_text"): self.visible_text.kill() self.loadThemeData() self.visible_text = pygame_gui.elements.UITextBox( html_text="<br>".join(self.show), relative_rect=pygame.Rect( 1.25 * self._size[0] / 15 + self._size[0] / 2, self._size[1] / 20, self._size[0] / 2 - 1.25 * self._size[0] / 15, self._size[1] * 9 / 10, ), manager=self, object_id=pygame_gui.core.ObjectID("text_instructions", "instruction_text"), ) for key in self.keys: ScreenObjectManager.instance.unregisterVisual(key) self.keys = [] for i, action in enumerate(self.actions): key = f"arrow-{i}" obj = visualFactory( **{ "name": "Image", "image_path": f"custom/Inconsistent Directions/ui/arrow.png", "hAlignment": "m", "vAlignment": "m", "zPos": 2, "scale": 0.025, "position": [40, 92 - 15 * i], "rotation": self.ROTATION[action] * math.pi / 180, "key": key }) ScreenObjectManager.instance.registerVisual(obj, key) self.keys.append(key) self.reset()
def restart(self): keys = ([f"{x}-{y}-text" for x in range(13) for y in range(13)] + [f"{x}-{y}-bg" for x in range(13) for y in range(13)] + [f"{x}-row" for x in range(14)] + [f"{y}-col" for y in range(14)] + [f"{x}-row-title" for x in range(13)] + [f"{y}-col-title" for y in range(13)]) for key in keys: if key in ScreenObjectManager.instance.objects: ScreenObjectManager.instance.unregisterVisual(key) self.times_width = random.randint(1, 12) self.times_height = random.randint(1, 12) top_left = (-85, 65) bottom_right = (15, -45) s_width = bottom_right[0] - top_left[0] s_height = top_left[1] - bottom_right[1] for x in range(self.times_width): for y in range(self.times_height): text = visualFactory( **{ "name": "Text", "text": "??", "font_style": "fonts/Poppins-Regular.ttf", "fill": "text_color", "font_size": 24, "position": [ top_left[0] + s_width * (x + 1.5) / (1 + self.times_width), top_left[1] - s_height * (y + 1.5) / (1 + self.times_height), ], "hAlignment": "m", "vAlignment": "m", "zPos": 4, "key": f"{x}-{y}-text", }) ScreenObjectManager.instance.registerVisual( text, f"{x}-{y}-text") bg = visualFactory( **{ "name": "Rectangle", "width": s_width / (1 + self.times_width), "height": s_height / (1 + self.times_height), "position": [ top_left[0] + s_width * (x + 1.5) / (1 + self.times_width), top_left[1] - s_height * (y + 1.5) / (1 + self.times_height), ], "fill": "default_text_bg", "zPos": 3, "key": f"{x}-{y}-bg", }) ScreenObjectManager.instance.registerVisual(bg, f"{x}-{y}-bg") for x in range(self.times_width + 1): line = Line() line.initFromKwargs( start=[ top_left[0] + s_width * (x + 1) / (1 + self.times_width), top_left[1], ], end=[ top_left[0] + s_width * (x + 1) / (1 + self.times_width), bottom_right[1], ], fill="line_color", zPos=5, ) ScreenObjectManager.instance.registerVisual(line, f"{x}-row") for y in range(self.times_height + 1): line = Line() line.initFromKwargs( start=[ top_left[0], top_left[1] - s_height * (y + 1) / (1 + self.times_height), ], end=[ bottom_right[0], top_left[1] - s_height * (y + 1) / (1 + self.times_height), ], fill="line_color", zPos=5, ) ScreenObjectManager.instance.registerVisual(line, f"{y}-col") for x in range(self.times_width): text = visualFactory( **{ "name": "Text", "text": str(x + 1), "font_style": "fonts/Poppins-Regular.ttf", "fill": "text_color", "font_size": 24, "position": [ top_left[0] + s_width * (x + 1.5) / (1 + self.times_width), top_left[1] - s_height * (0.5) / (1 + self.times_height), ], "hAlignment": "m", "vAlignment": "m", "zPos": 4, "key": f"{x}-row-title", }) ScreenObjectManager.instance.registerVisual(text, f"{x}-row-title") for y in range(self.times_height): text = visualFactory( **{ "name": "Text", "text": str(y + 1), "font_style": "fonts/Poppins-Regular.ttf", "fill": "text_color", "font_size": 24, "position": [ top_left[0] + s_width * (0.5) / (1 + self.times_width), top_left[1] - s_height * (y + 1.5) / (1 + self.times_height), ], "hAlignment": "m", "vAlignment": "m", "zPos": 4, "key": f"{y}-col-title", }) ScreenObjectManager.instance.registerVisual(text, f"{y}-col-title") self.animating_spots = [] self.animation_time = 0 self.solved = 0 self.failed = False ScriptLoader.instance.postInput(str(self.times_height)) ScriptLoader.instance.postInput(str(self.times_width)) self.setMood("neutral") self.restartBots()
def test_visual_factory(): with pytest.raises(ValueError) as e: visualFactory(**{})
def update(self, dt): super().update(dt) if self.animation_time > 0: self.animation_time -= dt while self.animation_time <= 0 and len(self.animation_requests) > 0: name, index, weather = self.animation_requests[0] self.animation_requests = self.animation_requests[1:] # Decide on position. if name == "Start": y_pos = 65 - (index // 16) * 16 x_pos = -90 + (index % 16) * 12 fill = self.NEUTRAL_BG else: y_pos = 20 - 25 * (name) x_pos = -90 + index * 12 fill = self.BAD_BG if name < len(self.solutions): if index < len(self.solutions[name]): if self.solutions[name][index] == weather: fill = self.GOOD_BG else: key3 = f"{name}-{index}-correction" obj3 = visualFactory( **{ "name": "Image", "image_path": f"custom/Days of the Month/ui/{self.WEATHER_ICONS[self.solutions[name][index]]}", "hAlignment": "m", "vAlignment": "m", "zPos": 2, "scale": 0.5, "position": [x_pos, y_pos + 10], "key": key3 }) self.object_keys.append(key3) ScreenObjectManager.instance.registerVisual( obj3, key3) key1 = f"{name}-{index}" key2 = f"{name}-{index}-box" obj1 = visualFactory( **{ "name": "Image", "image_path": f"custom/Days of the Month/ui/{self.WEATHER_ICONS[weather]}", "hAlignment": "m", "vAlignment": "m", "zPos": 2, "scale": 0.5, "position": [x_pos, y_pos], "key": key1 }) obj2 = visualFactory( **{ "name": "Rectangle", "width": 10, "height": 10, "stroke": "#000000", "stroke_width": 0.4, "fill": fill, "zPos": 1, "position": [x_pos, y_pos], "key": key2, }) self.object_keys.append(key1) self.object_keys.append(key2) ScreenObjectManager.instance.registerVisual(obj1, key1) ScreenObjectManager.instance.registerVisual(obj2, key2) if len(self.animation_requests ) == 0 or self.animation_requests[0][0] != name: self.animation_time += self.SEPARATE_WAIT else: self.animation_time += self.IN_BETWEEN_WAIT
def resetRescueVisual(self): from ev3sim.visual.manager import ScreenObjectManager from ev3sim.simulation.loader import ScriptLoader from ev3sim.presets.rescue import RescueInteractor ScriptLoader.instance.reset() ScriptLoader.instance.startUp() ScreenObjectManager.instance.resetVisualElements() with open(find_abs("rescue.yaml", preset_locations()), "r") as f: conf = yaml.safe_load(f) utils.GLOBAL_COLOURS.update(conf.get("colours", {})) r = RescueInteractor() r.TILE_DEFINITIONS = self.current_tiles r.CAN_SPAWN_POSITION = (self.previous_info.get("settings", {}).get( "rescue", {}).get("CAN_SPAWN_POSITION", [0, 0])) self.customMap = { "SCREEN_WIDTH": self._size[0], "SCREEN_HEIGHT": self._size[1], "MAP_WIDTH": 293.3, "MAP_HEIGHT": 200, } placeableArea = visualFactory( name="Rectangle", width=8 * 30, height=6 * 30, position=(15 + self.tile_offset[0], -15 + self.tile_offset[1]), fill="#6f6f6f", ) placeableArea.customMap = self.customMap placeableArea.calculatePoints() ScreenObjectManager.instance.registerVisual(placeableArea, "placeableArea") remove = [] for key in ScreenObjectManager.instance.objects: if key.startswith("tile-entry"): remove.append(key) for key in remove: ScreenObjectManager.instance.unregisterVisual(key) r.spawnTiles() for index, tile in enumerate(r.tiles): direction, rotation = self.getDirsAndRotations(tile) if tile["type"] == "follow": for i, entry_dir in enumerate(tile["entries"]): startArrow = visualFactory( name="Polygon", verts=[ [1.96, 0], [0.21, 1.75], [0.21, 0.5], [-1.4, 0.5], [-1.4, -0.5], [0.21, -0.5], [0.21, -1.75], [1.96, 0], ], fill="#219ebc", stroke_width=0, zPos=0.1, sensorVisible=False, rotation=rotation[entry_dir], ) startArrow.key = f"tile-{index}-entry-{i}" startArrow.position = [ tile["world_pos"][0] + self.tile_offset[0] + direction[entry_dir][0] * 11, tile["world_pos"][1] + self.tile_offset[1] + direction[entry_dir][1] * 11, ] startArrow.customMap = self.customMap startArrow.calculatePoints() ScreenObjectManager.instance.registerVisual( startArrow, startArrow.key) for obj in tile["all_elems"]: obj.position = [ obj.position[0] + self.tile_offset[0], obj.position[1] + self.tile_offset[1], ] if isinstance(obj, IVisualElement): obj.customMap = self.customMap obj.calculatePoints() elif isinstance(obj, BaseObject): obj.visual.customMap = self.customMap obj.visual.calculatePoints() for obj in r.connecting_objs: obj.customMap = self.customMap obj.position = [ obj.position[0] + self.tile_offset[0], obj.position[1] + self.tile_offset[1], ] r.spawnCan() r.can_obj.visual.customMap = self.customMap r.can_obj.body.position = [ a + b for a, b in zip(r.can_obj.body.position, self.tile_offset) ] r.can_obj.position = np.array(r.can_obj.body.position) r.can_obj.visual.calculatePoints() self.can_obj = r.can_obj self.current_tile_objects = r.tiles self.updateSelectPlacement()
def spawnPosition(self): self.setBotPos() for but in self.buttons: World.instance.unregisterObject(but) self.buttons = [] self.states = [random.randint(0, 2) for _ in range(3)] for x in range(3): c_key = f"movement_bot_colour-{x}" o_key = f"movement_bot-button-{x}" if c_key in ScreenObjectManager.instance.objects: ScreenObjectManager.instance.unregisterVisual(c_key) if o_key in ScreenObjectManager.instance.objects: ScreenObjectManager.instance.unregisterVisual(o_key) for y in range(3): if o_key + f"-{y}" in ScreenObjectManager.instance.objects: ScreenObjectManager.instance.unregisterVisual(o_key + f"-{y}") c_obj = visualFactory( name="Rectangle", width=5, height=5, position=[ self.INDICATOR_POSITIONS[x], -35, ], fill=self.COLOURS[self.states[x]], sensorVisible=True, stroke_width=0, zPos=0.5, ) ScreenObjectManager.instance.registerVisual(c_obj, c_key) buttonLight = visualFactory( name="Circle", radius=0.5, fill=self.COLOURS[self.states[x]], position=[ self.X_POSITIONS[x], self.Y_POSITIONS[self.states[x]], ], stroke_width=0, zPos=0.6, ) ScreenObjectManager.instance.registerVisual(buttonLight, o_key) for y in range(3): button = objectFactory(visual={ "name": "Rectangle", "width": 5, "height": 5, "fill": "#666666", "stroke_width": 0.1, "stroke": "#ffffff", "zPos": 0.5, }, position=[ self.X_POSITIONS[x], self.Y_POSITIONS[y], ], physics=True, key=o_key + f"-{y}") button.shape.sensor = True button.shape.collision_type = self.BALL_COLLISION_TYPE button.shape.movement_index = (x, y) self.buttons.append(button) World.instance.registerObject(button) ScreenObjectManager.instance.registerObject( button, o_key + f"-{y}") self.restartBots()
def loadMap(self, map_path): # load map custom_dir = find_abs_directory("workspace/custom/") full_path = join(custom_dir, "Memory Maze", map_path) with open(full_path, "r") as f: conf = yaml.safe_load(f) # Despawn old stuff for col in self.colours: ScreenObjectManager.instance.unregisterVisual(col.key) self.colours = [] for wall in self.walls: ScreenObjectManager.instance.unregisterVisual(wall.key) World.instance.unregisterObject(wall) self.walls = [] self.dimensions = conf["dimensions"] self.spawn = conf["spawn"] self.passcode = conf["passcode"] self.colour_map = conf["colours"] self.wall_map = conf["walls"] self.rotation = conf.get("rotation", 0) * math.pi / 180 # Spawn colours for x in range(self.dimensions[0]): for y in range(self.dimensions[1]): index = self.colour_map[y * self.dimensions[0] + x] if index == "_": continue c_key = f"movement_bot_colour-{x}-{y}" c_obj = visualFactory( name="Rectangle", width=self.width - self.margin, height=self.width - self.margin, position=[ self.width * (x - self.offset[0]), -self.width * (y - self.offset[1]), ], fill=self.COLOURS[index], sensorVisible=True, stroke_width=0, zPos=0.5, ) c_obj.key = c_key ScreenObjectManager.instance.registerVisual(c_obj, c_key) self.colours.append(c_obj) # Spawn walls # First, vertical for x in range(self.dimensions[0] + 1): for y in range(self.dimensions[1]): if self.wall_map[(y + 1) * self.dimensions[0] + y * (self.dimensions[0] + 1) + x] == "*": wall_key = f"movement_bot_wall-vert-{x}-{y}" wall_obj = objectFactory( visual={ "name": "Rectangle", "height": self.width, "width": 2, "stroke_width": 0, "fill": "#000000", "zPos": 0.7, }, position=[ (x - 0.5 - self.offset[0]) * self.width, -self.width * (y - self.offset[1]), ], rotation=0, physics=True, static=True, key=wall_key) self.walls.append(wall_obj) World.instance.registerObject(wall_obj) ScreenObjectManager.instance.registerObject( wall_obj, wall_key) # Next, horizontal for x in range(self.dimensions[0]): for y in range(self.dimensions[1] + 1): if self.wall_map[y * (2 * self.dimensions[0] + 1) + x] == "*": wall_key = f"movement_bot_wall-horizontal-{x}-{y}" wall_obj = objectFactory( visual={ "name": "Rectangle", "height": 2, "width": self.width, "stroke_width": 0, "fill": "#000000", "zPos": 0.7, }, position=[ (x - self.offset[0]) * self.width, -self.width * (y - self.offset[1] - 0.5), ], rotation=0, physics=True, static=True, key=wall_key) self.walls.append(wall_obj) World.instance.registerObject(wall_obj) ScreenObjectManager.instance.registerObject( wall_obj, wall_key)