【问题标题】:Enemy sprite not following player properly [duplicate]敌人精灵没有正确跟随玩家[重复]
【发布时间】:2019-06-12 04:05:36
【问题描述】:

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

此外,我觉得我的敌人精灵根本没有威胁。有一半的时候,他们并没有真正走向玩家。如果我撞到了敌人,那是因为我没有注意就向他们靠近。

我想解决我的敌人精灵聚集在墙上的问题,让我的敌人更具威胁性。我也觉得我的游戏太乏味了,所以我很感激任何关于我可以添加什么以使游戏更有趣的建议。

这是我的游戏代码:

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

【问题讨论】:

    标签: python pygame


    【解决方案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
    请注意,每个类型(calss)都有一个类属性,但每个对象(“敌人”)都有一个对象属性。每个敌人都必须有自己的运动矢量,否则最后一个敌人计算的运动将应用于所有敌人。这会导致敌人做出意想不到的移动。见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
    

    【讨论】:

    • 移动更顺畅(谢谢),但当我的玩家精灵不在时,我的敌人精灵仍然会向墙壁移动。它将向左或右墙移动,然后向下移动直到超出屏幕。你知道为什么会这样吗? @Rabbid76
    • @helpless 这只有在玩家离开屏幕时才会发生。玩家的坐标总是在窗口中吗? 0 < player.rect.x < window_width0 < player.rect.y < window_height?请注意,move() 中的答案存在问题:self.move_x 分别为 self.move_y 而不是 Enemy.move_xEnemy.move_y
    • 没有。我的播放器总是在屏幕上。我什至有墙来防止玩家精灵和敌人精灵移出屏幕。我不太明白move(): self.move_x 中的问题是什么意思。我应该如何改变它? @Rabbid76
    • @helpless 查看答案的最后更改。它必须是 self.move_xself.move_y 而不是 Enemy.move_xEnemy.move_y。在Enemy的构造函数中初始化:self.move_x = 0self.move_y = 0并循环移动敌人:for e in enemy_list: e.move(player)。我将所有这些代码添加到答案中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多