Beispiel #1
0
    def __init__(self, parent=None, main=None):
        """
        :param parent: родительский элемент class Division
        :param main: Main приложения (default=None (<=> parent.main))
        """
        self._parent = parent
        self._main = main
        if main is None and parent is not None:
            self._main = parent.main

        if main is not None or parent is not None:
            if parent is not None:
                parent.add_child(self)
            self._rect = FRect(0, 0, 100, 100)
            self.absolute_position = False
        else:
            self._rect = FRect(0, 0, 0, 0)
            self.absolute_position = True
        self._abs_rect = self.calculate_global_rect()

        self.in_step = False

        self._elements = []
        self._disabled = []
        self.step_time = 1
        self.event = None
        self.hover = False
        self.press = False
        self.select = False
        self.selected = None
        self.post_init()
Beispiel #2
0
 def preview(self, size):
     """
     Возвращает preview для инвентаря.
     :param size: (width, height)
     :return: pygame.Surface
     """
     i_img = self._image[0]
     img_b_rect = i_img.get_bounding_rect()
     img = i_img.subsurface(img_b_rect)
     r = FRect(img_b_rect).fit(FRect(0, 0, *size))
     return pygame.transform.scale(img, [int(e) for e in r.size])
Beispiel #3
0
 def set_rect(self, rect):
     """
     Изменить прямоугольник расположения.
     :param rect: Rect()
     """
     self._rect = FRect(rect)
     if self.in_step:
         self._abs_rect = self.calculate_global_rect()
Beispiel #4
0
 def _get_rect(self):
     """
     Прямоугольник, описанный около объекта.
     Создаётся из pymunk.bb главного shape.
     :return:
     """
     bb = self.bb
     r = FRect(bb.left, bb.bottom, bb.right - bb.left, bb.top - bb.bottom)
     return r
Beispiel #5
0
 def draw(self, surface):
     super().draw(surface)
     b_rect = self._abs_rect
     if self.content:
         ir = FRect(0, 0, b_rect.w * .8, b_rect.h * .8)
         ir.center = b_rect.center
         r = FRect(self.content.get_rect())
         r.fit_ip(ir)
         surface.blit(pygame.transform.scale(self.content, r.pygame.size),
                      r.topleft)
Beispiel #6
0
 def calculate_global_rect(self):
     """
     Абсолютная позиция (прямоугольник) относительно области отрисовки.
     Рекомендуется вызывать только в Division.start_step, используйте get_global_rect
     :return: Rect()
     """
     if self._parent is not None:
         rect = self._parent.global_rect
     elif self._main is not None:
         rect = self._main.get_visible_rect()
     else:
         return FRect(self._rect)
     if self.absolute_position:
         return FRect(*map(sum, zip(rect.topleft, self._rect.topleft)),
                      *self._rect.size)
     else:
         s_rect = self._rect
         s_tl = Vec2d(s_rect.topleft)
         s_sz = Vec2d(s_rect.size)
         return FRect(*(s_tl / 100 * rect.size + rect.topleft),
                      *(s_sz / 100 * rect.size))
Beispiel #7
0
    def __init__(self,
                 center,
                 screen_rect,
                 constraint,
                 zoom_con=None,
                 zoom_offset=1):
        """
        :param center: Начальная позиция камеры
        :param screen_rect: Прямоугольник отображаемой области c масштабированием 1, важен лишь размер
        :param constraint: Область, в которую камере разрешено заходить [x1, y1, x2, y2]
        :param zoom_con: Ограничения масштабирования. [min, max]
        :param zoom_offset:
        """
        self._constraint = pygame.Rect(constraint)
        self.i_size = list(screen_rect.size)
        self.screen_shift = list(screen_rect.topleft)

        if zoom_con is None:
            self.zoom_con = [None, None]
        else:
            self.zoom_con = zoom_con
        self.zoom_offset = zoom_offset
        self._target_zoom = 1 / zoom_offset
        if self.zoom_con[
                0] is not None and self._target_zoom < self.zoom_con[0]:
            self._target_zoom = self.zoom_con[0]
        if self.zoom_con[
                1] is not None and self._target_zoom > self.zoom_con[1]:
            self._target_zoom = self.zoom_con[1]

        self.move_speed = 6
        self.zoom_speed = 2

        self.rect = FRect(0, 0, *self.i_size)
        self.rect.center = center
        self.rect.clamp_ip(self._constraint)

        self._c_rect = FRect(self.rect)
        self.zoom = 1
Beispiel #8
0
 def _set_rect(self, rect):
     if self._body is not None:
         self._body.position = FRect(rect).center
Beispiel #9
0
 def _get_rect(self):
     r = FRect(*self._pos, 0, 0)
     r.inflate_ip(*self._size)
     return r
Beispiel #10
0
 def _set_rect(self, rect):
     body = self._get_body()
     if body is not None:
         body.position = FRect(rect).center
