Python pygame -删除屏幕外的精灵

zpgglvta  于 2023-02-21  发布在  Python
关注(0)|答案(2)|浏览(293)

我用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)

然后在draw方法中我写self.all_sprites.draw()这个游戏是一个无限运行的,每一帧敌人都向下移动几个像素,问题是过了一段时间游戏变得很慢,因为当方块离开屏幕时,精灵不会被删除,有没有办法自动删除屏幕外的示例?
我尝试了以下方法,但它只是删除屏幕上的所有敌人。

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

我想我可以做一些类似game.all_sprites.pop(1)的事情(位置0是播放器),但我找不到一种方法来存档类似的东西...

dsf9zpds

dsf9zpds1#

如果敌人的rect不在屏幕内,他们可以通过调用self.kill()将自己从游戏中移除,例如:

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

nmpmafwu2#

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

相关问题