Pygame Using Class to Randomize Image Placements - python

I'm creating a card/tile memory association game. It is a 4x4 grid of 100x100 pixel images, so 16 images in total are displayed (8 pairs).
For now all I want is for the images to be displayed in a grid in a random order each time the game is started, which I feel I am close to doing using shuffling them in a list in a class and then calling that class from the main function in the while loop.
Here is my code:
# Memory Tiles Game
# A Memory Game which users can flip tiles in and remember their placement to match
# all of the tiles
import pygame, sys, time
from pygame.locals import *
# User-defined classes
class memorygame(object):
def __init__(self):
imagelist = [image1,image2,image3,image4,image5,image6,image7
image8,image9]
shuffle.imagelist
screen.blit(imagelist[0],(0,0))
screen.blit(imagelist[1],(104,0))
screen.blit(imagelist[2],(208,0))
screen.blit(imagelist[3],(312,0))
screen.blit(imagelist[4],(0,104))
screen.blit(imagelist[5],(104,104))
screen.blit(imagelist[6],(208,104))
screen.blit(imagelist[7],(312,104))
shuffle.imagelist
screen.blit(imagelist[0],(0,208))
screen.blit(imagelist[1],(104,208))
screen.blit(imagelist[2],(208,208))
screen.blit(imagelist[3],(312,208))
screen.blit(imagelist[4],(0,312))
screen.blit(imagelist[5],(104,312))
screen.blit(imagelist[6],(208,312))
screen.blit(imagelist[7],(312,312))
# User-defined functions
def main():
black = ( 0, 0, 0)
white = (255,255,255)
red = (100, 0, 0)
green = ( 0,153, 0)
blue = ( 0, 0,255)
image1 = pygame.image.load('image0.bmp')
image2 = pygame.image.load('image1.bmp')
image3 = pygame.image.load('image2.bmp')
image4 = pygame.image.load('image3.bmp')
image5 = pygame.image.load('image4.bmp')
image6 = pygame.image.load('image5.bmp')
image7 = pygame.image.load('image6.bmp')
image8 = pygame.image.load('image7.bmp')
image9 = pygame.image.load('image8.bmp')
w = 500
h = 400
screen = pygame.display.set_mode((w, h))
screen.fill((white))
running = 1
# Initialize pygame
pygame.init()
# Set window size and title, and frame delay
surfaceSize = (500, 400) # example window size
windowTitle = 'Memory Game' # example title
frameDelay = 0.02 # smaller is faster game
# Create the window
surface = pygame.display.set_mode(surfaceSize, 0, 0)
pygame.display.set_caption(windowTitle)
# create and initialize objects
gameOver = False
#center = [200, 200] # example - replace
# Draw objects
# The next line is an example - replace it
#pygame.draw.circle(surface, pygame.Color('green'), center, 50, 0)
# Refresh the display
pygame.display.update()
# Loop forever
while True:
# Check event
event = pygame.event.poll()
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.fill((black))
class memorygame(object)
# Handle additional events
# Update and draw objects for the next frame
gameOver = update(center, surface)
# Refresh the display
pygame.display.update()
# Set the frame speed by pausing between frames
time.sleep(frameDelay)
main()
It doesn't seem to compile, and I am not sure why. I get a syntax error in the shell.

First of all, you forgot a comma at the end of the first line in the imagelist in your memorygame class. Changing that to
imagelist = [image1,image2,image3,image4,image5,image6,image7,
image8,image9]
should fix the first syntax error.
Secondly, I'm not sure what you are trying to achieve with the line class memorygame(object) in your main loop. You probably want to create an instance of the class outside of the while loop and call a function that blits the images inside the while loop.
The image variables are local by the way, the memorygame class will not see them, unless you explicitly make them global variables, or pass them to the __init__ method of memorygame.
Besides, the way you're shuffling the imagelist isn't quite right. You should import random, and then call random.shuffle(imagelist) instead.

Related

Explosions Sprite Despears Way To Fast When Enemy is Killed How Do Fix This?

on my draw I did this but the explosion doesnt event last a sec and just dispears
is there a better way I could do this instead of saying if the enemy health is greater then this load this?
for enemys in enemying:
if enemys.health < -4
for explode in explodes:
explode.draw((enemys.hitbox, enemys.hitbox))
my explosion class
class explode:
def __init__(self,x,y,height,width,color):
self.x = x
self.y = y
self.height = height
self.width = width
self.explode = [
pygame.image.load("spark_01.png"),
pygame.image.load("spark_02.png"),
pygame.image.load("spark_03.png"),
pygame.image.load("spark_04.png"),
pygame.image.load("spark_05.png"),
pygame.image.load("spark_06.png"),
pygame.image.load("spark_07.png")]
self.explode = [pygame.transform.scale(image,(image.get_width()//5,image.get_height()//5)) for image in self.explode]
self.rect = pygame.Rect(x,y,height,width)
self.direction = "blobright"
self.anim_index = 0
def draw(self,x):
self.rect.topleft = (self.x,self.y)
if self.direction == "blobright":
window.blit(self.explode[self.anim_index], self.rect)
self.anim_index += 1
if self.anim_index == len(self.explode):
self.anim_index = 0
black = (0,0,0)
explode1 = explode(400,450,50,50,black)
explodes = [explode1]
this is where I delete the enemys
for enemyshoot in enemyshooting:
for bullet in bullets:
if bullet.rect.colliderect(enemyshoot.hitbox):
if enemyshoot.health > -8:
enemyshoot.health -= 1
bullets.pop(bullets.index(bullet))
else:
del enemyshooting[one]
Here is the example I promised. Notice how the system clock and a flag
are used to control animation speed so that different actions can happen on the screen at different speeds. This program is written quick-and-dirty. There are MUCH more efficient ways to handle the animation so that the screen is only drawn to when it is time for something to move, and ONLY those parts of the screen that have changed are drawn and refreshed. But don't worry about that. The lesson here is how to use the clock to slow down your animation speed. What's the old saying? Code now, refactor later? Words to live by.
import pygame
from pygame.locals import * # Pygame Constants such as FULLSCREEN and KEYDOWN.
from pygame import Color
pygame.init()
import time
# ==============================================================
# Disable Windows Auto-scaling
# The windows auto-scaling feature can mess with pygame graphics.
# Windows-Specific: Delete if you are not on a Windows machine
# If you are on Windows, comment section to see the effect.
import ctypes
awareness = ctypes.c_int()
errorCode = ctypes.windll.shcore.GetProcessDpiAwareness(0, ctypes.byref(awareness))
errorCode = ctypes.windll.shcore.SetProcessDpiAwareness(2) # Awareness levels can be 0, 1 or 2:
# ===============================================================
# I will base the example on your explode class. If I were writing the
# game, I would use a sprite class along with a sprite group to simplify
# the code. However, these topics are an entirely different branch of study
# so I won't use them in the example. Forgive my quick-and-dirty code.
# I don't have your image files, but it looks as though
# you have an actual animation to use for your explosion that is
# made up of several different frames. We will emulate this for the
# sake of our demonstration.
class EXPLODE:
def create_spark(self):
TRANSPARENT = (254,255,255) # You can chose your own transparent color.
# Lacking the spark files, let's draw our own.
spark_img = pygame.Surface((31,31))
spark_img.fill(TRANSPARENT)
spark_img.set_colorkey(TRANSPARENT)
spark_rec = spark_img.get_rect()
left_center = (spark_rec.left,spark_rec.centery)
right_center = (spark_rec.right,spark_rec.centery)
top_center = (spark_rec.centerx,spark_rec.top)
bottom_center = (spark_rec.centerx,spark_rec.bottom)
top_left = spark_rec.topleft
top_right = spark_rec.topright
bottom_left = spark_rec.bottomleft
bottom_right = spark_rec.bottomright
pygame.draw.circle(spark_img,Color("yellow"),spark_rec.center,spark_rec.width//2,0)
pygame.draw.line(spark_img,Color("indianred"),left_center,right_center,2)
pygame.draw.line(spark_img,Color("red"),top_center,bottom_center,2)
pygame.draw.line(spark_img,Color("burlywood3"),top_left,bottom_right,3)
pygame.draw.line(spark_img,Color("orange"),top_right,bottom_left,3)
# Now crop line segments that fall outside the spark circle..
pygame.draw.circle(spark_img,TRANSPARENT,spark_rec.center,spark_rec.width//2+8,8)
return spark_img
def __init__(self,window,x,y,height,width,color = (255,0,0)):
self.window = window # Needed so class can draw to the screen.
self.T0 = time.time() # Holds the starting time for the timer.
self.x = x
self.y = y
self.height = height
self.width = width
self.anim_index = 0
image = self.create_spark()
# Standing in for actual animation pages, we scale up the spark image.
self.explode = [
image,
pygame.transform.scale(image,(image.get_width()*2,image.get_height()*2)),
pygame.transform.scale(image,(image.get_width()*4,image.get_height()*4)),
pygame.transform.scale(image,(image.get_width()*6,image.get_height()*6)),
pygame.transform.scale(image,(image.get_width()*8,image.get_height()*8))]
'''
# Or you can load your spark frames as before.
self.explode = [
pygame.image.load("spark_01.png"),
pygame.image.load("spark_02.png"),
pygame.image.load("spark_03.png"),
pygame.image.load("spark_04.png"),
pygame.image.load("spark_05.png"),
pygame.image.load("spark_06.png"),
pygame.image.load("spark_07.png")]
# All of the loaded images are scaled down to 1/5 their size.
self.explode = [pygame.transform.scale(image,(image.get_width()//5,image.get_height()//5)) for image in self.explode]
'''
self.rect = image.get_rect()
self.direction = "blobright" # <-- I don't know what this is, so I've ignored it.
self.anim_index = 0
def draw(self,enemy_rec,anin_speed): # Create an animation method to handle the draw routine.
clock = time.time()
elapsed_time = clock - self.T0
finish_flg = False
if elapsed_time > anin_speed: # Animation Speed Controlled Here!!
self.anim_index +=1
self.T0 = time.time() # Reset the start time.
if self.anim_index == len(self.explode)-1:
finish_flg = True
frame = self.explode[self.anim_index]
rec = frame.get_rect()
rec.center = enemy_rec.center
self.window.blit(frame,rec)
return finish_flg # The finish flag lets the main program know it can delete the enemy.
# ================== MAIN() ===================
# ----------------------------------------------
def main(): # By using a 'main()' function, your code will run faster!
screen = pygame.display.set_mode((3000,2000),pygame.FULLSCREEN,32)
screen_rec = screen.get_rect()
screen.fill(Color("steelblue1"))
# Declare and initialie an instance of the EXPLODE class.
# Only one enemy can blow up at the same time for any give instance
# of the class, so you may want each ship to have its own instance
# if there is a chance of simultanious explosions.
# I wouldn't normally use this aproach, but I wanted to stay
# as close as possible to your existing code.
explode = EXPLODE(screen,screen_rec.centerx,screen_rec.centery,30,20,Color('blue'))
# Let's create some "enemy" units.
# You would use an enemy class for this (and for drawing them)
# but this example is qick and dirty, so.. Two enemies coming up!
# One enemy to blow up when it hits the wall.
enemy1_img = pygame.Surface((30,30))
enemy1_rec = enemy1_img.get_rect()
enemy1_img.fill(Color("Green"))
pygame.draw.rect(enemy1_img,Color("Red"),enemy1_rec,5)
# And one 'enemy' to move while the other is blowing up.
enemy2_img = enemy1_img.copy()
enemy2_rec = enemy2_img.get_rect()
# Give enemies screen positions.
enemy1_rec.center = (screen_rec.centerx-300, screen_rec.centery-300)
enemy2_rec.center = (screen_rec.centerx-800,screen_rec.centery-300)
# Create a wall for a ship to crash into.
wall_img = pygame.Surface((100,60))
wall_img.fill(Color("Indianred"))
wall_rec = wall_img.get_rect()
wall_rec.center = screen_rec.center
wall_rec = wall_rec.move((400,0))
# Oh, this list is ugly. Forgive me! Used instead of a list of Enemy-Class objects.
enemy_list = [[10,enemy1_img,enemy1_rec,(2,1)],[10,enemy2_img,enemy2_rec,(3,0)]] # [Life, Image, Rectangle, Speed]
# Ok, the setup is finished. Time for some action!
# =============== BODY ===================
# ------------------------------------------
anin_speed = 0.3 # You can control explosion speed here!
pygame.mouse.set_visible(False)
run_cycle = True
while run_cycle == True:
# There are much better ways to erase images, but this will do for now.
screen.fill(Color("steelblue1")) # Erase old sprites.
screen.blit(wall_img,wall_rec) # Put the wall back in place.
# Because it is bad idea to modify an object being looped through,
# we will construct a new list, called 'hold', and copy it back at the end.
hold = []
for enmy in enemy_list:
life,enemy_img,enemy_rec,speed = enmy
if life > 4:
screen.blit(enemy_img,enemy_rec) # If enemy is healthy, put it on the screen.
enemy_rec = enemy_rec.move(speed)
if enemy_rec.colliderect(wall_rec) == True:
life = 0
if enemy_rec.left > screen_rec.right+10: # End the program after top ship leaves the screen.
run_cycle = False
hold.append([life,enemy_img,enemy_rec,speed])
else: # Otherwise draw the explosion.
finish_flg = explode.draw(enemy_rec,anin_speed)
if finish_flg == False: # If TRUE the enemy is ommitted from the hold list!
hold.append(enmy)
enemy_list = hold.copy() # And now the possibly modified list is copied back to the enemy_list.
pygame.display.flip()
# ================
# Main
# ----------------
main() # Hint! For technical reasons related to the compiler being able
# to control scope and predict variable sizes, keeping your
# main body encapsulated in a function like this will improve
# efficiency and run speeds.
You have a great start. If nothing needs to happen while the explosion is going on, you could use a sleep command in your loop. >> time.sleep(0.01)
If the action has to continue on the screen during the explosion, then you will need to use a timer and keep returning to that function after each duration to draw the next frame. Just initialize using >> T0 = time.time() before the explosion, visit the function when time.time()-T0 > 0.01 seconds (for example) and reset T0 = time.time() after each frame is drawn. Return a 'finished' value when the animation is over, so you can remove it from your enemy list.
In the __init__() for explode note the time when it is called and save it.
In the explodes draw() only increment self.anim_index when enough time has passed since the last time it was incremented (based on the time value you saved in the __init__()). This will let you go more slowly through the frames of the exploding animation.
There is really no difference between this and any other object animation, other than once the cycle completes the object (the explosion) goes a way.

How can I change this surface image to the image I want in pygame?

# Memory V2
# The second version contains the complete tile grid and the black panel on the right, there is score in the black panel. All 8 pairs of two tiles are covered by question mark when the game starts . Each time the game is played, the tiles spawn in random locations in the grid. Player can click tiles to reveal images. Game ends upon clicking close screen or all 16 tiles being exposed. Game occurs on a 4x4 grid.
import pygame,random, time
# User-defined functions
def main():
# initialize all pygame modules (some need initialization)
pygame.init()
# create a pygame display window
pygame.display.set_mode((500, 400))
# set the title of the display window
pygame.display.set_caption('Memory v1')
# get the display surface
w_surface = pygame.display.get_surface()
# create a game object
game = Game(w_surface)
# start the main game loop by calling the play method on the game
#object
game.play()
# quit pygame and clean up the pygame window
pygame.quit()
# User-defined classes
class Game:
# An object in this class represents a complete game.
def __init__(self, surface):
# Initialize a Game.
# - self is the Game to initialize
# - surface is the display window surface object
# === objects that are part of every game that we will discuss
self.surface = surface
self.bg_color = pygame.Color('black')
self.FPS = 60
self.game_Clock = pygame.time.Clock()
self.close_clicked = False
self.continue_game = True
Tile.set_surface(self.surface)
# tell grid to be size 4 meaning 4x4 or 16 squares total
grid_size = 4
self.create_grid(grid_size)
self.score=0
def draw_score(self):
# this method draws the player's score in the top-right corner of the
# game window.
# - self : the game the score is being drawn for
font_color = pygame.Color("white")
font_bg = pygame.Color("black")
font = pygame.font.SysFont("arial", 32)
text_img = font.render(str(self.score), True, font_color, font_bg)
text_pos = (460,0)
self.surface.blit(text_img, text_pos)
def create_grid(self, grid_size):
# Creates a grid of tiles that is grid_size x grid_size in size.
self.grid = [ ]
# Create list of image names to be used on the squares (we just append image(1-9) and the file type bmp
# Then we create image surfaces of each image name and add image surfaces to itself which provides us with two of each image
img_names = ['image' + str(i) + '.bmp' for i in range(1,9)]
image_surfaces = [pygame.image.load(name) for name in img_names]
image_surfaces = image_surfaces + image_surfaces
random.shuffle(image_surfaces)
# this for loop creates each row in our grid
for row_num in range(grid_size):
new_row = self.create_row(row_num, grid_size,image_surfaces)
self.grid.append(new_row)
def create_row(self, row_num, size,images):
# Create one row in a grid. Each row contains size Tiles
# required for calculating the tile's x,y coordinates on screen
# - row_num: the nth row of the grid being created
# - size : the number of tiles in the row
# returns the newly created row'
tile_height = self.surface.get_height() // size
# 3/4 to leave space for black column on side
tile_width = 3/4*self.surface.get_width() // size
new_row = [ ]
for col_num in range(size):
# number of row x tile height produces y position
# number of col x tile_width produces x position
# + 10 so it fits
pos = (row_num*tile_height+10,col_num*tile_width+10)
# assigns one of the images to each tile by pairing it with a unique coordinate
#content=pygame.image.load('image0.bmp')
#content = images[row_num*size+col_num]
one_tile = Tile(pos, tile_width, tile_height)
content=pygame.image.load('image0.bmp')
#content=images[row_num*size+col_num]
if self.handle_mouse_click==True:
content=images[row_num*size+col_num]
one_tile.set_content(content)
#one_tile = Tile(pos, tile_width, tile_height)
#one_tile.set_content(content)
new_row.append(one_tile)
return new_row
def play(self):
# Play the game until the player presses the close box.
# - self is the Game that should be continued or not.
while not self.close_clicked: # until player clicks close box
# play frame
self.handle_events()
self.draw()
if self.continue_game:
self.update()
self.decide_continue()
self.game_Clock.tick(self.FPS) # run at most with FPS listed
def handle_events(self):
# Handle each user event by changing the game state
# - self is the Game whose events will be handled
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
self.close_clicked = True
if event.type == pygame.MOUSEBUTTONDOWN:
self.handle_mouse_click(event)
def handle_mouse_click(self, event):
# responds to one mouse click on screen; that means flipping the
# tile
#print("Screen was clicked at " + str(event.pos))
for row in self.grid:
for tile in row:
if tile.select(event.pos)==True:
print('hi')
#def change_content(self,content):
#return False
#return content_switch
def draw(self):
# Draw all game objects.
# - self is the Game to draw
self.surface.fill(self.bg_color) # clear the display surface
# draws the grid
for row in self.grid:
for tile in row:
tile.draw()
self.draw_score()
pygame.display.update() # updates the display
def update(self):
# Update the game objects for the next frame.
# - self is the Game to update
self.score= pygame.time.get_ticks()//1000
pass
def decide_continue(self):
# Check and remember if the game should continue
filled_tiles = [ ]
for row in self.grid:
for tile in row:
if tile.tile_content==True:
filled_tiles.append(tile)
if len(filled_tiles) == self.grid_size ** 2:
return False
else:
return True
class Tile:
# A tile represents one location on a grid. Tiles hold content
# (in this case, an X or an O).
# class attributes that are common to all tiles
# setting surface to none isnt exactly necessary, however we set class wide attributes here before putting it in a method
surface = None
fg_color = pygame.Color("white")
bg_color = pygame.Color("black")
# set border width for each tile in grid
border_width = 5
#classmethod
def set_surface(cls, surface):
# sets the class attribute, surface
cls.surface = surface
def __init__(self, screen_position, width, height):
# initialize one instance of our Tile class. Tiles represent
# one 'position' in our tic-tac-toe board.
# - self: the tile being initialized
# - screen_position: the [x, y] coordinates to draw the tile at
# - width: the width of the tile
# - height: the height of the tile
self.screen_position = screen_position
#self.content = ''
# create a rectangle defining our boundaries
x, y = screen_position
self.rect = pygame.Rect(x, y, width, height)
def draw_content(self):
# create an rect object of image so we can blit images to surface of grid tiles
image_rect=self.content.get_rect(center=self.rect.center)
Tile.surface.blit(self.content,image_rect)
def draw(self):
# draw the contents of a tile to its surface.
# - self: the tile being drawn
self.draw_content()
pygame.draw.rect(Tile.surface, Tile.bg_color, self.rect,
Tile.border_width)
def set_content(self, new_content):
# change our tile content.
self.content = new_content
def select(self, pos):
selected=False
if self.rect.collidepoint(pos):
if self.content==pygame.image.load('image0.bmp'):
selected=True
return selected
def __eq__(self):
if self.content==pygame.image.load('image0.bmp'):
return True
def tile_content(self):
if self.content == pygame.image.load('image0.bmp'):
return False
else:
return True
main()
So I'm trying to build another version of the game memory where upon clicking one of the tiles the question mark image 'flips' and becomes the actual image I assigned in my code and then the game ends after I flip all of the tiles. However, when I use self.content==pygame.image.load('image0.bmp') it doesn't seem to work or return true or anything even though I set it to do so. My professor said I need to overload the == operator which I think I did but for some reason it still refuses to flip upon me clicking it and I have no idea why? Can someone explain?
This is because pygame.image.load() returns a pygame.Surface(). Any object (instance of a class) is never exactly the same.
So:
pygame.image.load("image.png") == pygame.image.load("image.png") will always be False.
Also, when asking a question, try to put small snippets of code instead of the whole thing.

how to make an animation in pygame [duplicate]

This question already has answers here:
Animated sprite from few images
(4 answers)
Closed 1 year ago.
i am trying to make an animation of when my player gets shot to make it seem like he is falling to the ground.
i have tried the code below but that doesn't seem to work. it slows down the frames and only shows the last image of my animation is there a simpler way of animation in pygame?
if player2_hit_sequence == True:
stage1 = True
if stage1 == True:
game_display.blit(dying1_p2, (player2X, player2Y))
time.sleep(0.2)
stage1 = False
stage2 = True
if stage2 == True:
game_display.blit(dying2_p2, (player2X, player2Y))
time.sleep(0.2)
stage2 = False
stage3 = True
if stage3 == True:
game_display.blit(dying3_p2, (player2X, player2Y))
time.sleep(0.2)
is there a function to make a sequence of images or something like that?
Ok so for animation you need a bunch of images, and a timer.
I'm presenting some code snippets based around a pygame sprite. Maybe this doesn't exactly fit the question, but it seems like a better solution then painting/blitting images manually.
So first the code starts with a sprite class:
class AlienSprite(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.base_image = pygame.image.load('alien.png').convert_alpha()
self.image = self.base_image
self.rect = self.image.get_rect()
self.rect.center = ( WINDOW_WIDTH//2, WINDOW_HEIGHT//2 )
# Load warp animation
self.warp_at_time = 0
self.warp_images = []
for filename in [ "warp1.png", "warp2.png", "warp3.png" ]:
self.warp_images.append( pygame.image.load(filename).convert_alpha() )
So the idea is the Alien Sprite has a "normal" image, but then when it "warps" (teleports) an animation plays. The way this is implemented is to have a list of animation images. When the animation starts, the sprite's image is changed from base_image to the first of the warp_images[]. As time elapses, the sprites image is changed to the next frame, and then the next, before finally reverting back to the base image. By embedding all this into the sprite update() function, the normal updating mechanism for sprites handles the current "state" of the alien sprite, normal or "warp". Once the "warp"-state is triggered, it runs without any extra involvement of the pygame main loop.
def update(self):
# Get the current time in milliseconds (normally I keep this in a global)
NOW_MS = int(time.time() * 1000.0)
# Did the alien warp? (and at what time)
if (self.warp_at_time > 0):
# 3 Frames of warp animation, show each for 200m
ms_since_warp_start = NOW_MS - self.warp_at_time
if ( ms_since_warp > 600 ):
# Warp complete
self.warp_at_time = 0
self.image = self.base_image # return to original bitmap
# Move to random location
self.rect.center = ( random.randrange( 0, WINDOW_WIDTH ), random.randrange( 0, WINDOW_HEIGHT ) )
else:
image_number = ms_since_warp // 200 # select the frame for this 200ms period
self.image = self.warp_images[image_number] # show that image
def startWarp(self):
# Get the current time in milliseconds (normally I keep this in a global)
NOW_MS = int(time.time() * 1000.0)
# if not warping already ...
if (self.warp_at_time == 0):
self.warp_at_time = NOW_MS
So the first thing to notice, is that the update() uses the clock to know the number of elapsed milliseconds since the animation started. To keep track of the time I typically set a global NOW_MS in the game loop.
In the sprite, we have 3 frames of animation, with 200 milliseconds between each frame. To start a sprite animating, simply call startWarp() which obviously just kicks-off the timer.
SPRITES = pygame.sprite.Group()
alien_sprite = AlienSprite()
SPRITES.add(alien_sprite)
...
# Game Loop
done = False
while not done:
SPRITES.update()
# redraw window
screen.fill(BLACK)
SPRITES.draw(screen)
pygame.display.update()
pygame.display.flip()
if (<some condition>):
alien_sprite.startWarp() # do it
Obviously all those frame timings & what-not should be member variables of the sprite class, but I didn't do that to keep the example simple.

Pygame Cannot Blit An Image To A List Of Rectangles

I am working with pygame, and I thought it'd be a super neat idea to make it so that the bricks were automatically generated at the beginning of the game. So I made a function that asks for how many bricks you want generated, and then creates the "bodies" for those bricks in special locations and assigns them to a list. Then, in the while loop, I try to blit those with the according image. However, I get an error I have never seen before.
Error Image
import pygame, sys
import random
import numpy
pygame.init()
def myPopulater(amountToMake, image, width, h):
myBodies = []
for i in range(amountToMake):
r1 = numpy.random.randint(0, width)
r2 = numpy.random.randint(0, h)
myBodies = myBodies + image.get_rect()
myBodies[i].x = r1
myBodies[i].x = r2
return myBodies
width = 500
h = 500
ball = pygame.image.load("c:\\python\\ball.png")
screen = pygame.display.set_mode((width, h))
myList = myPopulater(25, ball, width, h)
while (1):
#WHENEVER SOMETHING HAPPENS
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill(black)
for i in range(0, 25):
screen.blit(ball, myList[i])
pygame.display.flip()
From what I can see, you're trying to add the result of image.get_rect() to your myBodies list.
You should use the list.append method to add an element to a list object.
Change this line:
myBodies = myBodies + image.get_rect()
To this:
myBodies.append(image.get_rect())
That will fix your error.

Pygame MemoryError

HI i wrote a simple block collecting program that was working just fine and dandy until i added sound. Then all the sudden i get a MemoryError which is something ive never seen before.
my code is attached along with the sound(wav) file that seem to be the problem. Any help would be great, and yes the code and the sound are in the same folder along with tons of other programs and pictures and stuff.
import pygame
import random
import pygame.mixer
winsound=pygame.mixer.Sound('winning.wav')
collectsound=pygame.mixer.Sound('blip.wav')
#Define colors
black = ( 0, 0, 0)
white = ( 255, 255, 255)
red = ( 255, 0, 0)
#Class represents ball, derives from Sprite class in pygame
class Block(pygame.sprite.Sprite):
#Constructor. Pass in the color of the block and its x and y pos.
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
pygame.sprite.Sprite.__init__(self)
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
self.image = pygame.Surface([width, height])
self.image.fill(color)
# Fetch the rectangle object that has the dimensions of the image
# image.
# Update the position of this object by setting the values
# of rect.x and rect.y
self.rect = self.image.get_rect()
# Initialize Pygame
pygame.init()
winsound=pygame.mixer.Sound('winning.wav')
collectsound=pygame.mixer.Sound('blip.wav')
#Set width and height of screen
screen_width=700
screen_height=400
screen=pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption('Block Attack!')
#List of sprites. Each block is added to this list. List is managed by RenderPlain()
block_list=pygame.sprite.RenderPlain()
#List of every sprite
all_sprites_list=pygame.sprite.RenderPlain()
for i in range(50):
#create instance of block
block=Block(black,20,14)
#set random location for the block
block.rect.x=random.randrange(screen_width)
block.rect.y=random.randrange(screen_height)
#Add the block to the list of objects
block_list.add(block)
all_sprites_list.add(block)
#Create red player block
player=Block(red,20,15)
all_sprites_list.add(player)
done=False
clock=pygame.time.Clock()
score=0
#-------Main Program Loop-------
while done==False:
for event in pygame.event.get(): #User did something
if event.type==pygame.QUIT: #If user clicked close
done=True #Flag that we are done so we exit this loop
#Clear screen
screen.fill(white)
#Get current mouse position. This returns the position as a list of two numbers
pos=pygame.mouse.get_pos()
#Fetch x and y out of list, like letters out of strung, set player object
#to location of the mouse
player.rect.x=pos[0]
player.rect.y=pos[1]
#Check if player block has collidied with anything...were still in a loop
block_hit_list=pygame.sprite.spritecollide(player, block_list, True)
#Check list of collisions.
if len(block_hit_list) >0:
score +=len(block_hit_list)
print( score )
collectsound.play()
elif score==50:
print('YOU WIN!!\n')
done=True
winsound.play()
#Draw all the sprites
all_sprites_list.draw(screen)
#Limit to 60 frames per second
clock.tick(60)
#Update screen
pygame.display.flip()
pygame.quit()
So when i run the code i get the error
Traceback (most recent call last):
File "/Users/zackbaker/Desktop/PythonFolder/BlockCollecter.py", line 4, in <module>
sound=pygame.mixer.Sound('winning.wav')
MemoryError
I think you have to initialize the mixer first, before using sounds.
pygame.mixer.init(44100, -16, 2, 2048)
# Read the docs to know what these numbers are

Categories