Esempio n. 1
0
    def __init__(self, item, **kwargs):
        super().__init__(**kwargs)
        self.camera = self.parent.parent.camera
        self.world = self.parent.parent.world
        self.item = item
        self.dir = (0, 0)
        self.targettile = None
        self.droptile = None

        self.help_pos = DynamicPos(
            (self.game.width // 2,
             self.game.height + constants.MENU_SCALE * 2.5),
            speed=10)
        self.help_pos.move((self.help_pos.x, self.game.height / 2 +
                            constants.TILE_SIZE * constants.MENU_SCALE))

        text_args = {
            "renderer": self.game.renderer,
            "size": 5 * constants.MENU_SCALE,
            "centered": True
        }

        self.help_text = (wgt.Text(**text_args,
                                   text="Pick a direction",
                                   offset=(0, 0),
                                   color=constants.LIGHT_GRAY),
                          wgt.TextLines(**text_args,
                                        text=["Z to throw", "X to cancel"],
                                        offset=(0, 7 * constants.MENU_SCALE)))
Esempio n. 2
0
    def __init__(self, speed, rect_size):
        self._ppt = round(constants.MENU_SCALE * 1.5) * 20
        self._shake = 0
        self._shake_x = 0
        self._shake_y = 0
        self._pos = DynamicPos((0, 0), speed=speed)
        self._rect_size = rect_size

        self._t_lastshake = 0
Esempio n. 3
0
    def __init__(self, item, **kwargs):
        super().__init__(**kwargs)
        self.world = self.parent.parent.world
        self.item = item
        self.options = []
        self.visible = True
        if self.world.has_component(item, c.UseEffect):
            self.options.append("use")
        if self.world.has_component(item, c.Explosive):
            self.options.append("prime")
        self.options.append("throw")
        self.options.append("drop")
        self.size = len(self.options)

        inv_slot_size = constants.TILE_SIZE*constants.MENU_SCALE
        self.pos = (40 + inv_slot_size*2 + 12*constants.MENU_SCALE, self.game.height/2 - inv_slot_size*3)
        image_bottom = self.pos[1]+inv_slot_size*1.5
        self.options_pos = [DynamicPos((self.pos[0], image_bottom + (10 + i*12)*constants.MENU_SCALE), speed=20) for i in range(self.size)]
        self.cursorpos = 0

        audio.play("snap2", replace=True)

        self.widgets = []
        if self.world.has_component(self.item, c.Describable):
            text_x = constants.TILE_SIZE * constants.MENU_SCALE * 1.6
            describe = self.world.entity_component(self.item, c.Describable)
            self.widgets.extend((
                wgt.Text(renderer=self.game.renderer, size=10*constants.MENU_SCALE, text=describe.name, offset=(text_x, 0)),
                wgt.Text(renderer=self.game.renderer, size=5*constants.MENU_SCALE, text=describe.desc, offset=(text_x, 15*constants.MENU_SCALE)),
            ))
Esempio n. 4
0
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.visible = False
        self.cursorpos = [0, 0]
        self.size = [2, 5]
        self.slot_size = constants.TILE_SIZE * constants.MENU_SCALE
        self.pos = DynamicPos((-self.slot_size * 2 - 21,
                               self.game.height / 2 - self.slot_size * 3),
                              speed=10)
        self.image_grid_pos = [0, 0]

        self.widgets = [
            wgt.TextLines(renderer=self.game.renderer,
                          size=5 * constants.MENU_SCALE,
                          offset=(0, -19 * constants.MENU_SCALE),
                          text=["Z to select", "X to return"])
        ]

        self.add_child_scene(ImageGrid,
                             grid_size=self.size,
                             image=self.game.renderer.get_image(
                                 name="inventory-slot",
                                 scale=constants.MENU_SCALE),
                             pos=self.image_grid_pos)
