def __init__(self, parent, model, surface_manager, action_factory, rng, rules_engine, configuration): """ Default constructor """ super().__init__(parent) self.model = model self.scene = None self.surface_manager = surface_manager self.action_factory = action_factory self.rng = rng self.rules_engine = rules_engine self.configuration = configuration self.current_level = None self.view = None self.animation_adapters = [] self.animation_timers = [] for adapter in range(10): self.animation_adapters.append(TimerAdapter()) self.animation_timers.append(QTimer(self)) self.animation_timers[adapter].timeout.connect(self.animation_adapters[adapter].trigger_animations) self.animation_timers[adapter].start(450 + adapter * 10) self.animations = [] self.move_controller = MoveController(action_factory = action_factory, rng = rng) self.__set_layout() self.keymap, self.move_key_map = self._construct_keymaps( configuration.controls) self.animation_factory = AnimationFactory()
def __init__(self, parent, model, surface_manager, action_factory, rng, rules_engine, configuration): """ Default constructor """ super().__init__(parent) self.model = model self.scene = None self.surface_manager = surface_manager self.action_factory = action_factory self.rng = rng self.rules_engine = rules_engine self.configuration = configuration self.current_level = None self.view = None self.animation_adapters = [] self.animation_timers = [] for adapter in range(10): self.animation_adapters.append(TimerAdapter()) self.animation_timers.append(QTimer(self)) self.animation_timers[adapter].timeout.connect( self.animation_adapters[adapter].trigger_animations) self.animation_timers[adapter].start(450 + adapter * 10) self.animations = [] self.move_controller = MoveController(action_factory=action_factory, rng=rng) self.__set_layout() self.keymap, self.move_key_map = self._construct_keymaps( configuration.controls) self.animation_factory = AnimationFactory()
class PlayMapWidget(QWidget): """ Widget for displaying playing world .. versionadded:: 0.5 """ def __init__(self, parent, model, surface_manager, action_factory, rng, rules_engine, configuration): """ Default constructor """ super().__init__(parent) self.model = model self.scene = None self.surface_manager = surface_manager self.action_factory = action_factory self.rng = rng self.rules_engine = rules_engine self.configuration = configuration self.current_level = None self.view = None self.animation_adapters = [] self.animation_timers = [] for adapter in range(10): self.animation_adapters.append(TimerAdapter()) self.animation_timers.append(QTimer(self)) self.animation_timers[adapter].timeout.connect(self.animation_adapters[adapter].trigger_animations) self.animation_timers[adapter].start(450 + adapter * 10) self.animations = [] self.move_controller = MoveController(action_factory = action_factory, rng = rng) self.__set_layout() self.keymap, self.move_key_map = self._construct_keymaps( configuration.controls) self.animation_factory = AnimationFactory() MenuRequested = pyqtSignal(name='MenuRequested') EndScreenRequested = pyqtSignal(name='EndScreenRequested') NextSpellRequested = pyqtSignal(name='NextSpellRequested') PreviousSpellRequested = pyqtSignal(name='PreviousSpellRequested') def _construct_keymaps(self, config): """ Construct keymaps for handling input """ keymap = {} move_keymap = {} for key in config.move_left: keymap[key] = self._move move_keymap[key] = 7 for key in config.move_up: keymap[key] = self._move move_keymap[key] = 1 for key in config.move_right: keymap[key] = self._move move_keymap[key] = 3 for key in config.move_down: keymap[key] = self._move move_keymap[key] = 5 for key in config.start: keymap[key] = self._menu for key in config.action_a: keymap[key] = self._action_a for key in config.back: keymap[key] = self._back for key in config.left_shoulder: keymap[key] = self._shoulder_left for key in config.right_shoulder: keymap[key] = self._shoulder_right for key in config.mode_1: keymap[key] = self._zoom_out for key in config.mode_2: keymap[key] = self._zoom_in return keymap, move_keymap def __set_layout(self): """ Set layout of this widget """ self.scene = QGraphicsScene() layout = QHBoxLayout() self.view = QGraphicsView(self.scene) self.view.setFocusPolicy(Qt.StrongFocus) self.view.installEventFilter(self) self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) layout.addWidget(self.view) self.setLayout(layout) def construct_scene(self): """ Construct scene to display """ self.__construct_scene(self.model, self.scene) self.model.player.register_for_updates(self) self.model.register_event_listener(self) self.__center_view_on_character(self.model.player) def __center_view_on_character(self, entity): """ Center view on given entity """ location = entity.location width = 32 height = 32 self.view.setSceneRect((location[0] * 32) - width // 2, (location[1] * 32) - height // 2, width, height) def __construct_scene(self, model, scene): """ Constructs scene to display """ for anim in [x for x in self.animations]: anim.stop() anim.clear() for adapter in self.animation_adapters: adapter.glyphs.clear() self.animations = [] scene.clear() self.current_level = model.player.level for location, tile in get_tiles(self.current_level): if tile['\ufdd0:floor']: new_glyph = MapGlyph(self.surface_manager.get_icon(tile['\ufdd0:floor']), None, self.animation_adapters[0]) new_glyph.setZValue(zorder_floor) new_glyph.setPos(location[0] * 32, location[1] * 32) scene.addItem(new_glyph) if tile['\ufdd0:wall']: new_glyph = MapGlyph(self.surface_manager.get_icon(tile['\ufdd0:wall']), None) new_glyph.setZValue(zorder_wall) new_glyph.setPos(location[0] * 32, location[1] * 32) scene.addItem(new_glyph) for tile_id in tile['\ufdd0:ornamentation']: new_glyph = MapGlyph(self.surface_manager.get_icon(tile_id), None, self.rng.choice(self.animation_adapters)) new_glyph.setZValue(zorder_ornament) new_glyph.setPos(location[0] * 32, location[1] * 32) scene.addItem(new_glyph) for item in tile['\ufdd0:items']: self.add_glyph(item, scene, zorder_item) for trap in tile['\ufdd0:traps']: self.add_glyph(trap, scene, zorder_trap) for creature in get_characters(self.current_level): self.add_glyph(creature, scene, zorder_character) def add_glyph(self, entity, scene, z_order): """ Add graphical representation of an entity :param entity: entity to display :param scene: scene where glyph will be added :type scene: QGraphicsScene :param z_order: z-order of entity being displayed :type z_order: int """ new_glyph = MapGlyph(self.surface_manager.get_icon(entity.icon), entity, self.rng.choice(self.animation_adapters)) new_glyph.setZValue(z_order) new_glyph.setPos(entity.location[0] * 32, entity.location[1] * 32) scene.addItem(new_glyph) def remove_glyph(self, entity): """ Remove graphical representation of an entity """ glyphs = [x for x in self.view.items() if (hasattr(x, 'entity')) and (x.entity == entity)] for glyph in glyphs: self.view.scene().removeItem(glyph) def receive_event(self, event): """ Receive event from model """ anim = self.animation_factory.create_animation(event) anim.trigger(self) def remove_finished_animation(self): """ Remove finished animation """ finished_animations = [x for x in self.animations if x.state() == QAbstractAnimation.Stopped] counters = [x.animationAt(0).targetObject().object_to_animate for x in finished_animations] #TODO: works only if single thing is animated for item in finished_animations: item.clear() self.animations.remove(item) def receive_update(self, event): """ Receive update from entity """ if e_event_type(event) == 'move': if self.model.player.level != self.current_level: self.__construct_scene(self.model, self.scene) self.__center_view_on_character(self.model.player) def eventFilter(self, qobject, event): #pylint: disable-msg=C0103 """ Filter events .. Note:: This is done in order to process cursor keys """ result = False if event.type() == QEvent.KeyPress: self.keyPressEvent(event) result = True elif event.type() == QEvent.MouseButtonPress: self.mouseEvent(event) result = True else: result = super().eventFilter(qobject, event) return result def mouseEvent(self, event): """ Handle mouse events """ if self.model.player is None: return player = self.model.player next_creature = self.model.get_next_creature(self.rules_engine) if next_creature == player: point = self.view.mapToScene(event.pos()) x = int(point.x() / 32) y = int(point.y() / 32) player = self.model.player level = player.level location = player.location # if player was clicked, take stairs or open menu if (x, y) == location: if get_portal(level, location): if pyherc.vtable['\ufdd0:is-move-legal'](player, 9): pyherc.vtable['\ufdd0:move'](player, 9) else: self.MenuRequested.emit() elif is_move(event, player, (x, y)): # TODO: maybe moving should be possible with mouse? move(event, player, (x, y)) else: direction = find_direction(location, (x, y)) distance = distance_between(location, (x, y)) if distance == 1: #melee attack? if pyherc.vtable['\ufdd0:is-attack-legal'](player, direction): pyherc.vtable['\ufdd0:attack'](player, direction) else: if (location[0] == x) or (location[1] == y): if pyherc.vtable['\ufdd0:is-attack-legal'](player, direction): pyherc.vtable['\ufdd0:attack'](player, direction) self.process_npc() def keyPressEvent(self, event): #pylint: disable-msg=C0103 """ Handle key events """ if self.model.player is None: return key_code = event.key() player = self.model.player next_creature = self.model.get_next_creature(self.rules_engine) if next_creature == player: if key_code in self.keymap: self.keymap[key_code](key_code, event.modifiers()) self.process_npc() def process_npc(self): """ Process npc characters """ player = self.model.player next_creature = self.model.get_next_creature(self.rules_engine) if next_creature is None: self.model.end_condition = DIED_IN_DUNGEON while (next_creature != player and next_creature is not None and self.model.end_condition == 0): next_creature.act() next_creature = self.model.get_next_creature(self.rules_engine) if next_creature is None: self.model.end_condition = DIED_IN_DUNGEON if self.model.end_condition != 0: self.EndScreenRequested.emit() def _move(self, key, modifiers): """ Process movement key :param key: key triggering the processing :type key: int """ player = self.model.player direction = self.move_key_map[key] if modifiers & Qt.ControlModifier: if direction != 9: pyherc.vtable['\ufdd0:attack'](player, direction) elif modifiers & Qt.AltModifier: if direction != 9: cast(player, direction, 'fireball') else: self.move_controller.move_or_attack(player, direction) def _menu(self, key, modifiers): """ Process menu key :param key: key triggering the processing :type key: int """ self.MenuRequested.emit() def _back(self, key, modifiers): """ Process back key :param key: key triggering the processing :type key: int """ pyherc.vtable['\ufdd0:wait'](self.model.player, Duration.fast) def _zoom_in(self, key, modifiers): """ Zoom map in """ self.view.scale(1.1, 1.1) def _zoom_out(self, key, modifiers): """ Zoom map out """ self.view.scale(0.9, 0.9) def _shoulder_right(self, key, modifiers): """ Process right shoulder button :param key: key triggering the processing :type key: int .. versionadded:: 0.10 """ self.NextSpellRequested.emit() def _shoulder_left(self, key, modifiers): """ Process left shoulder button :param key: key triggering the processing :type key: int .. versionadded:: 0.10 """ self.PreviousSpellRequested.emit() def _action_a(self, key, modifiers): """ Process action a key :param key: key triggering the processing :type key: int """ player = self.model.player level = player.level items = list(get_items(level, player.location)) if items is not None and len(items) > 0: pick_up(player, items[0]) elif pyherc.vtable['\ufdd0:is-move-legal'](player, 9): pyherc.vtable['\ufdd0:move'](player, 9) elif is_dig_legal(player): dig(player)
class PlayMapWidget(QWidget): """ Widget for displaying playing world .. versionadded:: 0.5 """ def __init__(self, parent, model, surface_manager, action_factory, rng, rules_engine, configuration): """ Default constructor """ super().__init__(parent) self.model = model self.scene = None self.surface_manager = surface_manager self.action_factory = action_factory self.rng = rng self.rules_engine = rules_engine self.configuration = configuration self.current_level = None self.view = None self.animation_adapters = [] self.animation_timers = [] for adapter in range(10): self.animation_adapters.append(TimerAdapter()) self.animation_timers.append(QTimer(self)) self.animation_timers[adapter].timeout.connect( self.animation_adapters[adapter].trigger_animations) self.animation_timers[adapter].start(450 + adapter * 10) self.animations = [] self.move_controller = MoveController(action_factory=action_factory, rng=rng) self.__set_layout() self.keymap, self.move_key_map = self._construct_keymaps( configuration.controls) self.animation_factory = AnimationFactory() MenuRequested = pyqtSignal(name='MenuRequested') EndScreenRequested = pyqtSignal(name='EndScreenRequested') NextSpellRequested = pyqtSignal(name='NextSpellRequested') PreviousSpellRequested = pyqtSignal(name='PreviousSpellRequested') def _construct_keymaps(self, config): """ Construct keymaps for handling input """ keymap = {} move_keymap = {} for key in config.move_left: keymap[key] = self._move move_keymap[key] = 7 for key in config.move_up: keymap[key] = self._move move_keymap[key] = 1 for key in config.move_right: keymap[key] = self._move move_keymap[key] = 3 for key in config.move_down: keymap[key] = self._move move_keymap[key] = 5 for key in config.start: keymap[key] = self._menu for key in config.action_a: keymap[key] = self._action_a for key in config.back: keymap[key] = self._back for key in config.left_shoulder: keymap[key] = self._shoulder_left for key in config.right_shoulder: keymap[key] = self._shoulder_right for key in config.mode_1: keymap[key] = self._zoom_out for key in config.mode_2: keymap[key] = self._zoom_in return keymap, move_keymap def __set_layout(self): """ Set layout of this widget """ self.scene = QGraphicsScene() layout = QHBoxLayout() self.view = QGraphicsView(self.scene) self.view.setFocusPolicy(Qt.StrongFocus) self.view.installEventFilter(self) self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) layout.addWidget(self.view) self.setLayout(layout) def construct_scene(self): """ Construct scene to display """ self.__construct_scene(self.model, self.scene) self.model.player.register_for_updates(self) self.model.register_event_listener(self) self.__center_view_on_character(self.model.player) def __center_view_on_character(self, entity): """ Center view on given entity """ location = entity.location width = 32 height = 32 self.view.setSceneRect((location[0] * 32) - width // 2, (location[1] * 32) - height // 2, width, height) def __construct_scene(self, model, scene): """ Constructs scene to display """ for anim in [x for x in self.animations]: anim.stop() anim.clear() for adapter in self.animation_adapters: adapter.glyphs.clear() self.animations = [] scene.clear() self.current_level = model.player.level for location, tile in get_tiles(self.current_level): if tile['\ufdd0:floor']: new_glyph = MapGlyph( self.surface_manager.get_icon(tile['\ufdd0:floor']), None, self.animation_adapters[0]) new_glyph.setZValue(zorder_floor) new_glyph.setPos(location[0] * 32, location[1] * 32) scene.addItem(new_glyph) if tile['\ufdd0:wall']: new_glyph = MapGlyph( self.surface_manager.get_icon(tile['\ufdd0:wall']), None) new_glyph.setZValue(zorder_wall) new_glyph.setPos(location[0] * 32, location[1] * 32) scene.addItem(new_glyph) for tile_id in tile['\ufdd0:ornamentation']: new_glyph = MapGlyph(self.surface_manager.get_icon(tile_id), None, self.rng.choice(self.animation_adapters)) new_glyph.setZValue(zorder_ornament) new_glyph.setPos(location[0] * 32, location[1] * 32) scene.addItem(new_glyph) for item in tile['\ufdd0:items']: self.add_glyph(item, scene, zorder_item) for trap in tile['\ufdd0:traps']: self.add_glyph(trap, scene, zorder_trap) for creature in get_characters(self.current_level): self.add_glyph(creature, scene, zorder_character) def add_glyph(self, entity, scene, z_order): """ Add graphical representation of an entity :param entity: entity to display :param scene: scene where glyph will be added :type scene: QGraphicsScene :param z_order: z-order of entity being displayed :type z_order: int """ new_glyph = MapGlyph(self.surface_manager.get_icon(entity.icon), entity, self.rng.choice(self.animation_adapters)) new_glyph.setZValue(z_order) new_glyph.setPos(entity.location[0] * 32, entity.location[1] * 32) scene.addItem(new_glyph) def remove_glyph(self, entity): """ Remove graphical representation of an entity """ glyphs = [ x for x in self.view.items() if (hasattr(x, 'entity')) and (x.entity == entity) ] for glyph in glyphs: self.view.scene().removeItem(glyph) def receive_event(self, event): """ Receive event from model """ anim = self.animation_factory.create_animation(event) anim.trigger(self) def remove_finished_animation(self): """ Remove finished animation """ finished_animations = [ x for x in self.animations if x.state() == QAbstractAnimation.Stopped ] counters = [ x.animationAt(0).targetObject().object_to_animate for x in finished_animations ] #TODO: works only if single thing is animated for item in finished_animations: item.clear() self.animations.remove(item) def receive_update(self, event): """ Receive update from entity """ if e_event_type(event) == 'move': if self.model.player.level != self.current_level: self.__construct_scene(self.model, self.scene) self.__center_view_on_character(self.model.player) def eventFilter(self, qobject, event): #pylint: disable-msg=C0103 """ Filter events .. Note:: This is done in order to process cursor keys """ result = False if event.type() == QEvent.KeyPress: self.keyPressEvent(event) result = True elif event.type() == QEvent.MouseButtonPress: self.mouseEvent(event) result = True else: result = super().eventFilter(qobject, event) return result def mouseEvent(self, event): """ Handle mouse events """ if self.model.player is None: return player = self.model.player next_creature = self.model.get_next_creature(self.rules_engine) if next_creature == player: point = self.view.mapToScene(event.pos()) x = int(point.x() / 32) y = int(point.y() / 32) player = self.model.player level = player.level location = player.location # if player was clicked, take stairs or open menu if (x, y) == location: if get_portal(level, location): if pyherc.vtable['\ufdd0:is-move-legal'](player, 9): pyherc.vtable['\ufdd0:move'](player, 9) else: self.MenuRequested.emit() elif is_move( event, player, (x, y)): # TODO: maybe moving should be possible with mouse? move(event, player, (x, y)) else: direction = find_direction(location, (x, y)) distance = distance_between(location, (x, y)) if distance == 1: #melee attack? if pyherc.vtable['\ufdd0:is-attack-legal'](player, direction): pyherc.vtable['\ufdd0:attack'](player, direction) else: if (location[0] == x) or (location[1] == y): if pyherc.vtable['\ufdd0:is-attack-legal'](player, direction): pyherc.vtable['\ufdd0:attack'](player, direction) self.process_npc() def keyPressEvent(self, event): #pylint: disable-msg=C0103 """ Handle key events """ if self.model.player is None: return key_code = event.key() player = self.model.player next_creature = self.model.get_next_creature(self.rules_engine) if next_creature == player: if key_code in self.keymap: self.keymap[key_code](key_code, event.modifiers()) self.process_npc() def process_npc(self): """ Process npc characters """ player = self.model.player next_creature = self.model.get_next_creature(self.rules_engine) if next_creature is None: self.model.end_condition = DIED_IN_DUNGEON while (next_creature != player and next_creature is not None and self.model.end_condition == 0): next_creature.act() next_creature = self.model.get_next_creature(self.rules_engine) if next_creature is None: self.model.end_condition = DIED_IN_DUNGEON if self.model.end_condition != 0: self.EndScreenRequested.emit() def _move(self, key, modifiers): """ Process movement key :param key: key triggering the processing :type key: int """ player = self.model.player direction = self.move_key_map[key] if modifiers & Qt.ControlModifier: if direction != 9: pyherc.vtable['\ufdd0:attack'](player, direction) elif modifiers & Qt.AltModifier: if direction != 9: cast(player, direction, 'fireball') else: self.move_controller.move_or_attack(player, direction) def _menu(self, key, modifiers): """ Process menu key :param key: key triggering the processing :type key: int """ self.MenuRequested.emit() def _back(self, key, modifiers): """ Process back key :param key: key triggering the processing :type key: int """ pyherc.vtable['\ufdd0:wait'](self.model.player, Duration.fast) def _zoom_in(self, key, modifiers): """ Zoom map in """ self.view.scale(1.1, 1.1) def _zoom_out(self, key, modifiers): """ Zoom map out """ self.view.scale(0.9, 0.9) def _shoulder_right(self, key, modifiers): """ Process right shoulder button :param key: key triggering the processing :type key: int .. versionadded:: 0.10 """ self.NextSpellRequested.emit() def _shoulder_left(self, key, modifiers): """ Process left shoulder button :param key: key triggering the processing :type key: int .. versionadded:: 0.10 """ self.PreviousSpellRequested.emit() def _action_a(self, key, modifiers): """ Process action a key :param key: key triggering the processing :type key: int """ player = self.model.player level = player.level items = list(get_items(level, player.location)) if items is not None and len(items) > 0: pick_up(player, items[0]) elif pyherc.vtable['\ufdd0:is-move-legal'](player, 9): pyherc.vtable['\ufdd0:move'](player, 9) elif is_dig_legal(player): dig(player)