Example #1
0
    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()
Example #2
0
    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()
Example #3
0
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)
Example #4
0
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)