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, model, surface_manager, action_factory, rng, rules_engine, configuration, screen): """ Default constructor """ super(MapScreen, self).__init__() self.model = model self.surface_manager = surface_manager self.action_factory = action_factory self.rng = rng self.rules_engine = rules_engine self.configuration = configuration self.screen = screen self.keymap, self.move_key_map = self._construct_keymaps( configuration.controls) self.move_controller = MoveController(action_factory, rng) self.messages = []
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 MapScreen(): """ Class for map screen .. versionadded:: 0.9 """ @log_debug def __init__(self, model, surface_manager, action_factory, rng, rules_engine, configuration, screen): """ Default constructor """ super(MapScreen, self).__init__() self.model = model self.surface_manager = surface_manager self.action_factory = action_factory self.rng = rng self.rules_engine = rules_engine self.configuration = configuration self.screen = screen self.keymap, self.move_key_map = self._construct_keymaps( configuration.controls) self.move_controller = MoveController(action_factory, rng) self.messages = [] @log_debug 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.action_a: keymap[key] = self._action_a for key in config.back: keymap[key] = self._back return keymap, move_keymap @log_info def show(self): """ Show the map """ self.refresh_screen() player = self.model.player while self.model.end_condition == 0 and player.level is not None: next_creature = self.model.get_next_creature(self.rules_engine) if next_creature == player: self._handle_player_input() elif next_creature is not None: next_creature.act() else: self.model.end_condition = DIED_IN_DUNGEON self.refresh_screen() dialog = EndScreen(model = self.model, dying_rules = self.rules_engine.dying_rules, screen = self.screen, controller = EndScreenController()) dialog.show() @log_debug def _handle_player_input(self): """ Handle input from player """ key = chr(self.screen.getch()) if key in self.keymap: self.keymap[key](key) elif key == 'i': inv = InventoryScreen(character = self.model.player, config = self.configuration, screen = self.screen, action_factory = self.action_factory, parent = self.screen) inv.show() elif key == 'c': dialog = CharacterScreen(character = self.model.player, screen = self.screen) dialog.show() elif key == 'a': dir_key = chr(self.screen.getch()) if dir_key in self.move_key_map: direction = self.move_key_map[dir_key] pyherc.vtable['\ufdd0:attack'](self.model.player, direction) elif key == 'Q': self.model.end_condition = 1 @log_debug def _move(self, key): """ Process movement key :param key: key triggering the processing :type key: string """ direction = self.move_key_map[key] self.move_controller.move_or_attack(self.model.player, direction) @log_debug def _back(self, key): """ Process back key :param key: key triggering the processing :type key: int .. versionadded:: 0.10 """ pyherc.vtable['\ufdd0:wait'](self.model.player, Duration.fast) @log_debug def _action_a(self, key): """ Process action a key :param key: key triggering the processing :type key: int """ player = self.model.player level = player.level items = level.get_items_at(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, 'walk', self.action_factory): pyherc.vtable['\ufdd0:move'](player, 9, self.action_factory) @log_debug def refresh_screen(self): """ Draw whole screen """ player = self.model.player level = player.level if level is None: return for column_number, column in enumerate(level.floor): for row_number, tile in enumerate(column): self.screen.addch(row_number + 1, column_number, ord(self.surface_manager.get_icon(tile)), self.surface_manager.get_attribute_by_name('dim')) for column_number, column in enumerate(level.walls): for row_number, tile in enumerate(column): glyph_number = self.surface_manager.get_icon(tile) if glyph_number is not None: self.screen.addch(row_number + 1, column_number, ord(glyph_number), self.surface_manager.get_attribute_by_name('dim')) for portal in level.portals: self.screen.addch(portal.location[1] + 1, portal.location[0], ord(self.surface_manager.get_icon(portal.icon)), self.surface_manager.get_attribute(portal.icon)) for item in level.items: self.screen.addch(item.location[1] + 1, item.location[0], ord(self.surface_manager.get_icon(item.icon)), self.surface_manager.get_attribute(item.icon)) for monster in level.creatures: self.screen.addch(monster.location[1] + 1, monster.location[0], ord(self.surface_manager.get_icon(monster.icon)), self.surface_manager.get_attribute(monster.icon)) self.screen.addch(player.location[1] + 1, player.location[0], ord(self.surface_manager.get_icon(player.icon)), self.surface_manager.get_attribute(player.icon)) stats = 'HP:{0}({1}) MG:{2}({3})'.format(player.hit_points, player.max_hp, 0, 0) stats = stats.ljust(80) self.screen.addstr(22, 0, stats) self.screen.refresh() @log_debug def receive_event(self, event): """ Receive event """ if event.event_type == 'move': self.refresh_screen() if event.mover == self.model.player: self.messages = [] self.screen.addstr(0, 0, ' '.ljust(80)) if e_event_type(event) in ['attack hit', 'attack miss', 'attack nothing', 'poison triggered', 'poison ended', 'poisoned', 'heal started', 'heal ended', 'heal triggered', 'death', 'pick up', 'drop', 'damage triggered', 'equip', 'unequip', 'notice', 'lose focus', 'error']: message = event.get_description(self.model.player) self.messages.append(message) if len(self.messages) > 2: self.messages = self.messages[-2:] displayed_messages = ', '.join(self.messages) displayed_messages = displayed_messages.ljust(80) self.screen.addstr(0, 0, displayed_messages)
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 MapScreen(): """ Class for map screen .. versionadded:: 0.9 """ @log_debug def __init__(self, model, surface_manager, action_factory, rng, rules_engine, configuration, screen): """ Default constructor """ super(MapScreen, self).__init__() self.model = model self.surface_manager = surface_manager self.action_factory = action_factory self.rng = rng self.rules_engine = rules_engine self.configuration = configuration self.screen = screen self.keymap, self.move_key_map = self._construct_keymaps( configuration.controls) self.move_controller = MoveController(action_factory, rng) self.messages = [] @log_debug 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.action_a: keymap[key] = self._action_a for key in config.back: keymap[key] = self._back return keymap, move_keymap @log_info def show(self): """ Show the map """ self.refresh_screen() player = self.model.player while self.model.end_condition == 0 and player.level is not None: next_creature = self.model.get_next_creature(self.rules_engine) if next_creature == player: self._handle_player_input() elif next_creature is not None: next_creature.act() else: self.model.end_condition = DIED_IN_DUNGEON self.refresh_screen() dialog = EndScreen(model=self.model, dying_rules=self.rules_engine.dying_rules, screen=self.screen, controller=EndScreenController()) dialog.show() @log_debug def _handle_player_input(self): """ Handle input from player """ key = chr(self.screen.getch()) if key in self.keymap: self.keymap[key](key) elif key == 'i': inv = InventoryScreen(character=self.model.player, config=self.configuration, screen=self.screen, action_factory=self.action_factory, parent=self.screen) inv.show() elif key == 'c': dialog = CharacterScreen(character=self.model.player, screen=self.screen) dialog.show() elif key == 'a': dir_key = chr(self.screen.getch()) if dir_key in self.move_key_map: direction = self.move_key_map[dir_key] pyherc.vtable['\ufdd0:attack'](self.model.player, direction) elif key == 'Q': self.model.end_condition = 1 @log_debug def _move(self, key): """ Process movement key :param key: key triggering the processing :type key: string """ direction = self.move_key_map[key] self.move_controller.move_or_attack(self.model.player, direction) @log_debug def _back(self, key): """ Process back key :param key: key triggering the processing :type key: int .. versionadded:: 0.10 """ pyherc.vtable['\ufdd0:wait'](self.model.player, Duration.fast) @log_debug def _action_a(self, key): """ Process action a key :param key: key triggering the processing :type key: int """ player = self.model.player level = player.level items = level.get_items_at(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, 'walk', self.action_factory): pyherc.vtable['\ufdd0:move'](player, 9, self.action_factory) @log_debug def refresh_screen(self): """ Draw whole screen """ player = self.model.player level = player.level if level is None: return for column_number, column in enumerate(level.floor): for row_number, tile in enumerate(column): self.screen.addch( row_number + 1, column_number, ord(self.surface_manager.get_icon(tile)), self.surface_manager.get_attribute_by_name('dim')) for column_number, column in enumerate(level.walls): for row_number, tile in enumerate(column): glyph_number = self.surface_manager.get_icon(tile) if glyph_number is not None: self.screen.addch( row_number + 1, column_number, ord(glyph_number), self.surface_manager.get_attribute_by_name('dim')) for portal in level.portals: self.screen.addch(portal.location[1] + 1, portal.location[0], ord(self.surface_manager.get_icon(portal.icon)), self.surface_manager.get_attribute(portal.icon)) for item in level.items: self.screen.addch(item.location[1] + 1, item.location[0], ord(self.surface_manager.get_icon(item.icon)), self.surface_manager.get_attribute(item.icon)) for monster in level.creatures: self.screen.addch(monster.location[1] + 1, monster.location[0], ord(self.surface_manager.get_icon(monster.icon)), self.surface_manager.get_attribute(monster.icon)) self.screen.addch(player.location[1] + 1, player.location[0], ord(self.surface_manager.get_icon(player.icon)), self.surface_manager.get_attribute(player.icon)) stats = 'HP:{0}({1}) MG:{2}({3})'.format(player.hit_points, player.max_hp, 0, 0) stats = stats.ljust(80) self.screen.addstr(22, 0, stats) self.screen.refresh() @log_debug def receive_event(self, event): """ Receive event """ if event.event_type == 'move': self.refresh_screen() if event.mover == self.model.player: self.messages = [] self.screen.addstr(0, 0, ' '.ljust(80)) if e_event_type(event) in [ 'attack hit', 'attack miss', 'attack nothing', 'poison triggered', 'poison ended', 'poisoned', 'heal started', 'heal ended', 'heal triggered', 'death', 'pick up', 'drop', 'damage triggered', 'equip', 'unequip', 'notice', 'lose focus', 'error' ]: message = event.get_description(self.model.player) self.messages.append(message) if len(self.messages) > 2: self.messages = self.messages[-2:] displayed_messages = ', '.join(self.messages) displayed_messages = displayed_messages.ljust(80) self.screen.addstr(0, 0, displayed_messages)
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)