Why do I get blank grey background instead of animations in PyGame?

谁都会走 提交于 2019-12-24 01:38:34

问题


I am creating the Environment class. The function init should build the simulated environment, while the function run should execute different events in this environment during 10 seconds.

Below I share some major parts of my code. When I run env = Environment("TEST") env.run() (see below), the window with grey screen appears. Then it closes in 10 seconds. Nothing is visible in this screen. It's just a grey background. However, I do not get any error message.

What am I doing wrong in the Environment class?

Just to mention that the same code worked fine when I had the whole code of Environment placed directly in main loop, i.e. when Environment class has not existed.

import numpy as np
import pygame
import random

WHITE = (255, 255, 255)
GREEN = (20, 255, 140)
GREY = (210, 210, 210)

SCREENWIDTH = 1000
SCREENHEIGHT = 578

IMG_WORKER_RUNNING = "images/workers/worker_1.png"
IMG_WORKER_IDLE = "images/workers/worker_2.png"
IMG_WORKER_ACCIDENT = "images/workers/accident.png"


class Worker(pygame.sprite.Sprite):
    RUNNING = 0
    IDLE = 1
    ACCIDENT = 2
    NUMBER_OF_ACCIDENTS = 0
    IMAGE_CACHE = {}

    def __init__(self, idw, image_running, image_idle, image_accident,
                 all_sprites, location, *groups):
        # Each state has it's own image
        self.images = {
            Worker.RUNNING: pygame.transform.scale(
                self.get_image(image_running),
                (45, 45)
            ),
            Worker.IDLE: pygame.transform.scale(
                self.get_image(image_idle),
                (20, 45)
            ),
            Worker.ACCIDENT: pygame.transform.scale(
                self.get_image(image_accident),
                (40, 40)
            )
        }

        self._layer = 2
        pygame.sprite.Sprite.__init__(self, groups)
        self.idw = idw
        self.reset(location)

    def reset(self, location):
        self.state = Worker.IDLE
        self.ticks_in_state = 0

        self.location = location
        self.image = self.images[self.state]
        self.rect = self.image.get_rect(topleft=location)

        self.direction = pygame.math.Vector2(0, 0)
        self.speed = random.randint(1, 3)

    def get_image(self, key):
        if not key in Worker.IMAGE_CACHE:
            Worker.IMAGE_CACHE[key] = pygame.image.load(key)
        return Worker.IMAGE_CACHE[key]


class Environment:
    def __init__(self, title):
        pygame.init()

        self.screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
        pygame.display.set_caption(title)

        self.all_sprites = pygame.sprite.LayeredUpdates()
        self.workers = pygame.sprite.Group()
        self.fences = pygame.sprite.Group()

        # create a worker
        idw = 1
        Worker(idw, IMG_WORKER_RUNNING, IMG_WORKER_IDLE,
               IMG_WORKER_ACCIDENT, self.all_sprites, (50, 50), 
               self.workers)

    def run(self):
        carry_on = True
        clock = pygame.time.Clock()
        simulation_time = 10  # time in seconds

        while carry_on:
            for event in pygame.event.get():
                if (event.type == pygame.QUIT) or (simulation_time == 0):
                    carry_on = False
                    pygame.display.quit()
                    pygame.quit()
                    quit()

                simulation_time -= 1

            agent_action = 0
            send_alert = np.random.normal(0, 0.1, 1)

            if send_alert > 0.2:
                agent_action = 1

            self.all_sprites.update(self.screen, agent_action)
            self.all_sprites.draw(self.screen)

        pygame.display.flip()
        clock.tick(20)


if __name__ == "__main__":
    env = Environment("TEST")
    env.run()

回答1:


You have to pass the all_sprites argument in the Worker.__init__ method to the __init__ method of the Sprite class, so that the sprite will be added to this group.

pygame.sprite.Sprite.__init__(self, all_sprites, groups)

You could also rearrange the parameters of the __init__ method and pass the two groups as the last arguments (they will be added to the groups list).

# In the Worker class.
def __init__(self, idw, image_running, image_idle, image_accident,
             location, *groups):

# Pass the two groups as the `groups` argument.
Worker(idw, IMG_WORKER_RUNNING, IMG_WORKER_IDLE,
       IMG_WORKER_ACCIDENT, (50, 50), self.all_sprites, 
       self.workers)

In the while loop you need to blit a background surface or fill the screen every frame in order to clear it, then draw the sprites and finally update the screen with pygame.display.flip() (you need to indent it in your example).

while carry_on:
    for event in pygame.event.get():
        if (event.type == pygame.QUIT) or (simulation_time == 0):
            carry_on = False
        # You probably don't want to decrement the
        # simulation_time once per event. Dedent
        # this line to decrement it once per frame.
        simulation_time -= 1

    agent_action = 0
    send_alert = np.random.normal(0, 0.1, 1)

    if send_alert > 0.2:
        agent_action = 1

    self.all_sprites.update(self.screen, agent_action)
    # Blit a background surface or fill the screen.
    self.screen.fill((0, 40, 0))  # Fill with dark green.
    # Blit all sprites.
    self.all_sprites.draw(self.screen)
    # Update the screen.
    pygame.display.flip()
    clock.tick(20)


来源:https://stackoverflow.com/questions/51848277/why-do-i-get-blank-grey-background-instead-of-animations-in-pygame

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!