Python pygame - 删除屏幕外精灵

时间:2016-11-23 18:45:18

标签: python pygame sprite

我用python 2和pygame创建了一个简单的2D游戏,你必须避免向下移动的方块。我为'敌人'创建了这个类:

class Enemy(pygame.sprite.Sprite):

  def __init__(self, game):
      self.groups = game.all_sprites
      pygame.sprite.Sprite.__init__(self, self.groups)
      self.game = game
      self.image = pygame.Surface((TILESIZE + 10, TILESIZE + 10))
      self.image.fill(ENEMY_COLOR)
      self.rect = self.image.get_rect()
      self.x = random.uniform(0, WIDTH - TILESIZE)
      self.rect.x = self.x
      self.y = 0

  def update(self):
      if self.rect.colliderect(self.game.player.rect):
          self.game.deaths += 1
          self.game.score = 0
          self.game.run()
      self.rect.y += (self.game.score + 500) / 50

然后,我有一个创建敌人实例的线程:

class Create_Enemy(Thread):

  def __init__(self):
      Thread.__init__(self)

  def run(self):
      while True:
          while not game.game_paused:
              time.sleep((game.score + 1) / game.speed)
              Enemy(game)

然后在绘制方法中我只写self.all_sprites.draw() 游戏是一个无限的跑步者,每一帧敌人向下移动几个像素。问题是,稍后游戏变得迟钝,因为当块离开屏幕时,精灵不会被删除。 有没有办法自动删除屏幕外实例?

我尝试了以下操作,但它只删除了屏幕上的所有敌人。

if self.rect.y >= WIDTH:
    self.rect.kill()

我以为我可以做game.all_sprites.pop(1)之类的事情(位置0是玩家)但我找不到存档类似内容的方法......

2 个答案:

答案 0 :(得分:0)

检查self.rect.y,WIDTH的值,也许是kill方法。它看起来像self.rect.y总是大于或等于WIDTH,这就是为什么它会杀死它们。

答案 1 :(得分:0)

如果self.kill()的{​​{1}}不在屏幕内,敌人可以通过拨打rect将自己从游戏中移除,例如:

def update(self):
    if self.rect.colliderect(self.game.player.rect):
        self.game.restart() // reset score + count deaths

    // we can simply use move_ip here to move the rect
    self.rect.move_ip(0, (self.game.score + 500) / 100)

    // check if we are outside the screen
    if not self.game.screen.get_rect().contains(self.rect):
        self.kill()

此外,您可以使用pygame的事件系统来生成您的敌人,而不是线程。这是一个简单,不完整但可运行的例子(请注意注释):

import random

import pygame

TILESIZE = 32
WIDTH, HEIGHT = 800, 600

// a lot of colors a already defined in pygame
ENEMY_COLOR = pygame.color.THECOLORS['red']
PLAYER_COLOR = pygame.color.THECOLORS['yellow']

// this is the event we'll use for spawning new enemies
SPAWN = pygame.USEREVENT + 1

class Enemy(pygame.sprite.Sprite):

    def __init__(self, game):

        // we can use multiple groups at once. 
        // for now, we actually don't need to
        // but we could do the collision handling with pygame.sprite.groupcollide()
        // to check collisions between the enemies and the playerg group
        pygame.sprite.Sprite.__init__(self, game.enemies, game.all)
        self.game = game
        self.image = pygame.Surface((TILESIZE + 10, TILESIZE + 10))
        self.image.fill(ENEMY_COLOR)

        // we can use named arguments to directly set some values of the rect
        self.rect = self.image.get_rect(x=random.uniform(0, WIDTH - TILESIZE))
        // we dont need self.x and self.y, since we have self.rect already
        // which is used by pygame to get the position of a sprite


    def update(self):
        if self.rect.colliderect(self.game.player.rect):
            self.game.restart() // reset score + count deaths

        // we can simply use move_ip here to move the rect
        self.rect.move_ip(0, (self.game.score + 500) / 100)

        // check if we are outside the screen
        if not self.game.screen.get_rect().contains(self.rect):
            self.kill()

class Player(pygame.sprite.Sprite):

    def __init__(self, game):
        pygame.sprite.Sprite.__init__(self, game.all, game.playerg)
        self.game = game
        self.image = pygame.Surface((TILESIZE, TILESIZE))
        self.image.fill(PLAYER_COLOR)
        self.rect = self.image.get_rect(x=WIDTH/2 - TILESIZE/2, y=HEIGHT-TILESIZE*2)

    def update(self):
        // no nothing for now
        pass


class Game(object):

    def __init__(self):
        // for now, we actually don't need mujtiple groups
        // but we could do the collision handling with pygame.sprite.groupcollide()
        // to check collisions between the enemies and the playerg group
        self.enemies = pygame.sprite.Group()
        self.all = pygame.sprite.Group()
        self.playerg = pygame.sprite.GroupSingle()
        self.running = True
        self.score = 0
        self.deaths = -1
        self.clock = pygame.time.Clock()

    def restart(self):
        // here we set the timer to create the SPAWN event
        // every 1000 - self.score * 2 milliseconds
        pygame.time.set_timer(SPAWN, 1000 - self.score * 2)
        self.score = 0
        self.deaths += 1

    def run(self):
        self.restart()
        self.player = Player(self)
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))

        while self.running:
            for e in pygame.event.get():
                if e.type == pygame.QUIT:
                    self.running = False
                // when the SPAWN event is fired, we create a new enemy
                if e.type == SPAWN:
                    Enemy(self)

            // draw and update everything
            self.screen.fill(pygame.color.THECOLORS['grey'])
            self.all.draw(self.screen)
            self.all.update()
            pygame.display.flip()

            self.clock.tick(40)

if __name__ == '__main__':
    Game().run()