pygame 两组之间的碰撞

pygame collissions between two groups

我检查宇宙飞船和小行星之间碰撞的软件仍然有问题。我不知道为什么我只在屏幕的左上角发生碰撞。

有什么想法吗?有什么帮助吗?

import pygame, sys
import random
import math
from pygame.locals import KEYDOWN, K_SPACE

pygame.init()
pygame.display.set_caption("ASTROCRASH version 0.1 >>> DKR103 <<<")
clock = pygame.time.Clock()

SCREENH = 600
SCREENW = 800
SCREEN = pygame.display.set_mode((SCREENW, SCREENH))

sGRAD = math.pi/180

BLACK = (0,0,0)
WHITE = (255,255,255)
BBB = (0, 75, 230)

ASTEROIDS = []
MISSILES = []
SPACESHIPS = []

class AsteroidSprite(pygame.sprite.Sprite):
    def __init__(self,posX,posY):
        pygame.sprite.Sprite.__init__(self)    
        self.image = pygame.image.load("img/asteroid3.png").convert()
        self.rect = self.image.get_rect()
        self.x = posX
        self.y = posY
        self.speed = 2
        self.dx = random.choice([1,-1]) * self.speed * random.random()
        self.dy = random.choice([1,-1]) * self.speed * random.random()

    def update(self):
        if self.y > SCREENH:
            self.y = (0 - self.rect[3])
        if self.y < (0 - self.rect[3]):
            self.y = SCREENH
        if self.x > SCREENW:
            self.x = (0 - self.rect[2])
        if self.x < (0 - self.rect[2]):
            self.x = SCREENW

        self.x += self.dx
        self.y += self.dy

class Ship(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        #load original image
        self.imageMaster = pygame.image.load("img/spaceship.png")
        self.imageMaster = self.imageMaster.convert()
        ###self.imageMaster.set_colorkey(WHITE)
        #set Sprite attribute
        self.image = self.imageMaster
        #get Sprite rect
        self.rect = self.image.get_rect()
        self.rect.center = ((SCREEN.get_width()/2),(SCREEN.get_height()/2))
        #initial rotation value
        self.dir = 0
        #ship movement speed
        self.speed = 5

    def rotation(self):
        #set Sprite center before rotation
        self.oldCenter = self.rect.center
        #rotate Sprite
        self.image = pygame.transform.rotate(self.imageMaster,self.dir)
        self.rect= self.image.get_rect()
        #set new Sprite center equal to old Center so it stays in place
        self.rect.center = self.oldCenter
        self.value = self.dir * math.pi / 180
    def update(self):
        #move
        key = pygame.key.get_pressed()
        if key[pygame.K_UP]:

            self.rect[0] -= self.speed * math.sin(self.value)
            self.rect[1] -= self.speed * math.cos(self.value)

        #rotate
        if key[pygame.K_LEFT]:
            self.dir += 5
            if self.dir > 360:
                self.dir = 15
        if key[pygame.K_RIGHT]:
            self.dir -= 5
            if self.dir < 0:
                self.dir = 355
        #outside SCREEN conditions
        if self.rect[1] > SCREENH:
            self.rect[1] = (0 - self.rect[3])
        if self.rect[1] < (0 - self.rect[3]):
            self.rect[1] = SCREENH
        if self.rect[0] > SCREENW:
            self.rect[0] = (0 - self.rect[2])
        if self.rect[0] < (0 - self.rect[2]):
            self.rect[0] = SCREENW

    def draw(self):
        SCREEN.blit(self.image,(self.rect[0],self.rect[1]))

def main():
    #spaceship
    spaceship = Ship()
    SPACESHIPS.append(spaceship)
    for i in range(8):
        ASTEROIDS.append(AsteroidSprite(300,300))

    runGame = True   
    while runGame:

        clock.tick(60)
        SCREEN.fill(BLACK)      

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                runGame = False

        #update asteroids
        for i in range(8):
            ASTEROIDS[i].update()
            SCREEN.blit(ASTEROIDS[i].image,(ASTEROIDS[i].x,ASTEROIDS[i].y))
        for a in ASTEROIDS:
            if pygame.sprite.spritecollide(a,SPACESHIPS,0):
                SCREEN.fill(BBB)  

        spaceship.rotation()       
        spaceship.update()
        spaceship.draw()
        print spaceship.rect[0]

        pygame.display.update()                          
main()
pygame.quit()

pygame.sprite.groupcollide() 函数查找两个传递的精灵组的所有精灵之间的碰撞和 returns 包含碰撞信息的字典 ,如文档州。

因为碰撞是通过比较每个精灵的sprite.rect属性来确定的,每次调用精灵实例的update()方法时你需要更新 self.rect 对象 的 位置,而不是更改其 self.xself.y 属性。

你的Shipclass没问题,因为你改变了self.rect对象和它自己的.x.y 属性 。 (例如 self.rect[1] = (0 - self.rect[3]))。
但是在 AsteroidSprite class 中,您在 __init__() 方法中创建了一个矩形对象调用 .update() 方法时,仅 更改实例的 self.xself.y 属性

您需要更改的内容:

  1. AsteroidSpriteclass的.update()方法,因为需要改变self.rect物体位置,用于碰撞检测.
  2. 检查冲突的 if 语句,因为 pygame.sprite.groupcollide() returns 一个字典对象,而不是布尔值

希望对您有所帮助:)