Esempio n. 5
0
class Inventory(Scene):
    """Main inventory menu."""
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.visible = False
        self.cursorpos = [0, 0]
        self.size = [2, 5]
        self.slot_size = constants.TILE_SIZE * constants.MENU_SCALE
        self.pos = DynamicPos((-self.slot_size * 2 - 21,
                               self.game.height / 2 - self.slot_size * 3),
                              speed=10)
        self.image_grid_pos = [0, 0]

        self.widgets = [
            wgt.TextLines(renderer=self.game.renderer,
                          size=5 * constants.MENU_SCALE,
                          offset=(0, -19 * constants.MENU_SCALE),
                          text=["Z to select", "X to return"])
        ]

        self.add_child_scene(ImageGrid,
                             grid_size=self.size,
                             image=self.game.renderer.get_image(
                                 name="inventory-slot",
                                 scale=constants.MENU_SCALE),
                             pos=self.image_grid_pos)

    def handle_input(self, keypress):
        handled = False
        if keypress.has_action(key_input.Action.BACK) or keypress.has_action(
                key_input.Action.INVENTORY_CLOSE):
            handled = True
            self.hide()

        if keypress.has_action(key_input.Action.DIRECTION):
            handled = True
            audio.play("click3", replace=True)
        if keypress.has_action(key_input.Action.UP):
            self.cursorpos[1] = max(self.cursorpos[1] - 1, 0)
        if keypress.has_action(key_input.Action.DOWN):
            self.cursorpos[1] = min(self.cursorpos[1] + 1, self.size[1] - 1)
        if keypress.has_action(key_input.Action.LEFT):
            self.cursorpos[0] = max(self.cursorpos[0] - 1, 0)
        if keypress.has_action(key_input.Action.RIGHT):
            self.cursorpos[0] = min(self.cursorpos[0] + 1, self.size[0] - 1)

        if keypress.has_action(key_input.Action.ACCEPT):
            handled = True
            itempos = self.cursorpos[0] * self.size[1] + self.cursorpos[1]
            items = self.parent.world.entity_component(
                self.parent.world.tags.player, c.Inventory).contents
            if itempos < len(items):
                self.game.set_focus(
                    self.add_child_scene(InventoryOptions, items[itempos]))

        return handled

    def update(self, delta):
        if self.visible or self.game.focus_scene is self:
            self.pos.update(delta)
            if self.pos.x < -self.slot_size * 2 - 20:
                self.visible = False
            else:
                self.visible = True

        for i in range(2):
            self.image_grid_pos[i] = self.pos[i]

    def draw(self, screen):
        if not self.visible:
            return

        drawposx = round(self.pos.x)
        drawposy = round(self.pos.y)

        inventory = self.parent.world.entity_component(
            self.parent.world.tags.player, c.Inventory)

        for widget in self.widgets:
            widget.draw(screen, (drawposx, drawposy))

        for i, entity in enumerate(inventory.contents):
            pos = (drawposx + self.slot_size * (i // self.size[1] + 0.5),
                   drawposy + self.slot_size * (i % self.size[1] + 0.5))
            self.parent.draw_centered_entity(screen, entity,
                                             constants.MENU_SCALE, pos)

        inv_cursor_screenpos = (drawposx + self.slot_size * self.cursorpos[0],
                                drawposy + self.slot_size * self.cursorpos[1])
        screen.blit(
            self.game.renderer.get_image(name="inventory-cursor-box",
                                         scale=constants.MENU_SCALE),
            inv_cursor_screenpos)

    def show(self):
        """Tell inventory to move onscreen."""
        self.pos.move((40, self.pos.y))
        audio.play("snap1", replace=True)
        audio.dim_music()
        self.game.set_focus(self)

    def hide(self):
        """Tell inventory to move offscreen."""
        self.pos.move((-self.slot_size * 2 - 21, self.pos.y))
        audio.play("drop", replace=True)
        audio.undim_music()
        self.game.remove_focus(self)
Esempio n. 6
0
class ThrowOptions(Scene):
    """Throw direction selector once an item has been chosen to throw."""
    scene_properties = {**Scene.scene_properties, "draw_above_parent": False}

    def __init__(self, item, **kwargs):
        super().__init__(**kwargs)
        self.camera = self.parent.parent.camera
        self.world = self.parent.parent.world
        self.item = item
        self.dir = (0, 0)
        self.targettile = None
        self.droptile = None

        self.help_pos = DynamicPos(
            (self.game.width // 2,
             self.game.height + constants.MENU_SCALE * 2.5),
            speed=10)
        self.help_pos.move((self.help_pos.x, self.game.height / 2 +
                            constants.TILE_SIZE * constants.MENU_SCALE))

        text_args = {
            "renderer": self.game.renderer,
            "size": 5 * constants.MENU_SCALE,
            "centered": True
        }

        self.help_text = (wgt.Text(**text_args,
                                   text="Pick a direction",
                                   offset=(0, 0),
                                   color=constants.LIGHT_GRAY),
                          wgt.TextLines(**text_args,
                                        text=["Z to throw", "X to cancel"],
                                        offset=(0, 7 * constants.MENU_SCALE)))

    def handle_input(self, keypress):
        handled = False
        if keypress.has_action(key_input.Action.BACK):
            self.game.set_focus(
                self.parent.add_child_scene(inventory_options.InventoryOptions,
                                            self.item))
            self.remove_scene()
            handled = True

        if keypress.has_action(key_input.Action.DIRECTION):
            self.dir = keypress.get_direction()
            playerpos = self.world.entity_component(self.world.tags.player,
                                                    c.TilePosition)
            self.targettile = [playerpos.x, playerpos.y]
            stopped = False
            distance = 0
            while not stopped:
                self.targettile[0] += self.dir[0]
                self.targettile[1] += self.dir[1]
                distance += 1
                if not self.world.get_system(s.GridSystem).on_grid(
                        self.targettile):
                    self.targettile[0] -= self.dir[0]
                    self.targettile[1] -= self.dir[1]
                    distance -= 1
                    stopped = True
                if self.world.get_system(s.GridSystem).get_blocker_at(
                        self.targettile) != 0:
                    distance -= 1
                    stopped = True
                if distance == 5:
                    stopped = True

            self.droptile = [
                playerpos.x + self.dir[0] * distance,
                playerpos.y + self.dir[1] * distance
            ]

            handled = True

        if keypress.has_action(key_input.Action.ACCEPT):
            if self.droptile is not None:
                self.world.entity_component(self.world.tags.player,
                                            c.Inventory).contents.remove(
                                                self.item)
                self.world.remove_component(self.item, c.Stored)
                self.world.add_component(self.item,
                                         c.TilePosition(*self.droptile))
            if self.targettile is not None:
                target = self.world.get_system(s.GridSystem).get_blocker_at(
                    self.targettile)
                if target:
                    if self.world.has_component(self.item, c.UseEffect):
                        use = self.world.entity_component(
                            self.item, c.UseEffect)
                        for effect in use.effects:
                            getattr(self.parent.parent, effect[0])(target,
                                                                   *effect[1:])
                    if self.world.entity_component(self.item,
                                                   c.Item).consumable:
                        self.world.add_component(self.item, c.Dead())
                self.remove_scene()

            handled = True

        if keypress.has_action(key_input.Action.INVENTORY_CLOSE):
            self.remove_scene()

        return handled

    def update(self, delta):
        self.help_pos.update(delta)

    def draw(self, screen):
        item_x = self.game.width // 2 + self.dir[0] * self.camera.get_zoom() / 2
        item_y = self.game.height // 2 + self.dir[1] * self.camera.get_zoom(
        ) / 2
        self.parent.parent.draw_centered_entity(screen, self.item,
                                                self.camera.get_scale(),
                                                (item_x, item_y))
        if self.targettile is not None:
            crosshair = self.game.renderer.get_image(
                name="crosshair", scale=self.camera.get_scale())
            self.game.renderer.draw_centered_image(
                screen, crosshair,
                self.camera.tile_to_screen_pos(*self.targettile))

        for text in self.help_text:
            text.draw(screen, (self.help_pos.x, self.help_pos.y))
