允许敌人跟随玩家

时间:2019-07-13 19:57:37

标签: python python-3.x pygame

我正试图吸引一个叫做fudd_img的敌人来追随以bear_img身份扮演的玩家。 fudd_img应该比播放器本身慢。

我尝试使用以下行:

if bear_rect_x > fudd_rect_x:
    fudd_rect_x = fudd_rect_x + max(2, bear_rectx - fudd_rect_x)
elif bear_rect_x < fudd_rect_x:
    fudd_rect_x = fudd_rect_x - max(2, fudd_rect_x - bear_rect_x)

但是,fudd_img会完全充当bear_img,而不是查找bear_img的路径。每当我尝试将其转换为y时,它都将不起作用,并且fudd_img不会沿y轴移动。

import random
import pygame
import sys
import time
import math

# --- constants --- (UPPER_CASE_NAMES)

GREEN = (24, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0,0,0)

SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
SW2 = SCREEN_WIDTH/2
SH2 = SCREEN_HEIGHT/2

#---
camerax = 0
cameray = 0
# --- functions ---

def text_objects(text, font):
    surface = font.render(text, True, BLACK)
    return surface, surface.get_rect()

def message_display(text):
    surface, rect = text_objects(text, CLOCKTXT)
    rect.center = (58, 15)
    screen.blit(surface, rect)
    #pygame.display.update() # use update() only in one place

#generate random pos for fish and grass
def getRandomOffCameraPos(camerax, cameray, objWidth, objHeight):
    camera_rect = pygame.Rect(camerax, cameray, SCREEN_WIDTH, SCREEN_HEIGHT)
    x1 = camerax - SCREEN_WIDTH
    x2 = camerax + (2*SCREEN_WIDTH)
    y1 = cameray - SCREEN_HEIGHT
    y2 = cameray + (2*SCREEN_HEIGHT)
    while True:
        x = random.randint(x1, x2)
        y = random.randint(y1, y2)
        obj_rect = pygame.Rect(x, y, objWidth, objHeight)
        if not obj_rect.colliderect(camera_rect):
            return x, y

def makeNewGrass(camerax, cameray):
    w, h = 80, 80
    x, y = getRandomOffCameraPos(camerax, cameray, w, h)
    images = grasspic
    item = {
        'image': random.choice(images),
        'rect': pygame.Rect(x, y, w, h),
    }
    return item

def makeNewFish(camerax, cameray):
    w, h = 50, 50
    x, y = getRandomOffCameraPos(camerax, cameray, w, h)
    images = fishpic
    item = {
        'image': random.choice(images),
        'rect': pygame.Rect(x, y, w, h),
    }
    return item

def makegrass(number=15):    
    for i in range(number):
        item = makeNewGrass(camerax, cameray)
        item['rect'].x = random.randint(0, SCREEN_WIDTH-item['rect'].width)
        item['rect'].y = random.randint(0, SCREEN_HEIGHT-item['rect'].height)
        allgrass.append(item)

def makefish(number=2):
    for i in range(number):
        item = makeNewFish(camerax, cameray)
        item['rect'].x = random.randint(0, SCREEN_WIDTH-item['rect'].width)
        item['rect'].y = random.randint(0, SCREEN_HEIGHT-item['rect'].height)
        allfish.append(item)

def score_draw(score):
    message_display("Score is: " + str(score))

#--- main ---

pygame.init()

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Hungry Boi') 

CLOCKTXT = pygame.font.Font('freesans.ttf', 20)

# ---

bear_img = pygame.image.load('bear.png')
bear_img = pygame.transform.scale(bear_img, (150, 150))
bear_rect = bear_img.get_rect()
bear_rect.x = SCREEN_WIDTH * 0.4
bear_rect.y = SCREEN_HEIGHT * 0.4
bear_vel = 5

fudd_img = pygame.image.load('fudd.png')
fudd_img = pygame.transform.scale(fudd_img, (150,150))
fudd_rect = fudd_img.get_rect()
fudd_rect.x = SCREEN_WIDTH * 0.4
fudd_rect.y = SCREEN_HEIGHT * 0.4
fudd_vel = 2

grasspic = []
for i in range(1, 5):
    image = pygame.image.load('grass%s.png' % i)
    grasspic.append(image)

fishpic = []
for i in range(1, 3):
    image = pygame.image.load('fish%s.png' % i)
    image = pygame.transform.scale(image, (50, 50))
    fishpic.append(image)

# ---

allgrass = []
makegrass()

allfish = []
makefish()

x_change = 0
y_change = 0

score = 0
time = 60

# --- mainloop ---

gameExit = False
clock = pygame.time.Clock()

