Python pygame位掩码冲突获胜';行不通

Python pygame位掩码冲突获胜';行不通,python,pygame,sprite,collision,Python,Pygame,Sprite,Collision,虽然当我使用pygame.sprite.collide_rect或pygame.sprite.collide_circle时会检测到冲突,但当我尝试将位掩码分配给精灵并按此方式运行时,不会检测到冲突。(通过wall.collision_action()可以使第一个圆以与另一个圆相同的速度和方向移动)尽管现在不需要考虑这一点, 由于我使用的是圆的图像,这使得pygame.sprite.collide_圆可以很好地工作,所以将来我使用更详细的非圆sprite时,效果会更好 代码: 位掩码冲突在您的代

虽然当我使用
pygame.sprite.collide_rect
pygame.sprite.collide_circle
时会检测到冲突,但当我尝试将位掩码分配给精灵并按此方式运行时,不会检测到冲突。(通过
wall.collision_action()
可以使第一个圆以与另一个圆相同的速度和方向移动)尽管现在不需要考虑这一点,
由于我使用的是圆的图像,这使得pygame.sprite.collide_圆可以很好地工作,所以将来我使用更详细的非圆sprite时,效果会更好

代码:

位掩码冲突在您的代码中起作用,但我认为代码使它变得更加困难,因为精灵对象
ball\u class
wall\u class
中定义了单独的子精灵对象

class ball_class(pygame.sprite.Sprite):
    def __init__(self, surface):
        self.surface = surface
        self.x = 250
        self.y = 250
        self.vy = 0
        self.vx = 0
        self.sprite = pygame.sprite.Sprite()    # <-- HERE
        ...
请注意
图像
rect
掩码
成员变量。在此之前,代码在包含的sprite之外使用这些。但是PyGame库的编写是为了将它们作为类的成员,如果没有定义它们,它将无法正常工作。另外,您的两个精灵类没有调用基本精灵初始化器函数

这是你的代码的一个重新工作,当球碰到墙角时,会发生适当的碰撞(使用位掩码)

ball_64.png

import pygame, sys, math
from pygame.locals import *
pygame.init()

class ball_class(pygame.sprite.Sprite):
    def __init__(self, surface):
        pygame.sprite.Sprite.__init__(self)
        self.surface = surface
        self.x = 250
        self.y = 250
        self.vy = 0
        self.vx = 0
        self.image = pygame.image.load("ball_64.png").convert_alpha()
        self.rect  = self.image.get_rect(center = (self.x, self.y))
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]
        self.mask = pygame.mask.from_surface(self.image)

    def event(self, event):
        if event.key == K_UP:
            self.vy = -1
            self.vx = 0
        elif event.key == K_DOWN:
            self.vy = 1
            self.vx = 0
        elif event.key == K_LEFT:
            self.vx = -1
            self.vy = 0
        elif event.key == K_RIGHT:
            self.vx = 1
            self.vy = 0

    def move(self):
        self.y += self.vy
        self.x += self.vx
        self.rect.topleft = [int(self.x), int(self.y)]
        #self.mask = pygame.mask.from_surface(self.sprite.image)

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def position(self):
        return self.rect()

class wall_class(pygame.sprite.Sprite):
    def __init__(self, surface):
        pygame.sprite.Sprite.__init__(self)
        self.x = 250
        self.y = 100
        self.vy = 0
        self.image = pygame.image.load("wall.png").convert_alpha()
        self.rect  = self.image.get_rect(center = (self.x, self.y))
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]
        self.mask = pygame.mask.from_surface( self.image )

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def collision_action(self, by_sprite_at ):
        print("wall_class.collision_action( by_sprite_at=%s )" % ( str( by_sprite_at ) ) )
#        self.vy = ball.vy
#        self.vx = ball.vx
#        self.x += self.vx
#        self.y += self.vy
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]

def gameQuit():
    pygame.quit()
    sys.exit()

screen = pygame.display.set_mode((500, 500), 0, 32)
ball = ball_class(screen)
wall = wall_class(screen)
clock = pygame.time.Clock()
while True:
    screen.fill((128,128,128))
    ball.move()
    ball.draw(screen)
    wall.draw(screen)
    is_a_collision = pygame.sprite.collide_mask(wall, ball)
    if is_a_collision:
        wall.collision_action( ball.rect.center )

    for event in pygame.event.get():
        if event.type == QUIT:
            gameQuit()
        elif event.type == KEYDOWN:
            ball.event(event)
    clock.tick(100)
    pygame.display.update()
wall.png

import pygame, sys, math
from pygame.locals import *
pygame.init()

class ball_class(pygame.sprite.Sprite):
    def __init__(self, surface):
        pygame.sprite.Sprite.__init__(self)
        self.surface = surface
        self.x = 250
        self.y = 250
        self.vy = 0
        self.vx = 0
        self.image = pygame.image.load("ball_64.png").convert_alpha()
        self.rect  = self.image.get_rect(center = (self.x, self.y))
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]
        self.mask = pygame.mask.from_surface(self.image)

    def event(self, event):
        if event.key == K_UP:
            self.vy = -1
            self.vx = 0
        elif event.key == K_DOWN:
            self.vy = 1
            self.vx = 0
        elif event.key == K_LEFT:
            self.vx = -1
            self.vy = 0
        elif event.key == K_RIGHT:
            self.vx = 1
            self.vy = 0

    def move(self):
        self.y += self.vy
        self.x += self.vx
        self.rect.topleft = [int(self.x), int(self.y)]
        #self.mask = pygame.mask.from_surface(self.sprite.image)

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def position(self):
        return self.rect()

