问题
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