Как применить методы класса к свойству собственного класса в Python - PullRequest
1 голос
/ 01 октября 2019

Я создал класс с именем Thing для Pygame, который позже будет разделен на подклассы для разработки более конкретных классов и объектов. Этот класс должен хранить среди других атрибутов position и size объекта.

Однако в Pygame есть очень мощный класс, называемый Rect, который можетуже делают это, и имеет много полезных встроенных методов и свойств. Я мог бы использовать один атрибут Rect в моем классе Thing, но он хранит позиции в целых числах, и я хочу сохранить его в числах с плавающей запятой (Thing может потребоваться переместить меньше, чемодин пиксель на кадр).

Это то, что я имел в виду.

class Thing:
    def __init__(self, pos, size):
        self.x: float = pos[0]
        self.y: float = pos[1]
        self.size = size

    @property
    def rect(self):
        return pygame.Rect((self.x, self.y), self.size)

    @rect.setter
    def rect(self, var: pygame.Rect):
        self.x = var.x
        self.y = var.y
        self.size = var.size

Это позволило бы мне получить и установить Thing Rect, но я бы не сталНе сможете использовать встроенные сеттеры Rect по желанию:

foo = Thing((10, 10), (20, 20))
foo.draw(win)

foo.x += 100
foo.draw(win)

# This has no effect
foo.rect.y += 100
foo.draw(win)

temp = foo.rect
temp.x -= 100
foo.rect = temp
foo.draw(win)

Actual Behavior

Требуемое поведение для приведенного выше кодабудет иметь движение квадрата вправо, вниз , затем налево.

Есть ли способ:

  • Иметь Rect как Thing атрибут, но обновлять x и y всякий раз, когда он изменяется?
  • Применение методов к Rect свойству
  • Некоторое другое решение, которое вы можете придумать

TL; DR: Если у меня есть Rect как свойство,Я не могу сделать self.rect.center = (500,500)

Заранее спасибо!

1 Ответ

2 голосов
/ 01 октября 2019

Ваш класс должен наследовать от pygame.Rect. Это единственный способ автоматически получить методы Rect. Однако, делая это, вы унаследуете также int приведение типов координат, так как это в исходной реализации pygame.Rect. Боюсь, наследование не решит вашу проблему.

Вы знаете, что должны делать методы Rect (документация написана хорошо), поэтому я боюсь, чтоЕдинственный способ - переопределить их (или, по крайней мере, переопределить те, которые вам нужны) для вашего собственного Thing класса, чтобы имитировать поведение Rect с числами с плавающей точкой.

Я сделал нечто подобное: вот частькласс, который я написал (я не буду показывать все это, потому что он слишком длинный), чтобы дать вам идею:

class FlRect:
    """Similar to pygame.Rect but uses float numbers.

    The class stores internally only coordinates, width and height.
    Other attributes are rendered through properties, with getter and setter:
    x, y: coordinates of the top-left corner of the rectangle.
    top, bottom: y coordinates of the top and bottom edges respectively.
    left, right: x coordinates of the left and right edges respectively.
    centerx, centery: coordinates of the centre of the rectangle.
    width, height: self-explanatory. 
    """

    def __init__(self, x, y, w, h):
        """Initialization:

        x, y - coordinates of top-left corner of the rectangle
        w, h - width and height
        """
        self._x = x
        self._y = y
        self._w = w
        self._h = h

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        self._y = value

    @property
    def width(self):
        return self._w

    @width.setter
    def width(self, value):
        self._w = value

    @property
    def height(self):
        return self._h

    @height.setter
    def height(self, value):
        self._h = value

    @property
    def top(self):
        return self._y

    @top.setter
    def top(self, value):
        self._y = value

    @property
    def bottom(self):
        return self._y + self._h

    @bottom.setter
    def bottom(self, value):
        self._y = value - self._h

    @property
    def left(self):
        return self._x

    @left.setter
    def left(self, value):
        self._x = value

    @property
    def right(self):
        return self._x + self._w

    @right.setter
    def right(self, value):
        self._x = value - self._w

    @property
    def centerx(self):
        return self._x + (self._w / 2)

    @centerx.setter
    def centerx(self, value):
        self._x = value - (self._w / 2)

    @property
    def centery(self):
        return self._y + (self._h / 2)

    @centery.setter
    def centery(self, value):
        self._h = value - (self._h / 2)

    def get_rect(self):
        """Return a pygame.Rect object with rounded coordinates"""
        return Rect(round(self._x), round(self._y), round(self._w), round(self._h))

Конечно, это не будет так эффективно, как pygame.Rect, так как этонаписан на python, а класс Pygame Rect находится в C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...