告诉敌人通过屏幕边界的方式比走遍整个屏幕要短

Teach enemy that the way thru screen border is shorter than going all over the screen

我正在做一个项目,一个小游戏,我在其中整合了我从之前问题的答案中学到的一些东西。嗯,我想做一个标题画面。一切正常,但在“游戏”中我集成了“wraparound-effect”,这意味着玩家从屏幕的一侧离开并进入另一侧。我的效果版本非常简单,正因为如此,怪物无法跟随玩家穿过屏幕边界并在屏幕上走来走去,这让游戏变得更加简单,这不是我想要的。

我可以教敌人通过屏幕边界跟随玩家吗?

代码如下:

#sorry if the code isn't perfect, please just answer my question :) (you don't have to rewrite it)
#enemy means devil, I first did not want to make more enemies.
import pygame, time, math
pygame.init()

display_width = 1300
display_height = 700
win = pygame.display.set_mode((display_width, display_height))
clock = pygame.time.Clock()
Icon = pygame.image.load("Enmy.png")
pygame.display.set_icon(Icon)

playerimg = pygame.image.load("Playr.png").convert_alpha()
imgsize = (57, 100)
playerimg = pygame.transform.scale(playerimg, imgsize)

enmimg = pygame.image.load("Enmy.png").convert_alpha()
imgsze = (57, 100)
enmimg = pygame.transform.scale(enmimg, imgsze)

slimeimg = pygame.image.load("slime.png").convert_alpha()
imgesize = (57, 100)
slimeimg = pygame.transform.scale(slimeimg, imgesize)

gameover = pygame.image.load("GameOver.png")
imgsz = (100, 100)
gameover = pygame.transform.scale(gameover, imgsz)

player = playerimg.get_rect(center = (650, 350))
vel = 3

enemy = enmimg.get_rect(center = (650, 600))
EnemyVel = 2.7
DevilLives = 1

slime = slimeimg.get_rect(center = (650, 100))
slimeVel = 2.3
slimeLives = 1

Gameover = gameover.get_rect(center = (350, 350))

def text_objects(text, font):
    textSurface = font.render(text, True, (0, 0, 0))
    return textSurface, textSurface.get_rect()

def Intro():
    intro = True

    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

        key = pygame.key.get_pressed()
        if key[pygame.K_SPACE]:
            intro = False

        win.fill((255, 255, 255))
        largeText = pygame.font.Font('freesansbold.ttf',115)
        TextSurf, TextRect = text_objects("Monster Run", largeText)
        mediumText = pygame.font.Font("freesansbold.ttf",40)
        textSurf, textRect = text_objects("Press SPACE to start", mediumText)
        TextRect.center = ((display_width/2),(150))
        textRect.center = ((display_width/2),(670))
        win.blit(TextSurf, TextRect)
        win.blit(textSurf, textRect)
        win.blit(playerimg, player)
        win.blit(enmimg, enemy)
        pygame.display.flip()
        clock.tick(15)

def game():
    run = True
    while run:
        clock.tick(50)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                exit()

        collideDevil = player.colliderect(enemy)
        collideSlime = player.colliderect(slime)
        cldDevlSlm = enemy.colliderect(slime)
        if cldDevlSlm:
            enemy.x = enemy.x + 20
            slime.x = slime.x - 20
            
        if collideSlime:
            pygame.quit()
            exit(0)
        if collideDevil:
            pygame.quit()
            exit(0)
            
        keys = pygame.key.get_pressed()
        player.x += (keys[pygame.K_d] - keys[pygame.K_a]) * vel
        player.y += (keys[pygame.K_s] - keys[pygame.K_w]) * vel
        player.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
        player.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel

        #wraparound-effect
        if player.x <= -40:
            player.x = player.x + 1300
        if player.x >= 1300:
            player.x = player.x - 1340
        if player.y <= -40:
            player.y = player.y + 700
        if player.y >= 700:
            player.y = player.y - 740

    #devil "AI"

        dx = player.x - enemy.x
        dy = player.y - enemy.y
        dist = math.hypot(dx, dy)
        if dist > 0:
            enemy.x += min(EnemyVel, dist) * dx / dist
            enemy.y += min(EnemyVel, dist) * dy / dist

    #slime "AI"
        Dx = player.x - slime.x
        Dy = player.y - slime.y
        Dist = math.hypot(Dx, Dy)
        if Dist > 0:
            slime.x += min(slimeVel, Dist) * Dx / Dist
            slime.y += min(slimeVel, Dist) * Dy / Dist
                
        win.fill((255, 255, 255))
        win.blit(enmimg, enemy)
        win.blit(playerimg, player)
        win.blit(slimeimg, slime)
        pygame.display.flip()

Intro()
game()

使用取模 (%) 运算符简化将播放器“包裹”在屏幕周围的代码:

player.x %= 1340
player.y %= 740

“反转”敌人的移动,如果敌人和玩家之间的距离大于宽度的一半或高度的一半:

dx = player.x - enemy.x
dy = player.y - enemy.y
w = 1340
h = 740
if dx > w/2:
    dx -= w
elif dx < -w/2:
    dx += w 
if dy > h/2:
    dy -= w
elif dy < -h/2:
    dy += h 

最后将敌人“包裹”在屏幕周围:

enemy.x %= 1340
enemy.y %= 740

最小示例:

import pygame, math

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

player = pygame.Rect(250, 150, 20, 20)
vel = 5
enemy = pygame.Rect(50, 150, 20, 20)
enemyVel = 3

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

    keys = pygame.key.get_pressed()
    player.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
    player.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
    player.x %= (window.get_width() + player.width)
    player.y %= (window.get_height() + player.height)

    dx = player.x - enemy.x
    dy = player.y - enemy.y
    w = (window.get_width() + player.width)
    h = (window.get_height() + player.height)
    if dx > w/2:
        dx -= w
    elif dx < -w/2:
        dx += w 
    if dy > h/2:
        dy -= w
    elif dy < -h/2:
        dy += h 
    dist = math.hypot(dx, dy)
    if dist > 0:
        enemy.x += min(enemyVel, dist) * dx / dist
        enemy.y += min(enemyVel, dist) * dy / dist
    enemy.x %= (window.get_width() + enemy.width)
    enemy.y %= (window.get_height() + enemy.height)

    window.fill(0)
    pygame.draw.rect(window, (0, 0, 255), player)
    pygame.draw.rect(window, (255, 0, 0), enemy)
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
exit()