繁体   English   中英

pygame如何让敌人跟随玩家?

[英]How to make an enemy follow the player in pygame?

我制作了游戏的一部分。 它运行良好,但我想在我的游戏中添加敌人。 到目前为止,我在 pygame 精灵中添加了敌人的图像。
但是如何让敌人跟随玩家呢? 我试过这样做,但它只是让敌人的形象直接出现在玩家面前:

def moveEnemy(self):
    enemies.rect.x = player.rect.x
    enemies.rect.y = player.rect.y
    all_sprites_list.add(enemies)
    enemies_list.add(enemies)

我认为这会使敌人的形象跟随玩家。 相反,它只是与玩家的图像重叠。

我虽然阅读了许多 pygame 精灵示例,但示例中说用敌人.rect.x enemies.rect.x = -5或周围的东西替换敌人.rect.x enemies.rect.x = player.rect.x player.rect.x。 我也试过这个,但它只是向上移动图像而不是跟随玩家。

我必须制定一个方程式吗? 如果是这样我不知道该怎么做。
如何让敌人移动,同时让它跟随玩家? 有人可以帮我解决这个问题吗?

任何帮助,将不胜感激。

你需要通过改变敌人的位置来减少敌人和玩家之间的距离。 这可以通过找到它们位置之间的差异,然后使用该向量计算归一化(单位长度)方向向量来完成。 这样,通过将敌人的速度乘以方向向量来改变敌人的位置。

一种方法是向Enemy类添加如下所示的方法。 数学运算可以使用内置的math模块或pygame.math模块来完成。 后者还支持 2D Vector2类,因此实际使用它可能会更好。

import math
import pygame
from pygame.locals import *

class Enemy(object):
    ...
    def move_towards_player(self, player):
        # Find direction vector (dx, dy) between enemy and player.
        dx, dy = player.rect.x - self.rect.x, player.rect.y - self.rect.y
        dist = math.hypot(dx, dy)
        dx, dy = dx / dist, dy / dist  # Normalize.
        # Move along this normalized vector towards the player at current speed.
        self.rect.x += dx * self.speed
        self.rect.y += dy * self.speed

    # Same thing using only pygame utilities
    def move_towards_player2(self, player):
        # Find direction vector (dx, dy) between enemy and player.
        dirvect = pygame.math.Vector2(player.rect.x - self.rect.x,
                                      player.rect.y - self.rect.y)
        dirvect.normalize()
        # Move along this normalized vector towards the player at current speed.
        dirvect.scale_to_length(self.speed)
        self.rect.move_ip(dirvect)

您将需要添加检查以确定敌方对象是否会越过,从而在玩家移动这个距离时击中沿途的玩家,并做出相应的反应。 提示:只要移动的量——速度矢量的长度,即物体的速度——大于或等于它们之间的距离,就会发生碰撞。

在高层次上,您需要计算从敌人到玩家的向量。 方向向量的xy分量如下所示:

enemies.rect.x - player.rect.x
enemies.rect.y - player.rect.y

然后方向的倍数添加到敌人位置,使其向玩家移动。

但是:您会注意到,当玩家和敌人相距较远时,该向量的幅度会很大,而当他们靠得较近时,幅度会很小。 因此,为了避免敌人以超快的速度移动,您可以将方向向量归一化并乘以速度s以保持控制。

在这里, pxpy是敌人跟随/追逐的对象的位置(全局)。

class Enemy(object):
    def __init__(self,x,y):  # initial position
        self.x = x 
        self.y = y
    def move(self, speed=5): # chase movement
        # Movement along x direction
        if self.x > px:
            self.x -= speed
        elif self.x < px:
            self.x += speed
        # Movement along y direction
        if self.y < py:
            self.y += speed
        elif self.y > py:
            self.y -= speed

如果需要,您也可以自定义沿 x 和 y 方向的速度。

一个非常简单的方法是

    if x_player > x_enemy:
        x_enemy = x_enemy + 0.1
    if x_player < x_enemy:
        x_enemy = x_enemy - 0.1
    if y_player > y_enemy:
        y_enemy = y_enemy + 0.1
    if y_player < y_enemy:
        y_enemy = y_enemy - 0.1

显然,将变量更改为您正在使用的变量并更改您正在更改 x 和 y 的值以更改敌人移动的速度。

让敌人跟随玩家需要一些数学知识。 我建议使用pygame.math.Vector2进行计算。

计算敌人( follower_xfollower_y )到玩家( player_xplayer_y )的欧几里得距离以及从敌人到玩家的单位方向向量。 单位向量可以通过将方向向量除以距离或通过归一化( normalize() )方向向量来计算:

target_vector = Vector2(player_x, player_y)
follower_vector = Vector2(follower_x, follower_y)

distance = follower_vector.distance_to(target_vector)
direction_vector = target_vector - follower_vector
if distance > 0:
    direction_vector /= distance

定义一个精确的step_distance并沿着从敌人到玩家的方向向量在精灵的方向上移动

if distance > 0:
    new_follower_vector = follower_vector + direction_vector * step_distance.

定义玩家和敌人之间的minimum_distancemaximum_distance 最小距离可以为 0,最大距离可以很大:

minimum_distance = 0
maximum_distance = 10000

使用这个最小值和最大值来限制敌人的移动:

min_step = max(0, distance - maximum_distance)
max_step = distance - minimum_distance

敌人的移动速度可以恒定

VELOCITY = 5
step_distance = min(max_step, max(min_step, VELOCITY))

或用插值因子平滑:

LERP_FACTOR = 0.05
step_distance = min_step + (max_step - min_step) * LERP_FACTOR

最小的例子:

repl.it/@Rabbid76/PyGame-FollowMouseSmoothly

import pygame

VELOCITY         = 5
LERP_FACTOR      = 0.05
minimum_distance = 25
maximum_distance = 100

def FollowMe(pops, fpos):
    target_vector       = pygame.math.Vector2(*pops)
    follower_vector     = pygame.math.Vector2(*fpos)
    new_follower_vector = pygame.math.Vector2(*fpos)

    distance = follower_vector.distance_to(target_vector)
    if distance > minimum_distance:
        direction_vector    = (target_vector - follower_vector) / distance
        min_step            = max(0, distance - maximum_distance)
        max_step            = distance - minimum_distance
        #step_distance       = min(max_step, max(min_step, VELOCITY))
        step_distance       = min_step + (max_step - min_step) * LERP_FACTOR
        new_follower_vector = follower_vector + direction_vector * step_distance

    return (new_follower_vector.x, new_follower_vector.y) 

pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

follower = (100, 100)
run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    player   = pygame.mouse.get_pos()
    follower = FollowMe(player, follower)

    window.fill(0)  
    pygame.draw.circle(window, (0, 0, 255), player, 10)
    pygame.draw.circle(window, (255, 0, 0), (round(follower[0]), round(follower[1])), 10)
    pygame.display.flip()

pygame.quit()
exit()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM