Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
In my game I have a chronometer running. The chronometer is defined in the 'Play' class(which is used for everything related to when the player is controlling the character), not in the 'Victory' class(which purpose is to show an image when you pass the level). Both classes are defined in the main.py file. I want to print on the final victory screen(the player wins when the character gets to a determinate position) the time that has taken the player to get to that position. How would I do that? Thanks. Unfortunately, I cannot show code.
I made a little piece of code that could help you building this timer.
import pygame
pygame.init() # init is important there because it starts the timer
screen = pygame.display.set_mode((500, 500))
running = True
victory = False
class Play:
def __init__(self):
# all infos about player
self.time = pygame.time.get_ticks()
self.end_time = 0
def update_timer(self):
# here we get the actual time after 'init' has been executed
self.time = pygame.time.get_ticks()
# we divide it by 1000 because we want seconds instead of ms
self.end_time += self.time / 1000
return self.end_time
class Victory:
def __init__(self):
self.play = Play()
def pin_up_timer(self):
# Here I chose to print it inside of the console but feel free to pin it up wherever you want.
print(self.play.update_timer())
vic = Victory()
pl = Play()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# here I chose to end the game when I press KeyUp but you can do something else to stop it
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
victory = True
# I update timer every frame and BEFORE checking if victory is True in order to get a result more accurate
pl.update_timer()
# if victory is True, I pin up the timer and I end the code
if victory:
vic.pin_up_timer()
running = False
pygame.display.flip()
pygame.quit()
If you want the timer begin only if the player has moved, detects the key and add a variable like:
# (this variable outside of the main loop)
moved = False
# left or anything else
if event.key == pygame.K_LEFT:
moved = True
if moved:
pl.update_timer()
Related
I can't seem to figure out why my groups Pygame code keeps flickering when we run it. pygame.display.update is only called once, but our background seems to be potentially causing the issue.
Any an all help would be greatly appreciated! :)
Here's a link to my Replit with the code:
https://replit.com/#LukaLUSV6912/Santa-vs-Evil-Elves-Game?v=1
We are trying to get rid of the flickering from the Pygame animation and implement a winning and loosing screen based off the visibility of the elves(enemies) when the timer runs down to 0
Instructions: move with right + left arrow keys and fire snowballs with spacebar
'''"""
import pygame, random
pygame.init() # initialize pygame managers
# create a window
w = 600
h = 600
win = pygame.display.set_mode((w,h)) # define window variable
# pygame.display.set_caption("Read carefully.") # uncomment & edit to caption the window
#======================== Variables & functions ===================================================
img_size = (50,100)
img_size2 = (30,30)
# class that creates Santa
class Santa:
def __init__(self,color,x,y):
self.color = color
self.x = x
self.y = y
self.img = pygame.image.load("santaimg.png").convert_alpha()
self.img = pygame.transform.scale(self.img, img_size)
self.center=(x,y)
# The methods Right and Left allow Santa to move right and left and have boundries
def Right(self):
if self.x <551:
self.x +=20
self.center=(self.x,self.y)
# self.rect=self.img.get_rect(center=self.center)
def Left(self):
if self.x >0:
self.x -=20
self.center=(self.x,self.y)
# self.rect=self.img.get_rect(center=self.center)
# method that allows the bubbles to be drawn on the screen
def show(self):
# self.img = pygame.image.load("santaimg.png").convert()
# self.rect=self.img.get_rect(center=self.center)
win.blit(self.img, self.center)
#pygame.draw.ellipse(win,self.color,self.img)
#Class that creates the elves
class Elves():
def __init__(self, color, pos_x, pos_y):
self.color = color
self.pos_x= pos_x
self.pos_y = pos_y
self.square = 20
self.velocity = 0 # elves start stationary
self.box = pygame.Rect(self.pos_x,self.pos_y,self.square,self.square)
self.img2 = pygame.image.load("elfimg.png").convert_alpha()
self.img2 = pygame.transform.scale(self.img2,img_size2)
#self.area = pygame.Surface((self.square,self.square))
self.draw = True
# method that displays the elves
def Show(self):
if (self.draw == True):
win.blit(self.img2, (self.pos_x, self.pos_y))
# method that makes elves dissapear if snowball hits them
def dissapear(self, box):
global Dis
if (self.draw):
if self.box.colliderect(box): # box is the rect for elf
Dis += 1 # Each time user hits elf with snowball, value of Dis goes up one
self.draw = False
if (Dis == 20): # New victory image shows once 20 collisions occur
print("Victory! You Saved Christmas!")
global BG
BG = False # Makes it so background image stops refreshing
global SUp
SUp = False #Snowballs stop moving
gameDisplay = pygame.display.set_mode((w,h)) # Background Code - https://stackoverflow.com/questions/65009141/in-pygame-how-do-i-make-an-image-the-background#:~:text=Load%20a%20back%20ground%20image%20%28e.g.%20%27background.jpg%27%29%2C%20scale,pygame.transform.smoothscale%20%28background%2C%20gameDisplay.get_size%20%28%29%29%20gameDisplay.blit%20%28background%2C%20%280%2C%200%29%29
background = pygame.image.load('Victory.png').convert() #Retrieve the image
background = pygame.transform.smoothscale(background, gameDisplay.get_size()) # Sets the image size to the window size
gameDisplay.blit(background, (0, 0)) # Draws the image onto the screen
global running
running = False
# allows the elves to move up and down continuously
def Moving (self):
self.pos_y += self.velocity # Elves move based on velocity value
if self.pos_y >= 0 and self.pos_y < h/2.4: # Elves accelerate downwards when in top half of screen
self.velocity +=.3 # Velocity goes up, pos_y goes down
if self.pos_y > h/2.4: # Elves accelerate upwards when in bottom half of screen
self.velocity -= .3 # Velocity goes down, pos_y goes up
self.box = pygame.Rect(self.pos_x,self.pos_y,self.square,self.square)
#Class that creates snowballs
class Snow:
def __init__(self,color,x,y):
self.x = x
self.y = y
self.color = color
self.height = 15
self.length = 15
self.draw = True
self.snowy = pygame.draw.ellipse(win,self.color,(self.x,self.y,self.height,self.length))
# Show snowballs on screen
def show(self):
if (self.draw == True):
self.snowy = pygame.draw.ellipse(win,self.color,self.snowy)
#Snowballs go up
def upward(self):
global SUp
if SUp == True:
self.snowy.y -= 5
self.snowy = pygame.draw.ellipse(win,self.color,self.snowy)
# class that creates a timer
class Timer:
def __init__(self,limit):
self.limit = limit
self.clock = pygame.time.Clock()
self.start=pygame.time.get_ticks() # get starter tick at Timer instantiation
self.timeLeft = self.countDown()
def countDown(self):
'''Note: Will count down based on time passed, not frame rate, or call frequency.
Retuurns whole value time in seconds (int)'''
currTime=(self.start + pygame.time.get_ticks())/1500 #calculate how many seconds
# if self.timeLeft > 0:
return int(self.limit - currTime) # returns whole second numbers
#================================ Animation loop ===================================================
class Manager:
def __init__(self):
self.colors = ((255,255,255),(0,0,0),(173,216,230),(252,36,2),(0,0,255))
self.ElvesList = []
self.snowballs=[]
global SUp
SUp = True
global BG
BG = True
global Dis
Dis = 0
def main(self):
global running
running = True
clock = pygame.time.Clock()
# code that allows elves to show, everytime you play the game the elves have a different x and y
for i in range(20):
x = random.randint(0,w-20)
y= random.randint(0,h/3)
self.ElvesList.append(Elves(self.colors[2],x,y)) # instantiates the elves class
# calls Santa class in a variable called "SantaC"
SantaC= Santa(self.colors[3],w/2,h-50)
while running:
# clear window (comment out to have trace behind animation)
if (BG == True): # Refresh of image can be turned on/off
gameDisplay = pygame.display.set_mode((w,h)) # Background Code - https://stackoverflow.com/questions/65009141/in-pygame-how-do-i-make-an-image-the-background#:~:text=Load%20a%20back%20ground%20image%20%28e.g.%20%27background.jpg%27%29%2C%20scale,pygame.transform.smoothscale%20%28background%2C%20gameDisplay.get_size%20%28%29%29%20gameDisplay.blit%20%28background%2C%20%280%2C%200%29%29
background = pygame.image.load('SnowBackground.webp').convert() #Retrieve the image
background = pygame.transform.smoothscale(background, gameDisplay.get_size()) # Sets the image size to the window size
gameDisplay.blit(background, (0, 0)) # Draws the image onto the screen
# for every elf created in line 128 they will all show and move, methods of the elves are being called
for evil in self.ElvesList:
evil.Show()
evil.Moving()
# method that allows Santa to be shown
SantaC.show()
#borrowed code in order to display score in left corner (line 141-152)
font = pygame.font.Font("freesansbold.ttf",32)
textx = 10
texty = 10
timer = Timer(27) # 27 is used because there is a 2 second delay to run the code
timeLeft =timer.countDown()
# function that displays timer
def showtimer(x,y):
timing = font.render("Timer :" +str(timeLeft),True,(self.colors[4]))
win.blit(timing,(x,y))
showtimer(textx,texty) # determines where the timer will be displayed
# when the game reaches 0 seconds on the timer, "gameover" is displayed to the terminal
if timeLeft<=0:
gameDisplay = pygame.display.set_mode((w,h)) # Background Code - https://stackoverflow.com/questions/65009141/in-pygame-how-do-i-make-an-image-the-background#:~:text=Load%20a%20back%20ground%20image%20%28e.g.%20%27background.jpg%27%29%2C%20scale,pygame.transform.smoothscale%20%28background%2C%20gameDisplay.get_size%20%28%29%29%20gameDisplay.blit%20%28background%2C%20%280%2C%200%29%29
background = pygame.image.load('Defeat.png').convert() #Retrieve the image
background = pygame.transform.smoothscale(background, gameDisplay.get_size()) # Sets the image size to the window size
gameDisplay.blit(background, (0, 0)) # Draws the image onto the screen
for s in self.snowballs:
s.show()
s.upward()
# Sees if the rect of snowball and rect of elves has collided, if so the elf dissapears
for evil in self.ElvesList:
for s in self.snowballs:
evil.dissapear(s.snowy)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False # stops animation
if event.type == pygame.KEYDOWN:
# handles key press event
if event.key == pygame.K_SPACE:
# When the spacebar is pressed, a snowball will be shot out of Santas location
self.snowballs.append(Snow(self.colors[0],17.5+ SantaC.x,SantaC.y))
if event.key == pygame.K_RIGHT or event.key == pygame.K_d: # santa moves right if right key is clicked. Calls method from Santa's class.
SantaC.Right()
if event.key == pygame.K_LEFT or event.key == pygame.K_a: # santa moves left if left key is clicked. Calls method from Santa's class.
SantaC.Left()
# snowballs will be shown and move upward
#================== Animation control ===================
pygame.display.update()
clock.tick(30) # framerate in fps (30-60 is typical)
Manager().main()
The code is doing a lot of image and font loading repeatedly in the main loop. It's just re-loading the same thing, so this should be moved to before the loop. But I suspect the flickering is caused by the repeated calls to pygame.display.set_mode((w,h)) which is typically only called once, or when handling a window-resize event.
So maybe you want something like this for your main loop:
def showtimer(x,y,font,timeLeft,win):
timing = font.render("Timer :" +str(timeLeft),True,(self.colors[4]))
win.blit(timing,(x,y))
# Set the window size, and setup the timer
gameDisplay = pygame.display.set_mode((w,h))
timer = Timer(27) # 27 because there is a 2 second delay to run the code
timer_x = 10
timer_y = 10
# Load & scale any images, fonts, etc.
font = pygame.font.Font("freesansbold.ttf",32)
snowBackground = pygame.image.load('SnowBackground.webp').convert()
snowBackground = pygame.transform.smoothscale( snowBackground, gameDisplay.get_size())
defBackground = pygame.image.load('Defeat.png').convert()
defBackground = pygame.transform.smoothscale( defBackground, gameDisplay.get_size())
victBackground = pygame.image.load('Victory.png').convert()
victBackground = pygame.transform.smoothscale( victBackground, gameDisplay.get_size())
while running:
timeLeft = timer.countDown()
# clear window (comment out to have trace behind animation)
if (BG == True): # Refresh of image can be turned on/off
# when the game reaches 0 seconds on the timer, "gameover" is displayed to the terminal. Otherwise it's a snowy background
if Dis >= 20:
background = victBackground # player won!
elif timeLeft<=0:
background = defBackground # player defeated
else:
background = snowBackground # still playing
gameDisplay.blit( background, (0, 0) )
# paint & update Evil Elves
for evil in self.ElvesList:
evil.Show()
evil.Moving()
# method that allows Santa to be shown
SantaC.show()
# paint the timer
showtimer( timer_x, timer_y, font, timeLeft, win )
# flush the updates to the window
pygame.display.update()
# handle events & user input
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False # stops animation
# ... etc.
clock.tick( 60 )
I'm not 100% sure how the timer system works, so I just re-arranged it to how I guess it functions. Errors and Omissions should be expected.
The upshot of the changes above is that anything that can be pre-calculated is done outside of the loop. There absolutely no need to re-load and re-scale a background image to the window size every update loop. If you do need to handle window re-size events, do that in an event handler.
This question already has answers here:
Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?
(1 answer)
Why is my PyGame application not running at all?
(2 answers)
Closed 1 year ago.
Hi there and thank you for your time reading this.
This is related to the project I'm making. It's a reaction test game. Basically, Arcade buttons with LEDs light up, and players need to press them to score points. Whack-a-Mole style.
The game is timed, 30 seconds. But instead of using a numerical timer, I'm using a progress bar moving across the screen to indicate the remaining time instead.
image below:
game screenshot
I added this as an image blit in the code, but it doesn't refresh correctly. You can see it only at the start of the game, and when players press a button.
It needs to be constantly blitting across the screen.
Maybe I'm just missing something or my indentation is wrong?
Would really appreciate any inputs on this.
Main game loop code is below:
# MAIN GAME SEQUENCE CODE ---------------------------------------------------------------------------------------------
# Setup Pygame refresh rate to 120 fps
clock.tick(60)
while game_running:
# Idle Screen
idle_scrn()
# Instructions
inst_seq()
# GAME PLAY SECTION --------
score = 0
time_Out = 0
leds.off()
start_Time = pygame.time.Clock()
start = int(time.time())
time_move = -500
random_num = random.randint(0, 11)
leds.on(random_num)
print(random_num)
while time_Out != 30:
screen.blit(Timebar, (time_move,1000))
time_move += 50
pygame.display.update()
for event in pygame.event.get():
print("For Event started, Game screen started")
screen.fill((255,255,255))
screen.blit(Game_screen[6], (0,0))
score_textback = score_fontback.render("00", 3, (199,199,199))
score_text = score_font.render(str(score), 3, (255,37,24))
ctr = 1110
if score >= 10:
ctr -= 155
center_pos = (ctr, 580)
score_rect = score_text.get_rect(center = center_pos)
screen.blit(score_textback, (645, 390))
screen.blit(score_text, score_rect)
if event.type == pygame.JOYBUTTONDOWN:
print("If for event JOYBUTTONDOWN")
if event.button == random_num:
B = event.button
print(B, " button pressed, CORRECT")
leds.off()
butt_Sound.play()
random_num = random.randint(0, 11)
leds.on(random_num)
score += 1
pygame.display.update()
current_Time = int(time.time())
time_Out = current_Time - start
#pygame.display.update()
#print("TIMER: ", time_Out)
#print(type(start_Time))
#print(current_Time)
#print(type(current_Time))
#pygame.display.update()
# FINAL SCORE ------------------------
final_Score()
exit()
The image is Timebar. in the code, we move it 50 pixels across the screen in every refresh.
Thank you in advance.
Here's a minimal example, perhaps you'll find it useful:
import pygame
pygame.init()
width, height = 640, 480
screen = pygame.display.set_mode((width, height))
fps = 60
clock = pygame.time.Clock()
progress_width = 0 # initialse progress tracker
total_time = 0
target_time = 10_000 # ten seconds in milliseconds
finished = False
while not finished:
# Handle Events
for event in pygame.event.get():
if event.type == pygame.QUIT:
finished = True
elif event.type == pygame.KEYDOWN:
progress_width = 0 # reset progress
total_time = 0
# Update Game State
dt = clock.tick(fps) # limit FPS and return time since last call
total_time += dt
progress_width += width * dt / target_time # scale bar width
progress_rect = pygame.Rect(0, height-20, int(progress_width), 20)
# Draw Background
screen.fill(pygame.Color("black"))
# Draw Sprites
pygame.draw.rect(screen, pygame.Color("red"), progress_rect)
# Update Display
pygame.display.flip()
# Display the elapsed time in the title bar
pygame.display.set_caption(f"Simple Progress {total_time:,d} ms")
pygame.quit()
It calculates the time elapsed and updates the progress bar width. It takes ten seconds to fill the screen width and pressing a key resets the progress.
Your main loop should look something like:
Handle Events
Update Game State
Draw sprites
Update Screen
If you're trying to update the screen or handle events in multiple places, things get confusing pretty quickly.
I'm developing a pygame video game, and everything was working out perfectly until yesterday. The issues began after I formatted my pc. So when i run the game, the first screen to show up is the 'Menu'. So in this state class I have an event method where when you press the 'p' key it gets you to the 'Play' state. So now it is not working, I don't know why.
I've changed nothing. I just formatted my pc and reinstalled python, pygame and pgu module. But the strange thing comes when I reprogram the videogame so that the first state to show up when you run the game is the 'Play' state, everything works perfectly. It also has an event method where when you press the arrows, the character moves, and when the player presses ESC it takes you to the 'Menu' state.
So again when I'm at the 'Menu' state the game doesn't respond to the input I'm giving to it. I don't really know what's happening.
Here is an example of what I was saying in comments :
Sorry if all comments are not appropriate to your level but I wanted to be sure you understand it all.
import pygame
screen = pygame.display.set_mode((1000, 1000))
class Menu:
pass
class Play:
pass
def main():
running = True # here we define the main variable of the main loop
main_menu = True # when the main loop will begin, main_menu will begin too
game = False # game is false because player didn't press p
options = False # options is false because player didn't go to options
while running: # begin the main loop
while main_menu:
for event in pygame.event.get(): # listen for events
if event.type == pygame.QUIT: # if the player quit, ends up the 'main_menu' loop and 'running' loop too
running = False
main_menu = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_p: # if p key is pressed, exit from main menu and begin 'game' loop
main_menu = False
game = True
if event.key == pygame.K_o: # if o key is pressed, exit from main menu and begin 'options' loop
main_menu = False
options = True
screen.fill((255, 0, 0)) # I fill the screen in red to make the example more explicit
pygame.display.flip() # I update the screen every frame
while game:
for event in pygame.event.get(): # listen for events
if event.type == pygame.QUIT: # if the player quit, ends up 'running' and 'options' loop
running = False
game = False
if event.type == pygame.KEYDOWN: # listen for keys
if event.key == pygame.K_BACKSPACE: # if the player press backspace (delete), ends up 'game' loop
game = False # and begin (again) the 'main_menu' loop
main_menu = True
screen.fill((255, 255, 255)) # I fill the screen in white to make the example more explicit
pygame.display.flip() # I update the screen every frame
while options: # same logic for this one
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
options = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_BACKSPACE:
options = False
main_menu = True
screen.fill((0, 255, 0))
pygame.display.flip()
pygame.init() # initialize pygame
main() # begin main loop
pygame.quit() # quit pygame
Currently, I am working on a game in which you are asked a mathematical question such as 2 + 1 and numbers will fall from the top of the screen. The player has to click the right answer before it falls below the screen. However, I don't want to download images of the numbers because it would waste lots of time. Is there a way to draw or blit numbers instead? If there is, can the numbers be in a circle shape instead of a rectangle?
EDIT: I could create the numbers by displaying them as text. However, that would mean I have to create hundreds of different rectangles for each possible answer. My question then is, is there a way for me to tell Python to generate numbers and place them on a rectangle without me having to do it manually?
One solution would be to create a class in which you store the actual answer, the text surface and the rect for the collision detection. I use a pygame.sprite.Sprite subclass here, but you can do the same with a normal class. When a new question gets asked, you can just create a bunch of instances and add them to a sprite group, so that you can update them altogether in the main loop. You can use the pygame.Rect.collidepoint method for the collision detection.
import random
import pygame as pg
from pygame.math import Vector2
pg.init()
BLUE = pg.Color('dodgerblue1')
FONT = pg.font.Font(None, 42)
class Answer(pg.sprite.Sprite):
def __init__(self, pos, number):
super().__init__()
# Store the actual number, so that we can compare it
# when the user clicks on this object.
self.number = number
# Render the new text image/surface.
self.image = FONT.render(str(number), True, BLUE)
# A rect with the size of the surface, used for collision
# detection and rendering.
self.rect = self.image.get_rect(topleft=pos)
self.vel = Vector2(0, random.uniform(1, 4))
self.pos = Vector2(pos)
def update(self):
self.pos += self.vel
self.rect.center = self.pos
if self.rect.top > 480: # Screen bottom.
self.kill() # Remove the sprite from all groups.
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.MOUSEBUTTONDOWN:
if event.button == 3: # Right mouse button.
# Add 20 numbers (Answer objects).
for _ in range(20):
number = random.randrange(100)
all_sprites.add(Answer((random.randrange(620), -20), number))
elif event.button == 1: # Left mouse button.
# See if the user clicked on a number.
for answer in all_sprites:
# event.pos is the mouse position.
if answer.rect.collidepoint(event.pos):
print(answer.number)
all_sprites.update()
screen.fill((30, 30, 30))
all_sprites.draw(screen)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
(Right click to spawn the numbers, left click to touch single numbers.)
I am currently working on a game called Table Wars, a turn based strategy game for two players. Progress has been going smoothly, until I ran into a problem with spawning units.
The program won't spawn multiple of the same unit, or respawn new ones after the old ones die.
Here is some information that may help:
Each class is stored in a variable: (redI = Red_Infantry())
All functions are stored in the main loop.
The sprite classes have hard-coded X and Y values, used when spawning units and moving units.
What should I do?
As requested, here is the class for the Red Infantry:
class Red_Infantry(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_image('Soldier_red.png', -1)
self.selected = 0
self.area = screen.get_rect()
self.rect.topleft = (100, 300)
self.health = 100 #Soldiers are have mediocre toughness.
self.attack_damage = 25
self.range_maximum = 20 #in pixels, this is melee range
self.range_minimum = 0
self.update()
def update(self):
if self.health <= 0:
self.kill()
and the code to spawn this unit:
if spawned_units < 3 and PHASE == 1 and TURN == 'Red':
if REDGOLD < 10:
print "Out of money! Moving to Phase 2!"
PHASE = 2
spawned_units = 0
elif event.type == KEYDOWN and event.key == K_1:
if REDGOLD >= 10 and REDCOMMAND >= 5:
Sprites.append(redI)
REDGOLD -= 10
REDCOMMAND -= 5
spawned_units = spawned_units + 1
else:
print "Not enough gold!"
This is similar style with all units. It performs correctly the first time, but not in the second, third, and so on, meaning I can only have one Soldier. Also, when that soldier dies via self.kill, it won't come back if I try to spawn it.
The part of the spawn procedure you posted doesn't create any new instances. Unless redI is declared as a new Red_Infantry somewhere else, you need to modify the code to create a new instance of Red_Infantry every time you want to spawn a soldier.
sprites.append(Red_Infantry())
To update the sprites:
for sprite in sprites:
sprite.update()
Put movement and other state changes in the update method. This is what pygame expects, but you can use a different style if you want. The main point is you must have multiple instances of Red_Infantry in order to see multiple sprites.
You could also use pygame's Group class instead of a simple list to hold the sprites.
Here's a full example that uses Group instead of list. In the example, an Enemy is spawned each time a key is pressed. Each Enemy prints its unique ID to stdout.
import sys
import random
import pygame
from pygame.locals import *
def main():
pygame.init()
screen = pygame.display.set_mode((480, 320))
enemies = pygame.sprite.Group()
while True:
for event in pygame.event.get():
if event.type == KEYDOWN:
enemies.add(Enemy(screen))
elif event.type == QUIT:
sys.exit()
enemies.update()
screen.fill(pygame.Color("black"))
enemies.draw(screen)
pygame.display.update()
class Enemy(pygame.sprite.Sprite):
def __init__(self, screen):
pygame.sprite.Sprite.__init__(self)
print "created a new sprite:", id(self)
self.image = pygame.image.load("sprite.png")
self.rect = self.image.get_rect()
self.rect.move_ip(random.randint(0, screen.get_width()),
random.randint(0, screen.get_height()))
def update(self):
self.rect.move_ip(random.randint(-3, 3), 0)
if __name__ == "__main__":
main()