Esempio n. 7
0
class Camera:
    """The renderer camera.

    Can follow a point and shake.
    """
    def __init__(self, speed, rect_size):
        self._ppt = round(constants.MENU_SCALE * 1.5) * 20
        self._shake = 0
        self._shake_x = 0
        self._shake_y = 0
        self._pos = DynamicPos((0, 0), speed=speed)
        self._rect_size = rect_size

        self._t_lastshake = 0

    def get_rect(self):
        """Return the rect in which the camera can see.

        Rect position and size is in pixels.
        """
        x = (self._pos.x + random.uniform(
            -self._shake_x, self._shake_x)) * self._ppt / constants.TILE_SIZE
        y = (self._pos.y + random.uniform(
            -self._shake_y, self._shake_y)) * self._ppt / constants.TILE_SIZE
        rect = pygame.Rect((0, 0), self._rect_size)
        rect.center = (x, y)
        return rect

    def get_scale(self):
        """Return scale of camera. Larger number means more zoomed in."""
        return self._ppt / constants.TILE_SIZE

    def get_zoom(self):
        """Get pixels per tile of camera. Larger number means larger tiles."""
        return self._ppt

    def zoom(self, zoom):
        """Change the pixels per tile of the camera. Positive zoom means zooming in."""
        self._ppt += zoom

    def shake(self, amount):
        """Shake the camera."""
        self._shake += amount

    def set_target(self, pos, direct=False):
        """Set target position of the camera."""
        self._pos.move(pos, direct)

    def tile_to_pixel_pos(self, x, y):
        """Including zoom, return the position of the center of a tile relative to the top-left of the map."""
        return ((x + 0.5) * self._ppt, (y + 0.5) * self._ppt)

    def tile_to_camera_pos(self, x, y):
        """Excluding zoom, return the position of the center of a tile relative to the top-left of the map."""
        return ((x + 0.5) * constants.TILE_SIZE,
                (y + 0.5) * constants.TILE_SIZE)

    def tile_to_screen_pos(self, x, y):
        """Return the position of the center of a tile relative to the top-left of the screen."""
        pixelpos = self.tile_to_pixel_pos(x, y)
        rect = self.get_rect()
        return (pixelpos[0] - rect.x, pixelpos[1] - rect.y)

    def update(self, t_frame, pos=None):
        """Update shake amount and move towards target position."""
        if pos is not None:
            self.set_target(pos)

        self._pos.update(t_frame)

        self._t_lastshake += t_frame
        while self._t_lastshake >= 1000 / 30:
            self._t_lastshake -= 1000 / 30
            self._shake_x = random.uniform(-self._shake, self._shake)
            self._shake_y = random.uniform(-self._shake, self._shake)

            self._shake *= 0.75
            if self._shake < 0.1:
                self._shake = 0