pygame 敌人向玩家的二维运动,如何计算 x 和 y 速度? [英] pygame 2 dimensional movement of an enemy towards the player, how to calculate x and y velocity?

查看:65
本文介绍了pygame 敌人向玩家的二维运动,如何计算 x 和 y 速度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我目前制作的游戏中,我需要让敌人向玩家移动(这里的敌人是一个 blob)才能做到这一点,我已经创建了一个函数:def calculate_enemy_movement(enemy): 在里面我放了函数需要做什么:

<块引用>

计算每帧需要添加什么x值(x速度),以及每帧需要添加什么y值(y速度)到enemy.xenemy.yplayer.xplayer.y 走去,然后返回 x 速度并返回 y 速度.
此处调用此函数:将 x 速度和 y 速度添加到每帧敌人的 x 和 y 位置enemy_blob.x,enemy_blob.y += calculate_enemy_movement(enemy_blob)

现在我只需要有人帮我创建这个函数.我已经研究过它,我知道它与向量数学有关,但我不确定它究竟是如何工作的,所以如果有人可以编写函数并解释它是如何工作的,我会非常高兴.

如果您需要其余的代码:

导入pygame导入操作系统导入系统从数学导入 *导入数学从输入导入元组从 pygame.locals 导入 *运行 = 错误类游戏():def __init__(self):主要的()pygame.init()每秒帧数 = 60阿尼 = 4def diagonal_x_vel(速度):diagonal_x = int((math.pi/4) * 速度)返回 diagonal_xdef diagonal_y_vel(速度):diagonal_y = int(sin(math.pi/4) * 速度)返回 diagonal_y定义移动(矩形,移动):全局 player_rectrect.x += 运动[0]rect.y += 运动[1]返回矩形宽度,高度 = 1920, 1080player_action = 空闲"player_frame = 0类播放器():def __init__(self):self.main_char_height, self.main_char_width = 35 * 4, 35 * 4self.main_char_x = WIDTH/2 - self.main_char_width/2self.main_char_y = HEIGHT/2 - self.main_char_height/2self.current_health = 80self.maximum_health = 100self.health_bar_length = 500self.health_ratio = self.maximum_health/self.health_bar_lengthself.movi​​ng_right, self.movi​​ng_left, self.movi​​ng_down, self.movi​​ng_up, self.idle = False, False, False, False, Trueself.player_rect = pygame.Rect(self.main_char_x, self.main_char_y, self.main_char_width, self.main_char_height)self.player_flip = Falseself.VEL = 8定义更新():经过def take_dmg(self, amount):如果 self.current_health >0:self.current_health -= 数量如果 self.current_health <= 0:self.current_health = 0def get_health(self, amount):如果 self.current_health = self.maximum_health:self.current_health = self.maximum_health类敌人():def __init__(self, health, attack_damage, raw_speed, x, y, height, width, action,diagonal_vel_x,diangonal_vel_y):自我.x = x自我.y = yself.health = 健康self.attack_damage = attack_damageself.speed = raw_speedself.enemy_rect = pygame.Rect(x,y,width,height)self.action = 行动WIN = pygame.display.set_mode([WIDTH, HEIGHT], pygame.FULLSCREEN)pygame.display.set_caption(第一场比赛")玩家 = 玩家()动画帧 = {}def load_animation(path, image_name, frame_duration, scale_width, scale_height):全局 animation_framesanimation_frame_data = []n = 0对于 frame_duration 中的帧:animation_frame_id = image_name + _"+ str(n)img_loc = 路径 + /";+ animation_frame_id + .png"animation_image = pygame.transform.scale(pygame.image.load(img_loc),(scale_width, scale_height)).convert_alpha()animation_image.convert()animation_frames[animation_frame_id] = animation_image.copy()对于我在范围内(帧):animation_frame_data.append(animation_frame_id)n += 1返回 animation_frame_datadef change_action(action_var, frame, new_value):如果 action_var != new_value:action_var = new_value返回 action_var,框架动画数据库 = {}animation_database[idle"] = load_animation(assets", darkpurpleknight_idle", [8, 8, 8, 8], player.main_char_width,player.main_char_height)animation_database[run_top"] = load_animation(assets", darkpurpleknight_run_up", [8, 8, 8, 8, 8, 8],player.main_char_width,player.main_char_height)animation_database[run_bot"] = load_animation(assets", darkpurpleknight_run_down", [8, 8, 8, 8, 8, 8],player.main_char_width, player.main_char_height)animation_database[run"] = load_animation(assets", darkpurpleknight_run", [8, 8, 8, 8, 8, 8], player.main_char_width,player.main_char_height)滚动 = [0, 0]blob_height = 17blob_width = 25blob_frame = 0敌人 blob = 敌人 (50, 10, 5, 1000 , 1000, 17, 25, blob_idle",0,0)animation_database[blob_idle"] = load_animation(assets", blob_idle", [30, 30], blob_width * 4, blob_height * 4)时钟 = pygame.time.Clock()定义碰撞(rectA,rectB):如果 rectB.right <rectA.left:# rectB est à gauche返回错误如果 rectB.bottom rectA.right:# rectB est à droite返回错误如果 rectB.top >rectA.bottom:# rectB est en-dessous返回错误elif rectB.right >rectA.left:# rectB est en 碰撞 avec la gauche返回真elif rectB.bottom <rectA.top:# rectB est en 碰撞 avec le haut返回真elif rectB.left >rectA.right:# rectB est en 碰撞 avec la droite返回真elif rectB.top >rectA.bottom:# rectB est en 碰撞 avec le bas返回真bg_img = pygame.transform.scale(pygame.image.load("assets/DUNGEON_PISKEL_REMAKE_WITH_WALL_PROPS-1.png"),(WIDTH * 2, HEIGHT * 2)).convert()def animate_sprite(frame_counter, action):全局动画数据库帧计数器 += 1如果 frame_counter >= len(animation_database[action]):帧计数器 = 0img_id = animation_database[动作][frame_counter]animation_image = animation_frames[img_id]返回动画图像,帧计数器#def calculate_enemy_movement(敌人):#计算每帧需要加上什么x值(x速度),每帧需要加上什么y值(y速度)到敌人.x和敌人.y走#towards player.x 和 player.y.#返回x速度并返回y速度def draw_window(window):全球敌人_blob窗户 = 窗户全局 main_char_x, main_char_y全局 player_frame、bg_img、blob_frame全局滚动全球幻灯片# 将 x 速度和 y 速度添加到每帧敌人的 x 和 y 位置#enemy_blob.x,enemy_blob.y += calculate_enemy_movement(enemy_blob)window.blit(bg_img, (-WIDTH/2 - scroll[0], -HEIGHT/2 - scroll[1]))blob_img, blob_frame = animate_sprite(blob_frame,敌人的blob.action)window.blit(blob_img, (enemy_blob.x - 滚动[0],敌人_blob.y - 滚动[1]))player_img, player_frame = animate_sprite(player_frame, player_action)window.blit(pygame.transform.flip(player_img, player.player_flip, False), (player.player_rect.x, player.player_rect.y))pygame.display.update()边界 = []冲突 = 错误def set_borders(x, y, 宽度, 高度):边框 = pygame.Rect((x, y), (width, height))返回边界def check_colision(目标,列表):is_coliding = []对于列表中的我:is_coliding.append(collision(i, target))返回 is_coliding定义主():全局滚动全局 player_frame全球玩家_动作全局 player_flip全局 player_rect、rect1、coding全球VEL全球顶墙全球边界全局 main_char_x, main_char_y全局moving_left、moving_right、moving_up、moving_down、空闲game_running = 真游戏运行时:时钟滴答(FPS)对于 pygame.event.get() 中的事件:如果 event.type == pygame.KEYDOWN:如果 event.key == K_ESCAPE:game_running = 假从开始菜单导入 Open_launcherOpen_launcher()系统退出()top_map_border = set_borders(-WIDTH/2 - scroll[0], -HEIGHT/2 + 250 - scroll[1], 5000, 1)bot_map_border = set_borders(-WIDTH/2 - scroll[0], HEIGHT + 355 - scroll[1], 5000, 1)left_map_border = set_borders(-WIDTH/2 + 160 - scroll[0], -HEIGHT/2 - scroll[1], 1, 5000)right_map_border = set_borders(WIDTH + 785 - scroll[0], -HEIGHT/2 + 150 - scroll[1], 1, 5000)边界 = [top_map_border, bot_map_border, left_map_border, right_map_border]敌人 = []is_coliding_with_borders = check_colision(player.player_rect,边界)is_coliding_with_enemy = check_colision(player.player_rect,敌人)top_coliding = is_coliding_with_borders[0]bot_coliding = is_coliding_with_borders[1]left_coliding = is_coliding_with_borders[2]right_coliding = is_coliding_with_borders[3]键 = pygame.key.get_pressed()# 使用A"的每个动作如果键[pygame.K_a]:# 对角线左上角如果keys[pygame.K_w]而不是keys[pygame.K_d]:如果不是 left_coliding 和不是 top_coliding:player.player_flip = Trueplayer_action, player_frame = change_action(player_action, player_frame, 运行")滚动 [0] -= diagonal_x_vel(player.VEL)滚动 [1] -= diagonal_y_vel(player.VEL)elif left_coliding 而不是 top_coliding:player.player_flip = True滚动 [1] -= player.VELplayer_action, player_frame = change_action(player_action, player_frame, run_top")elif top_coliding 而不是 left_coliding:player.player_flip = True滚动 [0] -= player.VELplayer_action, player_frame = change_action(player_action, player_frame, 运行")elif left_coliding 和 top_coliding:player.player_flip = Falseplayer_action, player_frame = change_action(player_action, player_frame, 空闲")# 左下角对角线elif 键[pygame.K_s] 而不是键[pygame.K_d]:如果不是 left_coliding 而不是 bot_coliding:player.player_flip = Trueplayer_action, player_frame = change_action(player_action, player_frame, 运行")滚动 [0] -= diagonal_x_vel(player.VEL)滚动 [1] += diagonal_y_vel(player.VEL)elif left_coliding 而不是 bot_coliding:player.player_flip = True滚动[1] += player.VELplayer_action, player_frame = change_action(player_action, player_frame, run_bot")elif 不是 left_coliding 和 bot_coliding:player.player_flip = True滚动 [0] -= player.VELplayer_action, player_frame = change_action(player_action, player_frame, 运行")elif left_coliding 和 bot_coliding:player.player_flip = Falseplayer_action, player_frame = change_action(player_action, player_frame, 空闲")# 左运动elif 不是keys[pygame.K_s] 不是keys[pygame.K_d] 不是keys[pygame.K_w]:如果不是 left_coliding:player.player_flip = True滚动 [0] -= player.VELplayer_action, player_frame = change_action(player_action, player_frame, 运行")别的:player.player_flip = Trueplayer_action, player_frame = change_action(player_action, player_frame, 运行")别的:player_action, player_frame = change_action(player_action, player_frame, 空闲")# 使用D"的每一个动作如果键[pygame.K_d]:# 对角线右上角如果keys[pygame.K_w]而不是keys[pygame.K_a]而不是keys[pygame.K_s]:如果不是 right_coliding 和不是 top_coliding:player.player_flip = Falseplayer_action, player_frame = change_action(player_action, player_frame, 运行")滚动 [0] += diagonal_x_vel(player.VEL)滚动 [1] -= diagonal_y_vel(player.VEL)elif right_coliding 而不是 top_coliding:player.player_flip = False滚动 [1] -= player.VELplayer_action, player_frame = change_action(player_action, player_frame, run_top")elif top_coliding 而不是 right_coliding:player.player_flip = Falsescroll[0] += player.VELplayer_action, player_frame = change_action(player_action, player_frame, 运行")elif right_coliding 和 top_coliding:player.player_flip = Falseplayer_action, player_frame = change_action(player_action, player_frame, 空闲")# 对角机器人右elif keys[pygame.K_s] 而不是 keys[pygame.K_a] 而不是 keys[pygame.K_w]:如果不是 right_coliding 而不是 bot_coliding:player.player_flip = Falseplayer_action, player_frame = change_action(player_action, player_frame, 运行")scroll[0] += diagonal_x_vel(player.VEL)滚动 [1] += diagonal_y_vel(player.VEL)elif right_coliding 而不是 bot_coliding:player.player_flip = False滚动[1] += player.VELplayer_action, player_frame = change_action(player_action, player_frame, run_bot")elif 不是 right_coliding 和 bot_coliding:player.player_flip = Falsescroll[0] += player.VELplayer_action, player_frame = change_action(player_action, player_frame, 运行")elif right_coliding 和 bot_coliding:player.player_flip = Falseplayer_action, player_frame = change_action(player_action, player_frame, 空闲")# 正确的动作elif 不是keys[pygame.K_s] 不是keys[pygame.K_a] 不是keys[pygame.K_w]:如果不是 right_coliding:player.player_flip = Falsescroll[0] += player.VELplayer_action, player_frame = change_action(player_action, player_frame, 运行")别的:player.player_flip = Falseplayer_action, player_frame = change_action(player_action, player_frame, 运行")别的:player_action, player_frame = change_action(player_action, player_frame, 空闲")# 使用W"的每个动作如果键[pygame.K_w]:# 向上运动如果不是keys[pygame.K_d]而不是keys[pygame.K_a]:如果不是 top_coliding:player_action, player_frame = change_action(player_action, player_frame, run_top")滚动 [1] -= player.VEL别的:player_action, player_frame = change_action(player_action, player_frame, run_top")# 使用S"的每个动作如果键[pygame.K_s]:# 向下运动如果不是keys[pygame.K_d]而不是keys[pygame.K_a]:如果不是bot_coliding:player_action, player_frame = change_action(player_action, player_frame, run_bot")滚动[1] += player.VEL别的:player_action, player_frame = change_action(player_action, player_frame, run_bot")如果不是keys[pygame.K_a]而不是keys[pygame.K_s]而不是keys[pygame.K_d]而不是keys[pygame.K_w]:player_action, player_frame = change_action(player_action, player_frame, 空闲")draw_window(WIN)

解决方案

计算从敌人位置到玩家位置的向量:

dx = player_x - 敌人_xdy = player_y - 敌人_y

计算向量的长度(

导入pygame,数学pygame.init()窗口 = pygame.display.set_mode((400, 400))时钟 = pygame.time.Clock()player_x, player_y, player_vel = 100, 100, 5敌人 x、敌人 y、敌人 vel = 300、300、3运行 = 真运行时:时钟滴答(60)对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:运行 = 错误键 = pygame.key.get_pressed()player_x = max(10, min(390, player_x + player_vel * (keys[pygame.K_d] - keys[pygame.K_a])))player_y = max(10, min(390, player_y + player_vel * (keys[pygame.K_s] - keys[pygame.K_w])))dx = player_x - 敌人_xdy = player_y - 敌人_ydist = math.hypot(dx, dy)如果距离 >0:敌人 x += min(enemy_vel, dist) * dx/dist敌人y + = min(enemy_vel,dist)* dy/distwindow.fill(0)pygame.draw.circle(window, (0, 128, 255), (player_x, player_y), 10)pygame.draw.circle(window, (255, 32, 32), (enemy_x,敌人_y), 10)pygame.display.flip()pygame.quit()出口()


对于您的特定代码,calculate_enemy_movement 函数可能如下所示:

def calculate_enemy_movement(enemy_blob):dx = player.player_rect.x - 敌人_blob.xdy = player.player_rect.y -enemy_blob.ydist = math.hypot(dx, dy)如果距离 >0:move_x = min(enemy_blob.speed, dist) * dx/distmove_y = min(enemy_blob.speed, dist) * dy/dist返回 move_x, move_y返回 0, 0

move_x, move_y = calculate_enemy_movement(enemy_blob)敌人_blob.x += move_x敌人_blob.y += move_y

In the game i am currently making i need to make an ennemy move towards a player (here the enemy is a blob) to make this, i already created a function : def calculate_enemy_movement(enemy): and inside of it i put what the function needs to do :

calculate what x value needs to be added each frame(x velocity), and what y value needs to be added each frame(y velocity) to the enemy.x and enemy.y to walk towards the player.x and player.y and then return x velocity and return y velocity.
This function gets called here : add x velocity and y velocity to x and y pos of enemy each frame enemy_blob.x,enemy_blob.y += calculate_enemy_movement(enemy_blob)

now i just need someone to help me create this function. I've already looked into it and i know it has something to do with the vector mathematics but i'm not sure how exactly it works, so if someone could write the function and explain me how it works i would be really pleased.

if you need the rest of the code :

import pygame
import os
import sys
from math import *
import math
from typing import Tuple
from pygame.locals import *

running = False

class Game():
    def __init__(self):
        main()

pygame.init()

FPS = 60
ani = 4

def diagonal_x_vel(velocity):
    diagonal_x = int((math.pi / 4) * velocity)
    return diagonal_x

def diagonal_y_vel(velocity):
    diagonal_y = int(sin(math.pi / 4) * velocity)
    return diagonal_y

def move(rect, movement):
    global player_rect
    rect.x += movement[0]
    rect.y += movement[1]
    return rect

WIDTH, HEIGHT = 1920, 1080
player_action = "idle"
player_frame = 0

class Player():
    def __init__(self):
        self.main_char_height, self.main_char_width = 35 * 4, 35 * 4
        self.main_char_x = WIDTH / 2 - self.main_char_width / 2
        self.main_char_y = HEIGHT / 2 - self.main_char_height / 2
        self.current_health = 80
        self.maximum_health = 100
        self.health_bar_length = 500
        self.health_ratio = self.maximum_health / self.health_bar_length
        self.moving_right, self.moving_left, self.moving_down, self.moving_up, self.idle = False, False, False, False, True
        self.player_rect = pygame.Rect(self.main_char_x, self.main_char_y, self.main_char_width, self.main_char_height)

        self.player_flip = False
        self.VEL = 8

        def update():
            pass

        def take_dmg(self, amount):
            if self.current_health > 0:
                self.current_health -= amount
            if self.current_health <= 0:
                self.current_health = 0

        def get_health(self, amount):
            if self.current_health < self.maximum_health:
                self.current_health += amount
            if self.current_health >= self.maximum_health:
                self.current_health = self.maximum_health

class Enemy():
    def __init__(self, health, attack_damage, raw_speed, x, y, height, width, action,diagonal_vel_x,diangonal_vel_y):
        self.x = x
        self.y = y
        self.health = health
        self.attack_damage = attack_damage
        self.speed = raw_speed
        self.enemy_rect = pygame.Rect(x,y,width,height)
        self.action = action

WIN = pygame.display.set_mode([WIDTH, HEIGHT], pygame.FULLSCREEN)
pygame.display.set_caption("first game")

player = Player()
animation_frames = {}

def load_animation(path, image_name, frame_duration, scale_width, scale_height):
    global animation_frames

    animation_frame_data = []
    n = 0
    for frame in frame_duration:
        animation_frame_id = image_name + "_" + str(n)
        img_loc = path + "/" + animation_frame_id + ".png"
        animation_image = pygame.transform.scale(pygame.image.load(img_loc),
                                                 (scale_width, scale_height)).convert_alpha()
        animation_image.convert()

        animation_frames[animation_frame_id] = animation_image.copy()
        for i in range(frame):
            animation_frame_data.append(animation_frame_id)
        n += 1
    return animation_frame_data

def change_action(action_var, frame, new_value):
    if action_var != new_value:
        action_var = new_value
    return action_var, frame

animation_database = {}

animation_database["idle"] = load_animation("assets", "darkpurpleknight_idle", [8, 8, 8, 8], player.main_char_width,
                                            player.main_char_height)
animation_database["run_top"] = load_animation("assets", "darkpurpleknight_run_up", [8, 8, 8, 8, 8, 8],
                                               player.main_char_width,
                                               player.main_char_height)
animation_database["run_bot"] = load_animation("assets", "darkpurpleknight_run_down", [8, 8, 8, 8, 8, 8],
                                               player.main_char_width, player.main_char_height)
animation_database["run"] = load_animation("assets", "darkpurpleknight_run", [8, 8, 8, 8, 8, 8], player.main_char_width,
                                           player.main_char_height)
scroll = [0, 0]

blob_height = 17
blob_width = 25
blob_frame = 0

enemy_blob = Enemy(50, 10, 5, 1000 , 1000, 17, 25, "blob_idle",0,0)

animation_database["blob_idle"] = load_animation("assets", "blob_idle", [30, 30], blob_width * 4, blob_height * 4)

clock = pygame.time.Clock()

def collision(rectA, rectB):
    if rectB.right < rectA.left:
        # rectB est à gauche
        return False
    if rectB.bottom < rectA.top:
        # rectB est au-dessus
        return False
    if rectB.left > rectA.right:
        # rectB est à droite
        return False
    if rectB.top > rectA.bottom:
        # rectB est en-dessous
        return False

    elif rectB.right > rectA.left:
        # rectB est en collision avec la gauche
        return True
    elif rectB.bottom < rectA.top:
        # rectB est en collision avec le haut
        return True
    elif rectB.left > rectA.right:
        # rectB est en collision avec la droite
        return True
    elif rectB.top > rectA.bottom:
        # rectB est en collision avec le bas
        return True

bg_img = pygame.transform.scale(pygame.image.load("assets/DUNGEON_PISKEL_REMAKE_WITH_WALL_PROPS-1.png"),
                                (WIDTH * 2, HEIGHT * 2)).convert()

def animate_sprite(frame_counter, action):
    global animation_database
    frame_counter += 1
    if frame_counter >= len(animation_database[action]):
        frame_counter = 0
    img_id = animation_database[action][frame_counter]
    animated_image = animation_frames[img_id]
    return animated_image, frame_counter

#def calculate_enemy_movement(enemy):
    #calculate what x value needs to be added each frame(x velocity), and what y value needs to be added each frame(y velocity) to the enemy.x and enemy.y to walk
    #towards the player.x and player.y.
    #return x velocity and return y velocity

def draw_window(window):
    global enemy_blob
    window = window
    global main_char_x, main_char_y
    global player_frame, bg_img, blob_frame
    global scroll
    global slide

    #add x velocity and y velocity to x and y pos of enemy each frame
    #enemy_blob.x,enemy_blob.y += calculate_enemy_movement(enemy_blob)

    window.blit(bg_img, (-WIDTH / 2 - scroll[0], -HEIGHT / 2 - scroll[1]))

    blob_img, blob_frame = animate_sprite(blob_frame, enemy_blob.action)
    window.blit(blob_img, (enemy_blob.x - scroll[0], enemy_blob.y - scroll[1]))

    player_img, player_frame = animate_sprite(player_frame, player_action)

    window.blit(pygame.transform.flip(player_img, player.player_flip, False), (player.player_rect.x, player.player_rect.y))

    pygame.display.update()

borders = []
coliding = False

def set_borders(x, y, width, height):
    border = pygame.Rect((x, y), (width, height))
    return border

def check_colision(target, list):
    is_coliding = []
    for i in list:
        is_coliding.append(collision(i, target))
    return is_coliding

def main():
    global scroll
    global player_frame
    global player_action
    global player_flip
    global player_rect, rect1, coliding
    global VEL
    global top_wall
    global borders

    global main_char_x, main_char_y

    global moving_left, moving_right, moving_up, moving_down, idle
    game_running = True

    while game_running:
        clock.tick(FPS)

        for event in pygame.event.get():

            if event.type == pygame.KEYDOWN:
                if event.key == K_ESCAPE:
                    game_running = False
                    from start_menu import Open_launcher
                    Open_launcher()
                    sys.exit()

        top_map_border = set_borders(-WIDTH / 2 - scroll[0], -HEIGHT / 2 + 250 - scroll[1], 5000, 1)
        bot_map_border = set_borders(-WIDTH / 2 - scroll[0], HEIGHT + 355 - scroll[1], 5000, 1)
        left_map_border = set_borders(-WIDTH / 2 + 160 - scroll[0], -HEIGHT / 2 - scroll[1], 1, 5000)
        right_map_border = set_borders(WIDTH + 785 - scroll[0], -HEIGHT / 2 + 150 - scroll[1], 1, 5000)

        borders = [top_map_border, bot_map_border, left_map_border, right_map_border]
        enemies = []

        is_coliding_with_borders = check_colision(player.player_rect, borders)
        is_coliding_with_enemy = check_colision(player.player_rect, enemies)

        top_coliding = is_coliding_with_borders[0]
        bot_coliding = is_coliding_with_borders[1]

        left_coliding = is_coliding_with_borders[2]
        right_coliding = is_coliding_with_borders[3]

        keys = pygame.key.get_pressed()

        # EVERY MOVEMENT THAT USES "A"

        if keys[pygame.K_a]:

            # DIAGONAL TOP LEFT
            if keys[pygame.K_w] and not keys[pygame.K_d]:

                if not left_coliding and not top_coliding:
                    player.player_flip = True
                    player_action, player_frame = change_action(player_action, player_frame, "run")
                    scroll[0] -= diagonal_x_vel(player.VEL)
                    scroll[1] -= diagonal_y_vel(player.VEL)

                elif left_coliding and not top_coliding:
                    player.player_flip = True
                    scroll[1] -= player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run_top")

                elif top_coliding and not left_coliding:
                    player.player_flip = True
                    scroll[0] -= player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run")

                elif left_coliding and top_coliding:
                    player.player_flip = False
                    player_action, player_frame = change_action(player_action, player_frame, "idle")


            # DIAGONAL BOT LEFT
            elif keys[pygame.K_s] and not keys[pygame.K_d]:

                if not left_coliding and not bot_coliding:
                    player.player_flip = True
                    player_action, player_frame = change_action(player_action, player_frame, "run")
                    scroll[0] -= diagonal_x_vel(player.VEL)
                    scroll[1] += diagonal_y_vel(player.VEL)

                elif left_coliding and not bot_coliding:
                    player.player_flip = True
                    scroll[1] += player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run_bot")

                elif not left_coliding and bot_coliding:
                    player.player_flip = True
                    scroll[0] -= player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run")

                elif left_coliding and bot_coliding:
                    player.player_flip = False
                    player_action, player_frame = change_action(player_action, player_frame, "idle")

            # LEFT MOVEMENT
            elif not keys[pygame.K_s] and not keys[pygame.K_d] and not keys[pygame.K_w]:

                if not left_coliding:
                    player.player_flip = True
                    scroll[0] -= player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run")

                else:
                    player.player_flip = True
                    player_action, player_frame = change_action(player_action, player_frame, "run")

            else:
                player_action, player_frame = change_action(player_action, player_frame, "idle")

        # EVERY MOVEMENT THAT USES "D"

        if keys[pygame.K_d]:
            # DIAGONAL TOP RIGHT
            if keys[pygame.K_w] and not keys[pygame.K_a] and not keys[pygame.K_s]:

                if not right_coliding and not top_coliding:
                    player.player_flip = False
                    player_action, player_frame = change_action(player_action, player_frame, "run")
                    scroll[0] += diagonal_x_vel(player.VEL)
                    scroll[1] -= diagonal_y_vel(player.VEL)

                elif right_coliding and not top_coliding:
                    player.player_flip = False
                    scroll[1] -= player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run_top")

                elif top_coliding and not right_coliding:
                    player.player_flip = False
                    scroll[0] += player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run")

                elif right_coliding and top_coliding:
                    player.player_flip = False
                    player_action, player_frame = change_action(player_action, player_frame, "idle")


            # DIAGONAL BOT RIGHT
            elif keys[pygame.K_s] and not keys[pygame.K_a] and not keys[pygame.K_w]:

                if not right_coliding and not bot_coliding:
                    player.player_flip = False
                    player_action, player_frame = change_action(player_action, player_frame, "run")
                    scroll[0] += diagonal_x_vel(player.VEL)
                    scroll[1] += diagonal_y_vel(player.VEL)

                elif right_coliding and not bot_coliding:
                    player.player_flip = False
                    scroll[1] += player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run_bot")

                elif not right_coliding and bot_coliding:
                    player.player_flip = False
                    scroll[0] += player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run")

                elif right_coliding and bot_coliding:
                    player.player_flip = False
                    player_action, player_frame = change_action(player_action, player_frame, "idle")

            # RIGHT MOVEMENT
            elif not keys[pygame.K_s] and not keys[pygame.K_a] and not keys[pygame.K_w]:

                if not right_coliding:
                    player.player_flip = False
                    scroll[0] += player.VEL
                    player_action, player_frame = change_action(player_action, player_frame, "run")

                else:
                    player.player_flip = False
                    player_action, player_frame = change_action(player_action, player_frame, "run")

            else:
                player_action, player_frame = change_action(player_action, player_frame, "idle")

        # EVERY MOVEMENT THAT USES "W"
        if keys[pygame.K_w]:

            # UP MOVEMENT
            if not keys[pygame.K_d] and not keys[pygame.K_a]:
                if not top_coliding:
                    player_action, player_frame = change_action(player_action, player_frame, "run_top")
                    scroll[1] -= player.VEL
                else:
                    player_action, player_frame = change_action(player_action, player_frame, "run_top")

        # EVERY MOVEMENT THAT USES "S"
        if keys[pygame.K_s]:

            # DOWN MOVEMENT
            if not keys[pygame.K_d] and not keys[pygame.K_a]:
                if not bot_coliding:
                    player_action, player_frame = change_action(player_action, player_frame, "run_bot")
                    scroll[1] += player.VEL
                else:
                    player_action, player_frame = change_action(player_action, player_frame, "run_bot")

        if not keys[pygame.K_a] and not keys[pygame.K_s] and not keys[pygame.K_d] and not keys[pygame.K_w]:
            player_action, player_frame = change_action(player_action, player_frame, "idle")

        draw_window(WIN)

解决方案

Compute the vector from the the enemy position to the the player position:

dx = player_x - enemy_x
dy = player_y - enemy_y

Compute the length of the vector (Euclidean distance):

dist = math.sqrt(dx*dx + dy*dy)

or

dist = math.hypot(dx, dy)

Normalize the vector (Unit vector). A normalized vector has a length of 1:

if dist > 0:
    dx /= dist
    dy /= dist

Move the enemy a certain distance in the direction of the vector. Make sure the moving distance is no greater than the remaining distance of the enemy to the player:

move_dist = min(enemy_vel, dist)

enemy_x += move_dist * dx
enemy_y += move_dist * dy 

For a more sophisticated solution see How to make smooth movement in pygame

See also Follow target or mouse


Minimal example:

import pygame, math

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
player_x, player_y, player_vel = 100, 100, 5
enemy_x, enemy_y, enemy_vel = 300, 300, 3

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False          
        
    keys = pygame.key.get_pressed()
    player_x = max(10, min(390, player_x + player_vel * (keys[pygame.K_d] - keys[pygame.K_a])))
    player_y = max(10, min(390, player_y + player_vel * (keys[pygame.K_s] - keys[pygame.K_w])))

    dx = player_x - enemy_x
    dy = player_y - enemy_y
    dist = math.hypot(dx, dy)
    if dist > 0:
        enemy_x += min(enemy_vel, dist) * dx / dist
        enemy_y += min(enemy_vel, dist) * dy / dist

    window.fill(0)
    pygame.draw.circle(window, (0, 128, 255), (player_x, player_y), 10)
    pygame.draw.circle(window, (255, 32, 32), (enemy_x, enemy_y), 10)
    pygame.display.flip()

pygame.quit()
exit()


For your particular code, the calculate_enemy_movement function might look like this:

def calculate_enemy_movement(enemy_blob):
    dx = player.player_rect.x - enemy_blob.x
    dy = player.player_rect.y - enemy_blob.y
    dist = math.hypot(dx, dy)
    if dist > 0:
        move_x = min(enemy_blob.speed, dist) * dx / dist
        move_y = min(enemy_blob.speed, dist) * dy / dist
        return move_x, move_y
    return 0, 0

move_x, move_y = calculate_enemy_movement(enemy_blob)
enemy_blob.x += move_x
enemy_blob.y += move_y

这篇关于pygame 敌人向玩家的二维运动,如何计算 x 和 y 速度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