非常感谢。您的回答帮助我解决了问题。

更新代码:

import pygame, sys
import random
import math
from pygame.locals import KEYDOWN, K_SPACE

pygame.init()
pygame.display.set_caption("ASTROCRASH version 0.1 >>> DKR103 <<<")
clock = pygame.time.Clock()

SCREENH = 600
SCREENW = 800
SCREEN = pygame.display.set_mode((SCREENW, SCREENH))

sGRAD = math.pi/180

BLACK = (0,0,0)
WHITE = (255,255,255)
BBB = (0, 75, 230)

ASTEROIDS = []
MISSILES = []
SPACESHIPS = []

class AsteroidSprite(pygame.sprite.Sprite):
    def __init__(self,posX,posY):
        pygame.sprite.Sprite.__init__(self)    
        self.image = pygame.image.load("img/asteroid3.png").convert()
        self.rect = self.image.get_rect()
        self.rect.x = posX
        self.rect.y = posY
        self.speed = 2
        self.dx = random.choice([1,-1]) * self.speed * random.random()
        self.dy = random.choice([1,-1]) * self.speed * random.random()

    def update(self):
        if self.rect.y > SCREENH:
            self.rect.y = (0 - self.rect[3])
        if self.rect.y < (0 - self.rect[3]):
            self.rect.y = SCREENH
        if self.rect.x > SCREENW:
            self.rect.x = (0 - self.rect[2])
        if self.rect.x < (0 - self.rect[2]):
            self.rect.x = SCREENW

        self.rect.x += self.dx
        self.rect.y += self.dy

class Ship(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        #load original image
        self.imageMaster = pygame.image.load("img/spaceship.png")
        self.imageMaster = self.imageMaster.convert()
        ###self.imageMaster.set_colorkey(WHITE)
        #set Sprite attribute
        self.image = self.imageMaster
        #get Sprite rect
        self.rect = self.image.get_rect()
        self.rect.center = ((SCREEN.get_width()/2),(SCREEN.get_height()/2))
        #initial rotation value
        self.dir = 0
        #ship movement speed
        self.speed = 5

    def rotation(self):
        #set Sprite center before rotation
        self.oldCenter = self.rect.center
        #rotate Sprite
        self.image = pygame.transform.rotate(self.imageMaster,self.dir)
        self.rect= self.image.get_rect()
        #set new Sprite center equal to old Center so it stays in place
        self.rect.center = self.oldCenter
        self.value = self.dir * math.pi / 180
    def update(self):
        #move
        key = pygame.key.get_pressed()
        if key[pygame.K_UP]:

            self.rect[0] -= self.speed * math.sin(self.value)
            self.rect[1] -= self.speed * math.cos(self.value)

        #rotate
        if key[pygame.K_LEFT]:
            self.dir += 5
            if self.dir > 360:
                self.dir = 15
        if key[pygame.K_RIGHT]:
            self.dir -= 5
            if self.dir < 0:
                self.dir = 355
        #outside SCREEN conditions
        if self.rect[1] > SCREENH:
            self.rect[1] = (0 - self.rect[3])
        if self.rect[1] < (0 - self.rect[3]):
            self.rect[1] = SCREENH
        if self.rect[0] > SCREENW:
            self.rect[0] = (0 - self.rect[2])
        if self.rect[0] < (0 - self.rect[2]):
            self.rect[0] = SCREENW

    def draw(self):
        SCREEN.blit(self.image,(self.rect[0],self.rect[1]))

def main():
    #spaceship
    spaceship = Ship()
    SPACESHIPS.append(spaceship)
    for i in range(8):
        ASTEROIDS.append(AsteroidSprite(300,300))

    runGame = True   
    while runGame:

        clock.tick(60)
        SCREEN.fill(BLACK)      

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                runGame = False

        #update asteroids
        for i in range(8):
            ASTEROIDS[i].update()
            SCREEN.blit(ASTEROIDS[i].image,(ASTEROIDS[i].rect.x,ASTEROIDS[i].rect.y))
        for a in ASTEROIDS:
            if pygame.sprite.spritecollide(a,SPACESHIPS,0):
                SCREEN.fill(BBB)  

        spaceship.rotation()       
        spaceship.update()
        spaceship.draw()
        print spaceship.rect[0]

        pygame.display.update()                          
main()
pygame.quit()