Почему pygame не отображает все мои спрайты?

#python #python-3.x #pygame

#python #python-3.x #pygame

Вопрос:

Я пытаюсь следовать этому руководству, чтобы изучить pygame. Я дошел до того, что пытаюсь создать вражеские объекты, но я думаю, что допустил ошибку, потому что ничего не отображается.

 class Player(pygame.sprite.Sprite):
        def __init__(self):
            super(Player, self).__init__()
            self.surf = pygame.Surface((75,25))
            self.surf.fill((0, 0,0))
            self.rect = self.surf.get_rect()

           #Moves sprite based on keypresses(removed for clarity)
class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super(Enemy, self).__init__()
        self.surf = pygame.Surface((20,10))
        self.surf.fill((0,0,0))
        self.rect = self.surf.get_rect(
            center = (
            random.randint(SCREEN_WIDTH   20, SCREEN_WIDTH   100),
            random.randint(0, SCREEN_HEIGHT),
            )
        )
        self.speed = random.randint(5, 20)
        # moves sprite based on speed, remove when passes left edge
        def update(self):
            self.rect.move_ip(-self.speed, 0)
            if self.rect.right < 0:
                self.kill()
                #How sad for them


pygame.init()
#create screen
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

#custom events for adding a new Enemy
ADDENEMY = pygame.USEREVENT   1
pygame.time.set_timer(ADDENEMY, 250)
# Instantiate player
player = Player()
enemies = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
all_sprites.add(player)
#keep the game running!
running = True


#loop time!
while running:
    #look at all the events
    for event in pygame.event.get():
        #did the user hit a key?
        if event.type == KEYDOWN:
            #Was it escape?  uh oh we gotta stop
            if event.key == K_ESCAPE:
                running = False

        elif event.type ==QUIT:
            running = False

        elif event.type == ADDENEMY:
            #Create the new enemy
            new_enemy = Enemy()
            enemies.add(new_enemy)
            all_sprites.add(new_enemy)
    #gets the keys that were just pressed
    pressed_keys = pygame.key.get_pressed()
    #updates location based on keys
    player.update(pressed_keys)
    #updates enemy position
    enemies.update()
    #fill screen with white
    screen.fill((255, 255, 255))
    #Draw the sprites
    for entity in all_sprites:
        screen.blit(entity.surf, entity.rect)
    # Create a surface and pass in a tuple containing legth and width
    surf = pygame.Surface((50, 50))

    
    pygame.display.flip()
 

Насколько я могу судить, мне нужно создать класс enemy, а затем добавить событие, которое добавляет врага (ADDENEMY). При вызове этого события (каждые 250 мс благодаря таймеру) должен появиться враг, который перемещается влево, пока не достигнет конца отображения.
У меня есть группа спрайтов, которые являются врагами, и группа all_sprites, и я использую screen.blit и цикл for для отображения каждого объекта в all_sprites на экране. Чего мне не хватает? когда я запускаю это (вместе с битами, которые я отредактировал) Я вижу спрайт игрока нормально, и он движется, но я не вижу никаких врагов.

Ответ №1:

Ваших спрайтов нет в окне. Все спрайты находятся за пределами окна, потому что диапазон был указан неправильно:

random.randint(SCREEN_WIDTH 20, SCREEN_WIDTH 100)

 random.randint(20, SCREEN_WIDTH   100),
 

Кроме того, существует проблема с отступом. Метод update должен быть областью действия класса Enemy :

 class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        # [...]

    # INDENTATION

    #<--|
    def update(self):
        # [...]
 

Кроме того, см. pygame.sprite.Group.draw() :

Преобразует содержащиеся в нем спрайты в аргумент Surface . При этом используется Sprite.image атрибут для исходной поверхности и Sprite.rect . […]

Переименуйте атрибут surf на image и вызовите all_sprites.draw(screen) :

 class Player(pygame.sprite.Sprite):
        def __init__(self):
            super(Player, self).__init__()
            self.image = pygame.Surface((75,25))
            self.image.fill((0, 0,0))
            self.rect = self.image.get_rect()
 
 class Enemy(pygame.sprite.Sprite):
    def __init__(self):
        super(Enemy, self).__init__()
        self.image = pygame.Surface((20,10))
        self.image.fill((0,0,0))
        self.rect = self.image.get_rect(
            center = (
            random.randint(20, SCREEN_WIDTH   100),
            random.randint(0, SCREEN_HEIGHT),
            )
        )
        self.speed = random.randint(5, 20) 
 
 while running:
    # [...]

    #for entity in all_sprites:
    #    screen.blit(entity.surf, entity.rect) <---- DELETE


    all_sprites.draw(screen)                   <---- ADD
 

Комментарии:

1. Огромное спасибо, оказывается, это было не совсем так, я хотел, чтобы они начинались немного за кадром, но когда я отобразил их на экране с помощью (20, SCREEN_WIDTH 100) Я заметил, что они не двигались. Настоящая проблема заключалась в том, что я определил свою функцию обновления (self) в функции __init__(self)