虽然当我使用pygame.sprite.collide_rect
或pygame.sprite.collide_circle
时检测到碰撞,但是当我尝试将一个位掩码分配给精灵并按原样运行时,未检测到碰撞。 (wall.collision_action()
使第一个圆圈以与另一个圆圈相同的速度和方向移动)虽然现在不是一个问题,但是
因为我正在使用圆形图像使pygame.sprite.collide_circle工作正常,将来当我使用更详细和非圆形的精灵时,它将是。
代码:
import pygame, sys, math
from pygame.locals import *
pygame.init()
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()
self.sprite.image = pygame.image.load("ball.png").convert()
self.sprite.rect = self.sprite.image.get_rect(center = (self.x, self.y))
self.sprite.rect.topleft = [int(self.x), int(self.y)]
self.sprite.mask = pygame.mask.from_surface(self.sprite.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.sprite.rect.topleft = [int(self.x), int(self.y)]
self.sprite.mask = pygame.mask.from_surface(self.sprite.image)
def draw(self, surface):
surface.blit(self.sprite.image, self.sprite.rect)
def position(self):
return self.sprite.rect()
class wall_class(pygame.sprite.Sprite):
def __init__(self, surface):
self.surface = surface
self.x = 250
self.y = 100
self.vy = 0
self.sprite = pygame.sprite.Sprite()
self.sprite.image = pygame.image.load("ball.png").convert()
self.sprite.rect = self.sprite.image.get_rect(center = (self.x, self.y))
self.sprite.rect.topleft = [int(self.x), int(self.y)]
self.sprite.mask = pygame.mask.from_surface(self.sprite.image)
def draw(self, surface):
surface.blit(self.sprite.image, self.sprite.rect)
def collision_action(self):
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((0, 0, 0))
ball.move()
ball.draw(screen)
wall.draw(screen)
is_a_collision = pygame.sprite.collide_mask(wall.sprite, ball.sprite)
if is_a_collision:
wall.collision_action()
for event in pygame.event.get():
if event.type == QUIT:
gameQuit()
elif event.type == KEYDOWN:
ball.event(event)
clock.tick(100)
pygame.display.update()
答案 0 :(得分:0)
位掩码冲突 在您的代码中起作用,但是我认为代码变得更加困难,因为子对象ball_class
和wall_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
...
通常,当代码“子类化”现有类/对象时,它成为其中一个。因此,不必在类中包含辅助Sprite。这也使代码和逻辑更加复杂,棘手和混乱。
请考虑重新制作您的ball_class
:
class ball_class(pygame.sprite.Sprite):
def __init__(self, surface):
pygame.sprite.Sprite.__init__(self) # <-- HERE Must initialise sprites
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.mask = pygame.mask.from_surface(self.image)
请注意image
,rect
和mask
成员变量。以前,代码使用的是包含的sprite。但是编写PyGame库是为了期望它们成为类的成员,如果未定义它们,它将无法正常工作。另外,您的两个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()