def __init__( self, name: str, background: BaseTexture, pass_map: PassMap, triggers: List[Trigger], player_position: Vector, scripts: Mapping[str, Callable[[], None]], path: Path, save_point: Optional[Object], ): self.name = name self.background = background self.pass_map = pass_map self.trigger_event_watchers = [ TriggerEventWatcher(trigger) for trigger in triggers ] self.player = Player(player_position) self.scripts = scripts self.path = path self.objects: WalList[Object] = WalList([]) self.named_objects: Dict[str, Object] = {} self.state: dict = {} self.sprites: WalList[BaseSprite] = WalList([]) self.save_point = save_point if save_point is not None: self.add_object(save_point) self._update_callbacks: WalList[Callable[[float], None]] = WalList([]) get_event_manager().subscribe('key:confirm', Subscriber(self.on_interact))
def finalize(self): get_event_manager().subscribe( 'end_of_cycle', Subscriber(lambda *args: get_game().overworld.unfreeze()), ) self.kill() self.on_finish_callback()
def hide(self, on_finish: Callable): self.spawn( RoomTransitionFadeIn( self.game.screen.get_size()).start_animation()) get_event_manager().subscribe( 'room_exit_animation_finished', Subscriber(lambda event_id, arg: on_finish()), )
def on_confirm(self, event, arg): del event, arg if not self.is_alive(): return if self.pages[self.page_index].has_animation_finished(): self.next() get_event_manager().subscribe('key:confirm', Subscriber(self.on_confirm))
def handler(event, arg): del event, arg nonlocal counter counter += 1 if counter == num_awaitables: get_event_manager().raise_event(all_finished_event) else: get_event_manager().subscribe(one_finished_event, Subscriber(handler))
def _on_interact_somewhere(self, *args): del args if not self.is_alive(): return if not get_game().overworld.is_frozen(): player = get_game().overworld.room.player if self.get_hitbox_with_position().colliderect( player.get_extended_hitbox()): self.on_interact() get_event_manager().subscribe('key:confirm', Subscriber(self._on_interact_somewhere))
def load_room(self, room_name: str): logger.debug('Loading room {}', room_name) self._room_ready = False self.freeze() self.spawn( RoomTransitionFadeIn( self.game.screen.get_size()).start_animation()) get_event_manager().subscribe( 'room_exit_animation_finished', Subscriber( lambda event_id, arg: self._run_room_loading_logic(room_name)), )
def on_interact(self, *args): del args if get_game().overworld.room is not self: return if not get_game().overworld.is_frozen(): affected_rect = get_game( ).overworld.room.player.get_extended_hitbox() for watcher in self.trigger_event_watchers: if affected_rect.colliderect(watcher.trigger.rect): watcher.pass_event(Event('interact')) get_event_manager().subscribe('key:confirm', Subscriber(self.on_interact))
def __init__( self, pos: Vector, texture: Optional[BaseTexture] = None, is_passable: bool = False, hitbox: Optional[pg.Rect] = None, ): super().__init__(pos) self.texture = texture self.is_passable = is_passable self.hitbox = hitbox if hitbox is not None else generate_hitbox(20, 20) get_event_manager().subscribe('key:confirm', Subscriber(self._on_interact_somewhere)) self.on_interact: Callable[[], Any] = lambda: None
def _run_room_loading_logic(self, room_name: str, player_pos: Optional[Vector] = None): if self._room_loaded: prev_room_name = self.room.name self.room.kill() else: prev_room_name = 'default' self.room = load_room( Path('.') / 'assets' / 'rooms' / room_name, prev_room_name, player_pos, ) self._room_screen = pg.Surface(self.room.get_size()) self.spawn( RoomTransitionFadeOut( self.game.screen.get_size()).start_animation()) subscriber = Subscriber( lambda event_id, arg: self._finalize_room_loading()) get_event_manager().subscribe('room_enter_animation_finished', subscriber)
async def gather(*awaitables): # XXX: This code is fascinatingly awful, but it serves for a good purpose, # allowing awaiting multiple coroutines at the same time one_finished_event = get_event_manager().unique_id() all_finished_event = get_event_manager().unique_id() counter = 0 num_awaitables = len(awaitables) def handler(event, arg): del event, arg nonlocal counter counter += 1 if counter == num_awaitables: get_event_manager().raise_event(all_finished_event) else: get_event_manager().subscribe(one_finished_event, Subscriber(handler)) get_event_manager().subscribe(one_finished_event, Subscriber(handler)) for aw in awaitables: # WARNING: this code is potentially dangerous, since `aw`, which is changed # by the outer loop, is captured by the inner function. In this very case, # however, everything is fine, because that function is called immediately # and is then discarded. # # TODO: refactor this code to make it more robust and to silence Pylint's # cell-var-from-import warning async def await_and_notify(*args, **kwargs): del args, kwargs await aw get_event_manager().raise_event(one_finished_event) SimpleScript(await_and_notify)() await wait_for_event(all_finished_event)
def wait_for_any_event(): script = get_game().current_script get_event_manager().subscribe_to_any_event(Subscriber(lambda event, arg: script((event, arg)))) return (yield)
def wait_for_event(event_id): script = get_game().current_script get_event_manager().subscribe(event_id, Subscriber(lambda event, arg: script((event, arg)))) return (yield)
def initialize(self): get_game().overworld.freeze() get_event_manager().subscribe('key:confirm', Subscriber(self.on_confirm)) get_event_manager().subscribe('key:cancel', Subscriber(self.on_cancel)) self.next()
def on_cancel(self, event, arg): del event, arg if not self.is_alive(): return self.pages[self.page_index].try_force_finish() get_event_manager().subscribe('key:cancel', Subscriber(self.on_cancel))