Pygame:使用spritecollide()访问碰撞精灵的属性

2024-04-20 16:17:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在建造一个雷登2型的自上而下的射手。我需要知道当我使用“spritecollide”检测到碰撞时如何访问敌方对象。在

我需要敌方目标的原因是这样我就可以降低他们每一颗子弹击中他们的能量水平。在

这是我必须使用的字典:

enemyCollisions = pygame.sprite.groupcollide(shipBulletGroup, enemyGroup, True, False)

这是我的子弹课程:

^{pr2}$

以下是我未完成的敌人课程:

class Enemy_1(Entity):
    def __init__(self):
        Entity.__init__(self)
        self.speed = (1, 1)
        self.energy = 10
        self.begin = False
        self.run = False
        self.image = pygame.Surface((WIN_W/5, WIN_H/15)).convert()
        self.image.fill((70, 70, 70))
        self.rect = self.image.get_rect()
        self.rect.centerx = WIN_W/1.333
        self.rect.y = -WIN_H/15

    def shoot(self):
        bullet_1 = Bullet(self, 270)
        bullet_2 = Bullet(self, 225)
        bullet_3 = Bullet(self, 315)

    def update(self, enemyGroup, timer):
        if timer == 300:
            self.begin = True
        elif timer == 900:
            self.run = True
        elif timer > 900 and self.rect.x > WIN_W:
            self.remove(enemyGroup)

        if self.run:
            self.rect.x += self.speed[0]
            self.rect.y += self.speed[1]
        elif self.begin:
            self.rect.y += self.speed[1]
            if self.rect.y > WIN_H/4:
                self.rect.y = WIN_H/4

        if self.energy == 0:
            self.kill()

以下是完整的程序:

import sys, pygame, os, random, math

from ast import literal_eval

# Force static position of screen
os.environ['SDL_VIDEO_CENTERED'] = '1'

# Constants
LEFT = 'left'
RIGHT = 'right'

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

PILL_WIDTH = 5
PILL_HEIGHT = 20

WIN_W = 500
WIN_H = 800

SHIP_WIDTH = WIN_W/15
SHIP_HEIGHT = WIN_H/15

BULLET_DIMENSIONS = 5
TIMER = 0


class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)


class Text(Entity):
    def __init__(self, text, size, color, position, font=None):
        Entity.__init__(self)
        self.color = color
        self.font = pygame.font.Font(font, size)
        self.text = text
        self.set(text, position)

    def set(self, text, position):
        self.image = self.font.render(str(text), 1, self.color)
        self.rect = self.image.get_rect()
        self.rect.move_ip(position[0]-self.rect.width/2, (position[1]-self.rect.height)/2)


class Ship(Entity):
    def __init__(self, container):
        Entity.__init__(self)
        self.speed = 5
        self.score = 0
        self.image = pygame.Surface((SHIP_WIDTH, SHIP_HEIGHT)).convert()
        self.rect = self.image.get_rect()
        self.rect.centerx = container.centerx
        self.rect.y = container.centery

    def update(self, bulletGroup):
        key = pygame.key.get_pressed()
        if key[pygame.K_w]:
            self.rect.centery -= self.speed
        if key[pygame.K_s]:
            self.rect.centery += self.speed
        if key[pygame.K_d]:
            self.rect.centerx += self.speed
        if key[pygame.K_a]:
            self.rect.centerx -= self.speed
        if key[pygame.K_SPACE]:
            if TIMER % 7 == 0:
                bullet = Bullet(self, 90, 'friend')
                bulletGroup.add(bullet)

        # Ship Movement Boundaries
        if self.rect.y < WIN_H/25:
            self.rect.y = WIN_H/25
        if self.rect.y > WIN_H - SHIP_HEIGHT:
            self.rect.y = WIN_H - SHIP_HEIGHT
        if self.rect.x < 0:
            self.rect.x = 0
        if self.rect.x > WIN_W - SHIP_WIDTH:
            self.rect.x = WIN_W - SHIP_WIDTH

class Bullet(Entity):
    def __init__(self, ship, angle, type):
        Entity.__init__(self)
        self.speed = 8
        self.level = 0
        self.image = pygame.Surface((BULLET_DIMENSIONS, BULLET_DIMENSIONS)).convert()
        self.rect = self.image.get_rect()
        self.dx = math.cos(math.radians(angle)) * self.speed
        self.dy = math.sin(math.radians(angle)) * self.speed
        self.setXY(ship, type)

    def setXY(self, ship, type):
        self.rect.x = ship.rect.centerx
        if type == 'friend':
            self.rect.y = ship.rect.top
        elif type == 'enemy':
            self.rect.y = ship.rect.bottom

    def update(self):
        if self.rect.bottom < 0:
            self.kill()
        else:
            self.rect.x -= self.dx
            self.rect.y -= self.dy
            if type == 'friend':
                self.rect.y = -self.rect.y
                self.rect.x = -self.rect.x


