Вражеский спрайт не следует за игроком должным образом - PullRequest
1 голос
/ 12 июня 2019

Мои вражеские спрайты, как правило, могут следовать за игроком, но когда я продолжаю играть, иногда все вражеские спрайты начинают идти к стене и накладываться друг на друга.Даже если я заставлю спрайта игрока двигаться в другом направлении, вражеские спрайты будут двигаться только вдоль стены, а не к моему игроку.

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

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

Это мой код игры:

Code is removed for now. Will re-upload in 1 to 2 months.

1 Ответ

1 голос
/ 12 июня 2019

Чтобы получить "плавность", вам нужно вычислить позицию и движение противника с использованием значений с плавающей запятой, а не целых значений.
Обратите внимание, что позиция и размер объекта pygame.Rect сохраняются как целые. Каждый раз, когда к позиции добавляется движение, дробная часть теряется. Это приводит к тому, что небольшие движения в направлении вообще не выполняются. Если к интегральной координате добавляется значение меньше 0,5 (round), то положение никогда не изменится, даже за рамками. Если координата является значением с плавающей запятой, то через несколько кадров интегральная часть позиции изменится.

Добавить атрибут позиции (.pos) для класса Enemy:

class Enemy(pygame.sprite.Sprite):

    def __init__(self, x, y, speed, walls):

        # [...]
        self.pos = [x, y]
        self.rect.y = y
        self.rect.x = x

Измените позицию на атрибуте .pos и обновите .rect на .pos. e.g.:

self.pos[0] = self.pos[0] + self.move_x
self.rect.x = round(self.pos[0])

Если было обнаружено столкновение, то атрибут .pos должен быть исправлен с помощью целочисленной позиции в атрибуте .rect. e.g.:

if block_collide:
    self.pos[0] = self.rect.x

Далее вам нужно создать атрибуты атрибутов объекта self.move_x и self.move_y, а не атрибуты класса Enemy.move_x и Enemy.move_y.
Обратите внимание, что атрибут существует для каждого типа (calss) один раз, но атрибут объекта существует только один раз для каждого объекта («враг»). Каждый враг должен иметь свой собственный вектор движения, иначе движение, вычисленное последним врагом, будет применено ко всем врагам. Это заставляет врагов совершать неожиданные движения. См. Синтаксис определения класса .

Конечно, вы должны перемещать врагов в цикле

for e in enemy_list:
   e.move(player)

Полный код класса Enemy:

class Enemy(pygame.sprite.Sprite):

    def __init__(self, x, y, speed, walls):
        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.Surface([20, 20])
        self.image.fill(red)

        self.rect = self.image.get_rect()
        self.pos = [x, y]
        self.rect.y = y
        self.rect.x = x
        self.move_x = 0
        self.move_y = 0

        self.speed = speed # speed of the enemy
        self.walls = walls # walls for the collision test

    def move(self, player):
        dx, dy = player.rect.x - self.pos[0], player.rect.y - self.pos[1]
        dist = math.hypot(dx, dy)
        dx, dy = dx / dist, dy / dist
        self.move_x = dx * min(dist, self.speed)
        self.move_y = dy * min(dist, self.speed)

    def update(self):

        self.pos[0] = self.pos[0] + self.move_x
        self.rect.x = round(self.pos[0])
        block_collide = pygame.sprite.spritecollide(self, self.walls, False)
        for block in block_collide:
            if self.move_x > 0:
                self.rect.right = block.rect.left
            else:
                self.rect.left = block.rect.right
        if block_collide:
            self.pos[0] = self.rect.x

        self.pos[1] = self.pos[1] + self.move_y
        self.rect.y = round(self.pos[1])
        block_collide = pygame.sprite.spritecollide(self, self.walls, False)
        for block in block_collide:
            if self.move_y > 0:
                self.rect.bottom = block.rect.top
            else:
                self.rect.top = block.rect.bottom
        if block_collide:
            self.pos[1] = self.rect.y
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...