【问题标题】:Pygame Collision ErrorPygame 碰撞错误
【发布时间】:2018-05-11 08:26:21
【问题描述】:

我正在 pygame 中编写一个简单的躲避游戏,希望我能开发它来构建类似 Asteroids 的东西。

我使用.collidelist() 来识别与我随机生成的“小行星”的碰撞。但是当玩家进入小行星下方或上方时,就会检测到碰撞。

# -------------------- COLLISION  --------------------
        collision =  player_rect.collidelist(objects)
        if collision != -1:
            lives -= 1
            if lives >= 0:
                gameLoop()
            else:
                pygame.quit()
                quit()

我的小行星似乎只在垂直方向移动,而不是水平移动,即使我已经改变了它们的水平值。

for x in random_x_pos:
            random_y_pos[random_x_pos.index(x)] += object_y_vel[random_x_pos.index(x)]
            x += object_x_vel[random_x_pos.index(x)]

这是我的其余代码:

import pygame, random
from pygame.locals import *

pygame.init()
pygame.display.set_caption('Dodge')

#icon = pygame.image.load('icon.png')
#pygame.display.set_icon(icon)

# -------------------- Colours  --------------------
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
green = (0,155,0)
blue = (0,0,255)
pink = (233,30,98)

# -------------------- Variables  --------------------
display_width = 600
display_height = 600
FPS = 60
lives = 3

clock = pygame.time.Clock()
gameDisplay = pygame.display.set_mode((display_width, display_height))

# -------------------- Actual Game  --------------------
def gameLoop():
    global lives
    # -------------------- Player  --------------------
    player_dim = 20
    x_pos = ((display_width / 2) - player_dim)
    y_pos = ((display_height / 2) - player_dim)
    vel = 5
    player_rect = pygame.draw.rect(gameDisplay, pink, (x_pos, y_pos, player_dim, player_dim))

    # -------------------- Random Objects  --------------------
    object_dimensions  = 30
    amount_of_objects = 10
    random_x_pos, random_y_pos, object_x_vel, object_y_vel, objects = [], [], [], [], []
    for int in range(amount_of_objects):
        x, y, x_vel, y_vel = random.randint(0, display_width), random.randint(0, display_height), random.randint(-5,5), random.randint(-5,5)
        rect1 = pygame.draw.rect(gameDisplay, white, (x, y, 30, 30))
        again = rect1.colliderect(player_rect)
        while again:
            x, y = random.randint(0, display_width), random.randint(0, display_height)
            rect1 = pygame.draw.rect(gameDisplay, white, (x, y, 30, 30))
            again = rect1.colliderect(player_rect)
        random_x_pos.append(x)
        random_y_pos.append(y)
        object_x_vel.append(x_vel)
        object_y_vel.append(y_vel)

    # -------------------- Event Handling  --------------------
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        keys = pygame.key.get_pressed()
        if keys[pygame.K_ESCAPE]:
            pygame.quit()
            quit()
        if keys[pygame.K_UP] and y_pos > 0:
            y_pos -= vel
        if keys[pygame.K_DOWN] and (y_pos + player_dim) < display_height:
            y_pos += vel
        if keys[pygame.K_LEFT] and x_pos > 0:
            x_pos -= vel
        if keys[pygame.K_RIGHT] and (x_pos + player_dim) < display_width:
            x_pos += vel

        for x in random_x_pos:
            random_y_pos[random_x_pos.index(x)] += object_y_vel[random_x_pos.index(x)]
            x += object_x_vel[random_x_pos.index(x)]

        # -------------------- COLLISION  --------------------
        collision =  player_rect.collidelist(objects)
        if collision != -1:
            lives -= 1
            if lives >= 0:
                gameLoop()
            else:
                pygame.quit()
                quit()

        gameDisplay.fill(black)
        player_rect = pygame.draw.rect(gameDisplay, pink, (x_pos, y_pos, player_dim, player_dim))
        for obj in random_x_pos:
            y = random_y_pos[random_x_pos.index(obj)]
            var = pygame.draw.rect(gameDisplay, white, (obj, y, object_dimensions, object_dimensions))
            objects.append(var)
        pygame.display.update()
        clock.tick(FPS)


gameLoop()

【问题讨论】:

    标签: python pygame collision rect


    【解决方案1】:

    for obj in random_x_pos: 循环中,您疯狂地将新的矩形附加到objects 列表中。您无需移动并绘制这些旧矩形,因此您很快就会获得数千个仍用于碰撞检测的不可见矩形。

    您必须重组代码。我建议创建一个矩形列表及其速度。

    objects = []
    
    for i in range(amount_of_objects):
        rect = pygame.Rect(random.randint(0, display_width), random.randint(0, display_height), 30, 30)
        velocity = [random.randint(-5,5), random.randint(-5,5)]
        # Put the rect and the velocity into a list and append it to the objects.
        objects.append([rect, velocity])
    

    在 for 循环中更新矩形位置。可以同时进行碰撞检测。

    collision = False
    for rect, velocity in objects:
        rect.x += velocity[0]
        rect.y += velocity[1]
    
        if player_rect.colliderect(rect):
            collision = True
    
    if collision:
        lives -= 1
        # etc.
    

    像这样画矩形:

    for rect, velocity in objects:
        pygame.draw.rect(gameDisplay, white, rect)
    

    【讨论】:

    • 非常感谢。
    【解决方案2】:

    您的问题之一在于以下代码片段:

    for x in random_x_pos:
                random_y_pos[random_x_pos.index(x)] += object_y_vel[random_x_pos.index(x)]
                x += object_x_vel[random_x_pos.index(x)]
    

    在这个循环中,x 是循环变量,在循环的每个循环中都会发生变化。 x += object_x_vel[random_x_pos.index(x)] 行对代码没有影响,因为紧随其后的是下一个循环迭代,其中 x 被分配给 random_x_pos 的下一个值。

    相反,您可以尝试以下方法:

    for i in range(len(random_x_pos)):
                random_y_pos[i] += object_y_vel[i]
                random_x_pos[i] += object_x_vel[i]
    

    但请注意,您的代码中还有其他缺陷。例如,您将 python 内部 int 分配给循环变量并因此覆盖它。这可能会导致不良行为。

    【讨论】:

    • 非常感谢。
    猜你喜欢
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多