两组之间的pygame冲突

时间:2015-04-10 20:08:01

标签: pygame sprite

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

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

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()

2 个答案:

答案 0 :(得分:1)

pygame.sprite.groupcollide()函数查找两个传递的sprite-groups的所有sprite之间的冲突,返回包含冲突信息的字典,如文档所述。

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

您的 Ship没问题,因为您更改了self.rect对象及其自己的.x.y属性。 (例如self.rect[1] = (0 - self.rect[3]))。
但是在 AsteroidSprite中,您在__init__()方法中创建了一个rect对象,只有更改{调用self.x方法时,实例的{1}}和self.y属性

您需要改变的地方:

  1. .update()类的.update()方法,因为您需要更改用于碰撞检测的AsteroidSprite对象位置
  2. 检查碰撞的self.rect语句,因为 if会返回一个dict对象,而不是布尔值
  3. 我希望这会对你有所帮助:)。

答案 1 :(得分:0)

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

更新代码:

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()