【问题标题】:Pygame mask collisionPygame蒙版碰撞
【发布时间】:2020-05-21 11:40:54
【问题描述】:

我正在尝试在 pygame 中对旋转表面进行正确的碰撞检测。我决定尝试使用口罩。它有点工作,但它不像我喜欢/想的那么精确。我尝试在循环结束时更新蒙版以获得下一帧的“新鲜”命中框,但它没有按预期工作。我的错误是什么?

import pygame
import random

WHITE = [255, 255, 255]
RED = [255, 0, 0]

pygame.init()

FPS = pygame.time.Clock()
fps = 6

winW = 1000
winH = 500
BGCOLOR = WHITE
win = pygame.display.set_mode((winW, winH))
win.fill(WHITE)
pygame.display.set_caption('')
pygame.display.set_icon(win)


class Box(pygame.sprite.Sprite):
    def __init__(self, x, y, w, h):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([w, h], pygame.SRCALPHA)
        self.image.fill(random_color())
        self.mask = pygame.mask.from_surface(self.image)
        self.rect = pygame.Rect(x, y, w, h)
        self.angle = 0

    def move(self):
        self.rect.center = pygame.mouse.get_pos()

    def draw(self):
        blits = self.rotate()
        win.blit(blits[0], blits[1])
        self.mask = pygame.mask.from_surface(blits[0])

    def rotate(self):
        self.angle += 3
        new_img = pygame.transform.rotate(self.image, self.angle)
        new_rect = new_img.get_rect(center=self.rect.center)
        return new_img, new_rect


def update_display():
    win.fill(BGCOLOR)
    player.draw()
    for p in platforms:
        p.draw()
    pygame.display.update()


def collision():
    return pygame.sprite.spritecollide(player, plat_collide, False, pygame.sprite.collide_mask)


def random_color():
    return [random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)]


player = Box(100, 400, 50, 50)

platforms = [Box(300, 400, 100, 50)]
plat_collide = pygame.sprite.Group(platforms)

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

    hits = collision()
    if hits:
        BGCOLOR = RED
    else:
        BGCOLOR = WHITE

    player.move()

    update_display()

    FPS.tick(fps)

pygame.quit()

【问题讨论】:

    标签: python pygame collision-detection


    【解决方案1】:

    您的应用程序运行良好。但请注意,pygame.sprite.collide_mask() 使用 sprite 对象的 .rect.mask 属性进行碰撞检测。
    旋转图片后必须更新self.rect

    class Box(pygame.sprite.Sprite):
        # [...]
    
        def rotate(self):
            self.angle += 3
            new_img = pygame.transform.rotate(self.image, self.angle)
            new_rect = new_img.get_rect(center=self.rect.center)
            
            # update .rect attribute
            self.rect = new_rect # <------
            
            return new_img, new_rect
    

    另见Sprite mask


    最小示例: repl.it/@Rabbid76/PyGame-SpriteMask

    import pygame
    
    class SpriteObject(pygame.sprite.Sprite):
        def __init__(self, x, y, w, h, color):
            pygame.sprite.Sprite.__init__(self)
            self.angle = 0
            self.original_image = pygame.Surface([w, h], pygame.SRCALPHA)
            self.original_image.fill(color)
            self.image = self.original_image
            self.rect = self.image.get_rect(center = (x, y))
            self.mask = pygame.mask.from_surface(self.image )
        def update(self):
            self.rotate()
        def rotate(self):
            self.angle += 0.3
            self.image = pygame.transform.rotate(self.original_image, self.angle)
            self.rect = self.image.get_rect(center = self.rect.center)
            self.mask = pygame.mask.from_surface(self.image )
    
    pygame.init()
    clock = pygame.time.Clock()
    window = pygame.display.set_mode((400, 400))
    size = window.get_size()
    
    moving_object = SpriteObject(0, 0, 50, 50, (128, 0, 255))
    static_objects = [
        SpriteObject(size[0] // 2, size[1] // 3, 100, 50, (128, 128, 128)),
        SpriteObject(size[0] // 4, size[1] * 2 // 3, 100, 50, (128, 128, 128)),
        SpriteObject(size[0] * 3 // 4, size[1] * 2 // 3, 100, 50, (128, 128, 128))
    ]
    all_sprites = pygame.sprite.Group([moving_object] + static_objects)
    static_sprites = pygame.sprite.Group(static_objects)
    
    run = True
    while run:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        moving_object.rect.center = pygame.mouse.get_pos()
        all_sprites.update() 
        collide = pygame.sprite.spritecollide(moving_object, static_sprites, False, pygame.sprite.collide_mask)
        
        window.fill((255, 0, 0) if collide else (255, 255, 255))
        all_sprites.draw(window)
        pygame.display.update()
    
    pygame.quit()
    exit()
    

    【讨论】:

    • 既然你提到它,它就很有意义。谢谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 2015-02-22
    相关资源
    最近更新 更多