敌人精灵未正确跟随玩家

时间:2019-06-12 04:05:36

标签: python pygame

我的敌人精灵通常能够跟随玩家,但是当我继续玩游戏时,敌人精灵有时会全部开始向墙延伸并相互重叠。即使我让玩家精灵朝另一个方向移动,敌人精灵也只会沿着墙壁移动,而不是朝向玩家。

此外,我觉得我的敌人精灵完全没有威胁。在一半的时间里,他们并没有真正走向玩家。如果我曾经与敌人相撞,那是因为我没有注意而向他们前进。

我想解决我的敌人精灵向墙聚集的问题,并使我的敌人更具威胁性。我也发现我的游戏太乏味了,所以我很感谢我为增加游戏趣味而提出的任何建议。

这是我的游戏代码:

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

1 个答案:

答案 0 :(得分:1)

要获得“平滑”效果,您必须使用浮点值而不是整数值来计算敌人的位置和运动。
请注意,pygame.Rect对象的位置和大小是整数存储的。每次将运动添加到位置时,小数部分都会丢失。这导致根本不执行方向上的小移动。如果将小于0.5(round)的值添加到整数坐标,则位置将永远不会改变,即使超出帧也是如此。如果坐标是浮点值,则位置的整数部分将在几帧后发生变化。

在类Enemy上添加位置属性(.pos):

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。例如:

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

如果检测到碰撞,则必须通过属性.pos中的整数位置来校正属性.rect。例如:

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

此外,您必须创建对象属性属性self.move_xself.move_y,而不是类属性Enemy.move_xEnemy.move_y
注意,一个类对于每种类型(cals)都存在一次属性,但是对于每个对象(“敌人”)都只存在一次对象属性。每个敌人都必须有自己的运动矢量,否则最后一个敌人计算出的运动将应用于所有敌人。这会导致敌人做出意外动作。参见Class Definition Syntax

当然,您必须循环移动敌人

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