python - pygame中的 Sprite 掩码碰撞问题

标签 python python-3.x pygame collision-detection collision

我正在尝试在 pygame 中创建赛车游戏。我想要这样,当汽车离开赛道时,它会减速。我试图通过另一个 Sprite 来做到这一点,它是赛道的轮廓,当汽车接触到那个 Sprite 时,它会减速。这不起作用,我不知道为什么。有更好的方法吗?

Img是汽车图片

后面是跑道

BackHit是轮廓

我收到此错误代码:

Traceback (most recent call last): File "C:\Users\Daniella\Desktop\Python\Games\game.py", line 75, in if pygame.sprite.collide_mask(Img, BackHit): File "C:\Users\Daniella\AppData\Roaming\Python\Python36\site-packages\pygame\sprite.py", line 1470, in collide_mask xoffset = right.rect[0] - left.rect[0] AttributeError: 'pygame.Surface' object has no attribute 'rect'

这是代码:

import pygame

Width = 800
Height = 600

Black = (0, 0, 0)
White = (255, 255, 255)
Red = (255, 0, 0)
Green = (0, 255, 0)
Blue = (0, 0, 255)
Yellow = (255, 255, 0)
BackColour = (198, 151, 107)

pygame.init()
GameDisplay = pygame.display.set_mode((Width, Height))
pygame.display.set_caption("A bit Racey")
Clock = pygame.time.Clock()

Img = pygame.image.load("download.png")
ImgWidth = 46
ImgHeight = 68
Img = pygame.transform.scale(Img, (ImgWidth, ImgHeight))

Back = pygame.image.load("back1.png")
BackWidth = Width*4
BackHeight = Height*4
Back = pygame.transform.scale(Back, (BackWidth, BackHeight))

BackHit = pygame.image.load("back1 hit1.png")
BackHitWidth = Width*4
BackHitHeight = Height*4
BackHit = pygame.transform.scale(BackHit, (BackHitWidth, BackHitHeight))

def Car():
    GameDisplay.blit(Img, (400-ImgWidth/2, 300-ImgHeight/2))

def Background(X, Y):
    GameDisplay.blit(Back, (X, Y))

def BackgroundHit(X, Y):
    GameDisplay.blit(BackHit, (X, Y))

X = (Width*0.45)
Y = (Height*0.5)

XChange = 0
YChange = 0

Changer = 1

Crashed = False

while not Crashed:
    for Event in pygame.event.get():
        if Event.type == pygame.QUIT:
            Crashed = True
        elif Event.type == pygame.KEYDOWN:
            if Event.key == pygame.K_LEFT:
                Img = pygame.transform.rotate(Img, -90)
                XChange = 5 / Changer
            elif Event.key == pygame.K_RIGHT:
                Img = pygame.transform.rotate(Img, 90)
                XChange = -5 / Changer
            elif Event.key == pygame.K_UP:
                Img = pygame.transform.rotate(Img, 0)
                YChange = 5 / Changer
            elif Event.key == pygame.K_DOWN:
                Img = pygame.transform.rotate(Img, 180)
                YChange = -5 / Changer
        if Event.type == pygame.KEYUP:
            if Event.key == pygame.K_LEFT or Event.key == pygame.K_RIGHT:
                XChange = 0
            elif Event.key == pygame.K_UP or Event.key == pygame.K_DOWN:
                YChange = 0
    if pygame.sprite.collide_mask(Img, BackHit):
        Changer = 2
    Y += YChange
    X += XChange
    GameDisplay.fill(White)
    BackgroundHit(X, Y)
    Background(X, Y)
    Car()
    pygame.display.update()
    Clock.tick(200)

pygame.quit()
quit()

最佳答案

这是一个小例子,向您展示如何使用 pygame.mask.from_surfacepygame.Mask.overlap用于像素完美碰撞检测。

import pygame as pg

# Transparent surfaces with a circle and a triangle.
circle_surface = pg.Surface((60, 60), pg.SRCALPHA)
pg.draw.circle(circle_surface, (30, 90, 200), (30, 30), 30)
triangle_surface = pg.Surface((60, 60), pg.SRCALPHA)
pg.draw.polygon(triangle_surface, (160, 250, 0), ((30, 0), (60, 60), (0, 60)))


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()

    # Use `pygame.mask.from_surface` to get the masks.
    circle_mask = pg.mask.from_surface(circle_surface)
    triangle_mask = pg.mask.from_surface(triangle_surface)

    # Also create rects for the two images/surfaces.
    circle_rect = circle_surface.get_rect(center=(320, 240))
    triangle_rect = triangle_surface.get_rect(center=(0, 0))

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.MOUSEMOTION:
                triangle_rect.center = event.pos

        # Now calculate the offset between the rects.
        offset_x = triangle_rect.x - circle_rect.x
        offset_y = triangle_rect.y - circle_rect.y

        # And pass the offset to the `overlap` method of the mask.
        overlap = circle_mask.overlap(triangle_mask, (offset_x, offset_y))
        if overlap:
            print('The two masks overlap!', overlap)

        screen.fill((30, 30, 30))
        screen.blit(circle_surface, circle_rect)
        screen.blit(triangle_surface, triangle_rect)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

要为背景或赛道创建 mask ,您需要创建一个额外的图像,并让赛道或汽车应该减速的区域保持透明,然后检查汽车是否与赛道或外部区域发生碰撞。在这里,我检查绿色三角形是否与“轨道”(蓝线)相撞,在您的游戏中,如果汽车没有与轨道相撞,您就会减速。

import pygame as pg


bg_surface = pg.Surface((640, 480), pg.SRCALPHA)
pg.draw.lines(
    bg_surface, (30, 90, 200), True,
    ((60, 130), (300, 50), (600, 200), (400, 400), (150, 300)),
    12)
triangle_surface = pg.Surface((60, 60), pg.SRCALPHA)
pg.draw.polygon(triangle_surface, (160, 250, 0), ((30, 0), (60, 60), (0, 60)))


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()

    bg_mask = pg.mask.from_surface(bg_surface)
    triangle_mask = pg.mask.from_surface(triangle_surface)

    bg_rect = bg_surface.get_rect(center=(320, 240))
    triangle_rect = triangle_surface.get_rect(center=(0, 0))

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.MOUSEMOTION:
                triangle_rect.center = event.pos

        offset_x = triangle_rect.x - bg_rect.x
        offset_y = triangle_rect.y - bg_rect.y

        overlap = bg_mask.overlap(triangle_mask, (offset_x, offset_y))
        if overlap:
            print('The two masks overlap!', overlap)

        screen.fill((30, 30, 30))
        screen.blit(bg_surface, bg_rect)
        screen.blit(triangle_surface, triangle_rect)

        pg.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

关于python - pygame中的 Sprite 掩码碰撞问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46862739/

相关文章:

python - 如何更新Twisted中UDP协议(protocol)实例的值?

python - 在 Django 管理中,如何强制 "View on Site"按钮忽略站点?

python - 如果涉及最后一行,QPlainTextEdit 中的取消缩进功能会导致段错误

python json转储unicode错误

python - 缺少 python 3 API 函数

python - Pygame 安装在 Windows 上,尝试调用 pygame.image.load() 时得到 "pygame.error: Failed loading libwebp-7.dll"

python - PyGame:每次移动鼠标时计时器都会重置

python - 从字典中存在的列表值中获取单个 "set"对象

python-3.x - PyCharm : IDE does not seem to recognise Python 3 even with 3.x interpreter set

python - PYGAME:碰撞无法正常工作。播放器和平台表现不佳。帮助,这里是python的新手