по какой-то причине pygame устанавливает положение всех экземпляров класса в одно и то же значение? - PullRequest
0 голосов
/ 08 мая 2018

Я делаю игру в змею в Pygame, и я столкнулся с проблемой.Всякий раз, когда змея ест пищу, игрок получает очко.С этого момента хвост создается за змеей всякий раз, когда он движется.Только хвосты, количество очков игрока от головы змеи, будут вытянуты, а остальные удалены.Проблема возникает, когда я создаю хвосты.Всякий раз, когда я создаю экземпляр хвоста, я должен получить положение головы змеи и вычесть значение, равное размеру змеи, в противоположном направлении.Вот где хвост будет нарисован.Однако положение всех хвостов по какой-то причине установлено на одно и то же значение, и я не могу понять, почему это так.Я использую свою собственную библиотеку, поэтому я не могу опубликовать ее здесь, но я решил, что это не причина.

    import pygame as pg

    from random import randrange

    import widget


    # disp -> display properties
    disp = widget.get_json("config", ["display"])

    food = widget.Surface(image="../images/food.png", pos=[0, 0])

    def set_food_pos(snake):
        while True:
            pos = [randrange(0, disp["size"][_], disp["cell"]) for _ in range(2)]
            safe = 0

            for tail in snake.tails:
                if tail.pos != pos: safe += 1

            if safe == len(snake.tails):
                food.pos = pos
                food.rect.topleft = food.pos

                break


    class Snake(widget.Sprite):
        """ Snake: main playable sprite """

        SIZE = [disp["cell"]] * 2
        KEYS = [[276, 275], [273, 274]]

        def __init__(self):
            self.image = pg.image.load("../images/snake_head.png")
            self.pos = widget.VEC(0, 0)

            super().__init__(pg.sprite.GroupSingle)

            self.axis, self.orient, self.do_move = 0, 1, False
            self.past, self.delay = pg.time.get_ticks(), 150
            self.speed, self.vel = disp["cell"], [-1, 1]
            self.alive, self.points = True, 0
            self.tails = [self]

        def control(self, key):
            axis = [0 if key in Snake.KEYS[0] else 1][0]
            if axis != self.axis:
                if self.do_move:
                    self.axis = axis
                    self.orient = Snake.KEYS[axis].index(key)
                    self.do_move = False

        def time_base_movement(self):
            now = pg.time.get_ticks()
            if now - self.past >= self.delay:
                self.do_move = True
                self.pos[self.axis] += self.vel[self.orient] * self.speed
                self.past = pg.time.get_ticks()

        def eat_food(self):
            if food.rect.contains(self.rect):
                set_food_pos(self)
                self.points += 1

        def create_tail(self):
            if self.points:
                if self.do_move:
                    pos = [_ for _ in self.rect.topleft]
                    pos[self.axis] += self.vel[::-1][self.orient] * 20
                    tail = widget.Sprite(image="../images/snake_head.png", pos=pos)

                    self.tails.insert(0, tail)

        def render_tails(self, surface):
            if self.points > 0:
                tails = self.tails[:-1]

                for tail in tails[0:self.points]: tail.group.draw(surface)
                [self.tails.remove(tail) for tail in tails[self.points:]]

        def check_boundary_collision(self):
            for _ in range(2):
                if self.pos[_] > disp["size"][_] - Snake.SIZE[_]:self.alive = False
                elif self.pos[_] < 0: self.alive = False

            for tail in self.tails[:-1]:
                if tail.rect.contains(self.rect): self.alive = False

        def reset_properties(self):
            if self.alive == False:
                print([tail.pos for tail in self.tails[:-1]])
                self.tails = [self]
                self.do_move = False

                self.pos = widget.VEC([0, 0])
                self.rect.topleft = self.pos

                self.axis, self.orient = 0, 1
                self.points, self.alive = 0, True

                set_food_pos(self)

        def update(self):
            if self.alive:
                self.time_base_movement()
                self.check_boundary_collision()
                self.reset_properties()

                self.rect.topleft = self.pos

1 Ответ

0 голосов
/ 15 мая 2018

Я понял это, кажется, что python не создает новую копию атрибута каждый раз, когда он присваивается другому атрибуту. Вместо этого новый атрибут указывает на назначенный атрибут. Исправление для этого - метод «deepcopy» во встроенном модуле «copy».

Exe: new_value = copy.deepcopy (old_value)

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