class Powerup(Entity):
    def __init__(self, xden, pillCount):
        Entity.__init__(self)
        self.speed = 3
        self.density = xden
        self.image = pygame.Surface((PILL_WIDTH, PILL_HEIGHT)).convert()
        self.rect = self.image.get_rect()
        self.rect = self.rect.move(100,100)

    def restart(self):
        pass

    def update(self):
        if self.rect.y > WIN_H:
            del self
        else:
            self.rect = self.rect.move((0, self.speed))


class Enemy(Entity):
    def __init__(self):
        Entity.__init__(self)
        self.begin = False
        self.run = False
        self.color = (153, 0, 76)

class Planes(Enemy):
    def __init__(self, speed, energy, size, location):
        Enemy.__init__(self)
        self.speed = speed
        self.energy = energy
        self.image = pygame.Surface(size).convert()
        self.image.fill(self.color)
        self.rect = self.image.get_rect()
        self.rect.centerx = location[0]
        self.rect.y = location[1]

    def shoot(self, enemyBulletGroup):
        bullet_1 = Bullet(self, 240, 'enemy')
        bullet_2 = Bullet(self, 270, 'enemy')
        bullet_3 = Bullet(self, 300, 'enemy')
        enemyBulletGroup.add(bullet_1, bullet_2, bullet_3)

    def update(self, enemyGroup, enemyBulletGroup):
        if TIMER == 300:
            self.begin = True
        elif TIMER == 900:
            self.run = True
        elif self.rect.x > WIN_W or self.energy == 0:
            self.kill()

        if self.run:
            self.rect.x += self.speed[0]
            self.rect.y += self.speed[1]
            if TIMER % 100 == 0:
                self.shoot(enemyBulletGroup)
        elif self.begin:
            self.rect.y += self.speed[1]
            if self.rect.y > WIN_H/4:
                self.rect.y = WIN_H/4
                if TIMER % 100 == 0:
                    self.shoot(enemyBulletGroup)

def main():

    # Initialize Everything
    pygame.init()
    global TIMER
    fps = 60
    lLeft = lRight = lUp = lDown = shoot = False
    clock = pygame.time.Clock()
    play = True
    pygame.display.set_caption('Pong')
    screen = pygame.display.set_mode((WIN_W, WIN_H), pygame.SRCALPHA)

    # Create Game Objects
    ship = Ship(pygame.rect.Rect(0, 0, WIN_W, WIN_H))
    score1 = Text("Score: " + str(ship.score), 40, BLACK, (WIN_W/2, (WIN_H/25)))
    enemy_1 = Planes((1, 1), 10, (WIN_W/5, WIN_H/15), (WIN_W/1.4, -WIN_H/15))

    # Create Groups
    powerupGroup = pygame.sprite.Group()
    shipGroup = pygame.sprite.Group()
    shipGroup.add(ship)
    textGroup = pygame.sprite.Group()
    textGroup.add(score1)
    shipBulletGroup = pygame.sprite.Group()
    enemyBulletGroup = pygame.sprite.Group()
    enemyGroup = pygame.sprite.Group()
    enemyGroup.add(enemy_1)


    # Gameplay
    while play:
        # Checks if window exit button pressed
        for event in pygame.event.get():
            if event.type == pygame.QUIT: sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()

        # Update
        powerupGroup.update()
        ship.update(shipBulletGroup)
        shipBulletGroup.update()
        textGroup.update()
        enemyGroup.update(enemyGroup, enemyBulletGroup)
        enemyBulletGroup.update()


        enemyCollisions = pygame.sprite.groupcollide(shipBulletGroup, enemyGroup, True, False)
        for key in enemyCollisions:
            print enemyCollisions[key].energy


        # Print Background/Sprites
        screen.fill(WHITE)
        powerupGroup.draw(screen)
        shipGroup.draw(screen)
        shipBulletGroup.draw(screen)
        textGroup.draw(screen)
        enemyGroup.draw(screen)
        enemyBulletGroup.draw(screen)

        # Print Score Bar
        hori_partition = pygame.Surface((WIN_W, 1))
        screen.blit(hori_partition, (0, WIN_H/25))

        TIMER += 1
        # Limits frames per iteration of while loop
        clock.tick(fps)
        # Writes to main surface
        pygame.display.flip()

if __name__ == "__main__":
    main()

Tags: rectimageselfifinitdefupdatescreen
2条回答

^{}函数返回值为列表对象的字典

Every Sprite inside group1 is added to the return dictionary. The value for each item is the list of Sprites in group2 that intersect.

这就是迭代返回dict时调用print enemyCollisions[key].energy失败的原因,因为列表对象enemyCollisions[key]的值没有energy()方法。在

要在Python2.X中访问字典的所有值,可以使用dict实例的.itervalues()方法。要获取每个碰撞的精灵,请再次迭代这些值:

enemyCollisions = pygame.sprite.groupcollide(shipBulletGroup, enemyGroup, True, False)

#iterate over all values of the enemyCollisions dict
for enemyCollisions in enemyCollisions.itervalues():

    #access all enemies which collided with an shipBullet
    for enemy in enemyCollisions:
        print enemy.energy

访问碰撞精灵属性的语法如下:

collisions = pygame.sprite.spritecollide(self, pillGroup, True)
    for key in collisions:
        self.density += key.density

相关问题 更多 >