class wall_class(pygame.sprite.Sprite):
    def __init__(self, surface):
        pygame.sprite.Sprite.__init__(self)
        self.x = 250
        self.y = 100
        self.vy = 0
        self.image = pygame.image.load("wall.png").convert_alpha()
        self.rect  = self.image.get_rect(center = (self.x, self.y))
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]
        self.mask = pygame.mask.from_surface( self.image )

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def collision_action(self, by_sprite_at ):
        print("wall_class.collision_action( by_sprite_at=%s )" % ( str( by_sprite_at ) ) )
#        self.vy = ball.vy
#        self.vx = ball.vx
#        self.x += self.vx
#        self.y += self.vy
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]

def gameQuit():
    pygame.quit()
    sys.exit()

screen = pygame.display.set_mode((500, 500), 0, 32)
ball = ball_class(screen)
wall = wall_class(screen)
clock = pygame.time.Clock()
while True:
    screen.fill((128,128,128))
    ball.move()
    ball.draw(screen)
    wall.draw(screen)
    is_a_collision = pygame.sprite.collide_mask(wall, ball)
    if is_a_collision:
        wall.collision_action( ball.rect.center )

    for event in pygame.event.get():
        if event.type == QUIT:
            gameQuit()
        elif event.type == KEYDOWN:
            ball.event(event)
    clock.tick(100)
    pygame.display.update()

你的代码有很多问题。我建议您先阅读Python中类的一般用法,然后再阅读pygame中的sprite类,然后了解掩码的工作原理。真正深入阅读。在stackoverflow上有太多的问题需要解决。是的,可能有很多问题,但目前我只想解决一个。我将从解决方案向后工作,以完全理解所有内容。我假设“ball.png”已经具有透明度?您的面具有一些非常混乱的地方。尝试调用
wall.sprite.mask.outline()
,您会发现它返回一个空列表。与来自
ball.sprite
的掩码相同。您在这里做了一些非常奇怪的事情(例如扩展
Sprite
,但是没有填充正常的
Sprite
属性,而是在扩展的
Sprite
对象上创建一个
Sprite
属性,然后向该对象添加属性…)。
import pygame, sys, math
from pygame.locals import *
pygame.init()

class ball_class(pygame.sprite.Sprite):
    def __init__(self, surface):
        pygame.sprite.Sprite.__init__(self)
        self.surface = surface
        self.x = 250
        self.y = 250
        self.vy = 0
        self.vx = 0
        self.image = pygame.image.load("ball_64.png").convert_alpha()
        self.rect  = self.image.get_rect(center = (self.x, self.y))
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]
        self.mask = pygame.mask.from_surface(self.image)

    def event(self, event):
        if event.key == K_UP:
            self.vy = -1
            self.vx = 0
        elif event.key == K_DOWN:
            self.vy = 1
            self.vx = 0
        elif event.key == K_LEFT:
            self.vx = -1
            self.vy = 0
        elif event.key == K_RIGHT:
            self.vx = 1
            self.vy = 0

    def move(self):
        self.y += self.vy
        self.x += self.vx
        self.rect.topleft = [int(self.x), int(self.y)]
        #self.mask = pygame.mask.from_surface(self.sprite.image)

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def position(self):
        return self.rect()

class wall_class(pygame.sprite.Sprite):
    def __init__(self, surface):
        pygame.sprite.Sprite.__init__(self)
        self.x = 250
        self.y = 100
        self.vy = 0
        self.image = pygame.image.load("wall.png").convert_alpha()
        self.rect  = self.image.get_rect(center = (self.x, self.y))
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]
        self.mask = pygame.mask.from_surface( self.image )

    def draw(self, surface):
        surface.blit(self.image, self.rect)

    def collision_action(self, by_sprite_at ):
        print("wall_class.collision_action( by_sprite_at=%s )" % ( str( by_sprite_at ) ) )
#        self.vy = ball.vy
#        self.vx = ball.vx
#        self.x += self.vx
#        self.y += self.vy
#        self.sprite.rect.topleft = [int(self.x), int(self.y)]

def gameQuit():
    pygame.quit()
    sys.exit()

screen = pygame.display.set_mode((500, 500), 0, 32)
ball = ball_class(screen)
wall = wall_class(screen)
clock = pygame.time.Clock()
while True:
    screen.fill((128,128,128))
    ball.move()
    ball.draw(screen)
    wall.draw(screen)
    is_a_collision = pygame.sprite.collide_mask(wall, ball)
    if is_a_collision:
        wall.collision_action( ball.rect.center )

    for event in pygame.event.get():
        if event.type == QUIT:
            gameQuit()
        elif event.type == KEYDOWN:
            ball.event(event)
    clock.tick(100)
    pygame.display.update()