我的敌人精灵通常能够跟随玩家,但是当我继续玩游戏时,敌人精灵有时会全部开始向墙延伸并相互重叠。即使我让玩家精灵朝另一个方向移动,敌人精灵也只会沿着墙壁移动,而不是朝向玩家。
此外,我觉得我的敌人精灵完全没有威胁。在一半的时间里,他们并没有真正走向玩家。如果我曾经与敌人相撞,那是因为我没有注意而向他们前进。
我想解决我的敌人精灵向墙聚集的问题,并使我的敌人更具威胁性。我也发现我的游戏太乏味了,所以我很感谢我为增加游戏趣味而提出的任何建议。
这是我的游戏代码:
Code is removed for now. Will re-upload in 1 to 2 months.
答案 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_x
和self.move_y
,而不是类属性Enemy.move_x
和Enemy.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