Beispiel #11
0
class Camera:
    """
    Класс камеры. Содержит набор методов для выбора отображаемой области уровня, масштабирования.
    """
    def __init__(self,
                 center,
                 screen_rect,
                 constraint,
                 zoom_con=None,
                 zoom_offset=1):
        """
        :param center: Начальная позиция камеры
        :param screen_rect: Прямоугольник отображаемой области c масштабированием 1, важен лишь размер
        :param constraint: Область, в которую камере разрешено заходить [x1, y1, x2, y2]
        :param zoom_con: Ограничения масштабирования. [min, max]
        :param zoom_offset:
        """
        self._constraint = pygame.Rect(constraint)
        self.i_size = list(screen_rect.size)
        self.screen_shift = list(screen_rect.topleft)

        if zoom_con is None:
            self.zoom_con = [None, None]
        else:
            self.zoom_con = zoom_con
        self.zoom_offset = zoom_offset
        self._target_zoom = 1 / zoom_offset
        if self.zoom_con[
                0] is not None and self._target_zoom < self.zoom_con[0]:
            self._target_zoom = self.zoom_con[0]
        if self.zoom_con[
                1] is not None and self._target_zoom > self.zoom_con[1]:
            self._target_zoom = self.zoom_con[1]

        self.move_speed = 6
        self.zoom_speed = 2

        self.rect = FRect(0, 0, *self.i_size)
        self.rect.center = center
        self.rect.clamp_ip(self._constraint)

        self._c_rect = FRect(self.rect)
        self.zoom = 1

    def update(self, upd_time):
        tc, cc = self.rect.center, self._c_rect.center
        ts, cs = self.rect.size, self._c_rect.size
        # print(cs, self.zoom, self.zoom_offset, self.zoom / self.zoom_offset)
        dis_x, dis_y = tc[0] - cc[0], tc[1] - cc[1]
        ds_x, ds_y = ts[0] - cs[0], ts[1] - cs[1]

        if abs(ds_x) < .5:
            self._c_rect.w = ts[0]
        else:
            self._c_rect.w += ds_x * self.zoom_speed * upd_time / 1000
        if abs(ds_y) < .5:
            self._c_rect.h = ts[1]
        else:
            self._c_rect.h += ds_y * self.zoom_speed * upd_time / 1000

        if abs(dis_x) < .5:
            self._c_rect.centerx = tc[0]
        else:
            self._c_rect.centerx = cc[
                0] + dis_x * self.move_speed * upd_time / 1000
        if abs(dis_y) < .5:
            self._c_rect.centery = tc[1]
        else:
            self._c_rect.centery = cc[
                1] + dis_y * self.move_speed * upd_time / 1000
        self._c_rect.clamp_ip(self._constraint)

    def get_rect(self):
        """
        Прямоугольник в системе координат уровня, который камера освещает на данный момент..
        :return: Rect()
        """
        return self._c_rect
        # rect = pygame.Rect(0, 0, 0, 0)
        # rect.center = self.c_rect.center
        # rect.inflate_ip(self.c_rect.width // 2 * 2, self.c_rect.height // 2 * 2)
        # return rect

    def move(self, shift):
        """
        Сдвинуть камеру на вектор.
        :param shift: (x, y)
        """
        self.rect.x += shift[0]
        self.rect.y += shift[1]
        self.rect.clamp_ip(self._constraint)

    def move_smooth(self, coef):
        """
        Сдвиг камеры на процент текущего размера области отображения.
        :param coef: (x (%), y (%))
        :return:
        """
        self.rect.x += self._c_rect.width * coef[0] / 100
        self.rect.y += self._c_rect.height * coef[1] / 100
        self.rect.clamp_ip(self._constraint)

    def get_zoom(self):
        """
        Целевое масштабирование камеры.
        :return: int
        """
        return self._target_zoom * self.zoom_offset

    def set_zoom(self, zoom):
        """
        Установить целевое масштабирование камеры.
        :param zoom: int
        """
        # absolute zoom
        zoom = zoom / self.zoom_offset
        if zoom <= 0:
            return
        center = self.rect.center
        if self.zoom_con[
                0] is not None and zoom < self.zoom_con[0] / self.zoom_offset:
            zoom = self.zoom_con[0] / self.zoom_offset
        if self.zoom_con[
                1] is not None and zoom > self.zoom_con[1] / self.zoom_offset:
            zoom = self.zoom_con[1] / self.zoom_offset
        premade = [e / zoom for e in self.i_size]
        if premade[0] > self._constraint.size[0] or premade[
                1] > self._constraint.size[1]:
            m_ind = min((0, 1),
                        key=lambda e: self._constraint.size[e] - premade[e])
            self.set_zoom(self.i_size[m_ind] / self._constraint.size[m_ind] *
                          self.zoom_offset)
            return
        self.rect.size = premade
        self.rect.center = center
        self.rect.clamp_ip(self._constraint)
        self._target_zoom = zoom

    def reload_zoom(self, old_offset=1):
        self.set_zoom(self.get_zoom() * old_offset)

    zoom = property(get_zoom, set_zoom)

    def get_current_zoom(self):
        """
        Масштабирование камеры в данный момент.
        :return: int
        """
        return self.i_size[0] / self._c_rect.width

    def get_center(self):
        """
        Целевая позиция камеры
        :return: (x, y)
        """
        return self.rect.center

    def set_center(self, pos):
        """
        Установка целевой позиции камеры.
        :param pos: (x, y)
        """
        self.rect.center = pos

    center = property(get_center, set_center)

    def get_constraint(self):
        return self._constraint

    def set_constraint(self, rect):
        self._constraint = pygame.Rect(rect)
        self.reload_zoom()

    constraint = property(get_constraint, set_constraint)

    def move_constraint(self, rect):
        self._constraint = pygame.Rect(rect)
        self.rect.clamp_ip(self._constraint)

    def get_size(self):
        return self.i_size

    def set_size(self, size):
        self.i_size = size
        self.reload_zoom()

    size = property(get_size, set_size)

    def instant_move(self):
        self._c_rect.center = self.rect.center

    def instant_zoom(self):
        self._c_rect.size = self.rect.size

    def instant_target(self):
        """
        Мнгновенно установить камеру в целевую позицию
        """
        self._c_rect = self.rect.copy()

    def world_to_local(self, pos):
        rect = self.get_rect()
        tl = rect.topleft
        zoom = self.get_current_zoom()
        return (Vec2d(pos) - tl) * zoom

    def local_to_world(self, pos):
        rect = self.get_rect()
        tl = rect.topleft
        zoom = self.get_current_zoom()
        return Vec2d(pos) / zoom + tl