while not gameExit:

    # --- events ---

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameExit = True

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                x_change -= bear_vel
            elif event.key == pygame.K_RIGHT:
                x_change += bear_vel
            elif event.key == pygame.K_UP:
                y_change -= bear_vel
            elif event.key == pygame.K_DOWN:
                y_change += bear_vel

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                x_change += bear_vel
            elif event.key == pygame.K_RIGHT:
                x_change -= bear_vel
            elif event.key == pygame.K_UP:
                y_change += bear_vel
            elif event.key == pygame.K_DOWN:
                y_change -= bear_vel

    # --- updates ---

    bear_rect.x += x_change
    bear_rect.y += y_change

    keep_fish = []
    for fish in allfish:
        if not bear_rect.colliderect(fish['rect']):
            keep_fish.append(fish)
        else:
            makefish(1)
            #makegrass()
            score += 1
    allfish = keep_fish

    # --- time down ---
    for i in range(60):
        time -= 1

    # --- draws ---

    screen.fill(GREEN)

    for grass in allgrass:
        screen.blit(grass['image'], grass['rect'].move(camerax, cameray))

    for fish in allfish:
        screen.blit(fish['image'], fish['rect'].move(camerax, cameray))

    screen.blit(bear_img, bear_rect.move(camerax, cameray))
    screen.blit(fudd_img, fudd_rect.move(camerax, cameray))
    score_draw(score)


    pygame.display.update()

    # --- FPS ---

    clock.tick(30) #fps//may not be safe to run really fast

# --- end ---

pygame.quit()

如何让fudd_img跟随玩家,bear_img而不是跟随玩家顶部并在游戏的左上角生成?我希望以后,这将使碰撞系统更容易工作。

谢谢

1 个答案:

答案 0 :(得分:1)

如果必须沿直线行驶且没有任何障碍,则可以使用pygame.math.Vector2D进行所有计算。它具有使它变得更简单的所有必需功能,并且使用float值,因此移动可以更平滑。

首先,我将职位从pygame.Rect转换为pygame.math.Vector2D

player_vector = pygame.math.Vector2(player_rect.center)
enemy_vector = pygame.math.Vector2(enemy_rect.center)

接下来,我计算两个对象之间的差异(它仍然给出矢量)

diff = player_vector - enemy_vector

如果我将其添加到敌人的位置,那么它将获得玩家的位置-敌人将使玩家一步一步,但我需要具有相同方向的较短矢量来使敌人移动得更慢-使其逐步移动。

如果我对向量进行归一化,那么我得到的向量方向相同但较短。它的长度是1。

move = diff.normalize()

现在我可以将其添加到敌人的位置,以向玩家的方向迈出一步。

enemy_vector += move

现在我可以使用新位置将其转换回pygame.Rect中的位置

enemy_rect.center = enemy_vector

并在屏幕上绘制

pygame.draw.rect(screen, GREEN, player_rect)
pygame.draw.rect(screen, RED, enemy_rect)

如果我想更快地移动,可以乘以归一化向量

move = diff.normalize() * 2

player_vector = pygame.math.Vector2(player_rect.center)
enemy_vector = pygame.math.Vector2(enemy_rect.center)

diff = player_vector - enemy_vector

move = diff.normalize() * 2
enemy_vector += move

enemy_rect.center = enemy_vector

pygame.draw.rect(screen, GREEN, player_rect)
pygame.draw.rect(screen, RED, enemy_rect)

为了使移动更平滑,我将敌人的位置保留在Vector中(作为浮点值)并转换为pygame。Rect仅作画。

完整的示例。玩家处于中心位置,敌人从随机位置开始向玩家移动。它还显示对象之间的线。您可以使用箭头移动播放器。

import pygame
import random

# --- constants --- (UPPER_CASE_NAMES)

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 600

SCREEN_WIDTH_HALF = SCREEN_WIDTH//2
SCREEN_HEIGHT_HALF = SCREEN_HEIGHT//2

#--- main ---

pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

player_rect = pygame.Rect(0, 0, 16, 16)
player_rect.center = (SCREEN_WIDTH_HALF, SCREEN_HEIGHT_HALF)
player_speed = 2

enemy_rect = pygame.Rect(0, 0, 16, 16)
enemy_rect.centerx = random.randint(0, SCREEN_WIDTH)
enemy_rect.centery = random.randint(0, SCREEN_HEIGHT)
enemy_speed = 2

enemy_vector = pygame.math.Vector2(enemy_rect.center)

#old_rect = enemy_rect.copy()

clock = pygame.time.Clock()

run = True
while run:
    clock.tick(15) # 120 FPS
    #pygame.time.delay(5)

    # --- events ---

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    # --- changes ---

    keys = pygame.key.get_pressed()

    # move player

    if player_rect.top > 0 and keys[pygame.K_UP]:
        player_rect.y -= player_speed
    if player_rect.bottom < SCREEN_HEIGHT and keys[pygame.K_DOWN]:
        player_rect.y += player_speed

    if player_rect.left > 0 and keys[pygame.K_LEFT]:
        player_rect.x -= player_speed
    if player_rect.right < SCREEN_WIDTH and keys[pygame.K_RIGHT]:
        player_rect.x += player_speed

    # enemy follow player

    player_vector = pygame.math.Vector2(player_rect.center)
    diff = player_vector - enemy_vector
    if diff.length() > 0.1:
        move = diff.normalize() * enemy_speed
        enemy_vector += move
        enemy_rect.center = enemy_vector

    # -- draws ---

    screen.fill(BLACK)

    pygame.draw.line(screen, WHITE, player_rect.center, enemy_rect.center)
    pygame.draw.rect(screen, GREEN, player_rect)
    pygame.draw.rect(screen, RED, enemy_rect)
    #pygame.draw.rect(screen, WHITE, old_rect)

    pygame.display.flip()

# --- end ---

pygame.quit()