I can't move sprites in pygame - python

It's the first time I create a game with pygame and I find a logical error. This game consist in a sort of puzzle and to play it you have to click to the piece of puzzle then click on the area where you want it to move. When I try to run my code, sprites doesn't move. I tried to modify the function move(), but it didn't change anything. When I run the program and I selected and move the pieces of puzzle of the game they are drawing again by the computer but in the same position. They aren't moving at the coordinates that I write in the code.
import pygame
from pygame.locals import *
import sys
import os
width = 1100
hight = 700
square1 = (240, 45)
square2 = (25, 55)
square3 = (25, 245)
square4 = (248, 245)
coords1 = [800, 50]
coords2 = [550, 50]
coords3 = [550, 250]
coords4 = [810, 250]
pygame.init()
screen = pygame.display.set_mode((width, hight))
pygame.display.set_caption('Hidden Boys')
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((250, 250, 250))
class Puzzle_piece(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.counter = 0
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.state = "still"
self.area = screen.get_rect()
self.angle = 0
self.movepos = [0, 0]
def updates(self, position):
self.rect = position
def move(self):
screen.blit(self.image, self.rect)
def rotate_right(self):
self.angle += -90
self.image = pg.transform.rotozoom(self.orig_image, self.angle, 1)
self.rect = self.image.get_rect(center = self.rect.center)
class Frame(pygame.sprite.Sprite):
def __init__(self, image_file = None, location = None, dim = screen, color = (250, 250, 250)):
pygame.sprite.Sprite.__init__(self) #call Sprite initializer
if image_file and location != None :
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
self.frame = pygame.Surface(dim.get_size())
self.frame = self.frame.convert()
self.frame.fill(color)
def create_text(dim, blitted, color = (0, 0, 0), font = "", msg = "", position = (width, hight), alias = True):
font = pygame.font.SysFont(font, dim)
text = font.render(msg, alias, color)
textpos = text.get_rect()
textpos.center = position
blitted.blit(text, textpos)
def create_frames(name = "frame0", dim = screen, color = (250, 250, 250), image ="" ):
name = pygame.Surface(dim.get_size())
name = name.convert()
name.fill(color)
return name, img
def blit_frames(frame, coords = (0, 0), image = None, image_rect = None):
if image and image_rect != None :
frame.blit(image, image_rect)
screen.blit(frame, coords)
pygame.display.update()
pygame.display.flip()
def draw_sprites(sprites, frame, group):
for x in range(len(sprites)):
screen.blit(frame, sprites[x].rect, sprites[x].rect)
sprites[x].image = pygame.transform.scale(sprites[x].image, (272, 272))
group.update()
group.draw(screen)
pygame.display.flip()
background = Frame()
Frame1 = Frame("images\\field1.png", [-20, 0])
Piece1 = Puzzle_piece("images\\piece11.png", coords1)
Piece2 = Puzzle_piece("images\\piece21.png", coords2)
Piece3 = Puzzle_piece("images\\piece31.png", coords3)
Piece4 = Puzzle_piece("images\\piece41.png", coords4)
sprites_group = [Piece1, Piece2, Piece3, Piece4]
Piece_sprites = pygame.sprite.RenderPlain(sprites_group)
create_text(font = "squared_display", dim = 120, msg = "HIDDEN BOYS", position = (width/2, hight/4), blitted = background.frame)
create_text(font = "squared_display", dim = 50, msg = "Click to start", position = (width/2, hight/2), blitted = background.frame)
def move_pieces(piece):
for event in pygame.event.get():
if pygame.mouse.get_pos() in square1:
piece.updates(square1)
piece.move()
if pygame.mouse.get_pos() in square2:
piece.updates(square2)
piece.move()
if pygame.mouse.get_pos() in square3:
piece.updates(square3)
piece.move()
if pygame.mouse.get_pos() in square4:
piece.updates(square4)
piece.move()
screen.blit(background.frame, (0, 0))
pygame.display.flip()
def main():
clock = pygame.time.Clock()
while True:
frame = 0
counter = 0
clock.tick(60)
for event in pygame.event.get():
if event.type == QUIT:
return
if event.type == pygame.MOUSEBUTTONDOWN:
if frame == 0:
blit_frames(Frame1.frame, Frame1.rect, image = Frame1.image, image_rect = Frame1.rect)
draw_sprites(sprites_group, Frame1.frame, Piece_sprites)
frame += 1
elif frame == 1:
if pygame.mouse.get_pos() in coords1:
Piece1.state = "selected"
Piece1.counter += 1
move_pieces(Piece1)
if pygame.mouse.get_pos() in coords2:
Piece2.state = "selected"
Piece2.counter += 1
move_pieces(Piece2)
if pygame.mouse.get_pos() in coords3:
Piece3.state = "selected"
Piece3.counter += 1
move_pieces(Piece3)
if pygame.mouse.get_pos() in coords4:
Piece4.state = "selected"
Piece4.counter += 1
move_pieces(Piece4)
if event.type == pygame.MOUSEBUTTONUP:
if pygame.mouse.get_pos() in coords1 or coords2 or coords3 or coords4:
if Piece1.counter % 2 != 0:
Piece1.state = "unselected"
if Piece2.counter % 2 != 0:
Piece2.state = "unselected"
if Piece3.counter % 2 != 0:
Piece3.state = "unselected"
if Piece4.counter % 2 != 0:
Piece4.state = "unselected"
pygame.display.update()
pygame.display.flip()
if __name__ == '__main__': main()

Your updates method assigns the the tuple position to the rect object. Instead, try:
def updates(self, position):
self.rect.x, self.rect.y = position

Related

How to create button with transparent background and shadow in pygame?

Hi guys I need your help. I want to set opacity of the rectangles which are created by help of class button
this is before class
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Snake')
bg_img = pygame.image.load('Graphics/bg.png')
bg_img = pygame.transform.scale(bg_img,(screen_width,screen_height))
class button():
def __init__(self,text,width,height,pos,elevation,image,color,shadow,hover):
self.image = pygame.transform.scale(image, (int(width), int(height)))
self.rect = self.image.get_rect()
self.elevation = elevation
self.dynamic_elecation = elevation
self.original_y_pos = pos[1]
self.color = color
self.color_shadow = shadow
self.hover = hover
self.clicked = False
self.top_rect = pygame.Rect(pos,(width,height))
self.top_color = color
self.bottom_rect = pygame.Rect(pos,(width,height))
self.bottom_color = shadow
font = pygame.font.SysFont('rockwell', 50)
self.text_surf = font.render(text,True,'#FFFFFF')
self.text_rect = self.text_surf.get_rect(center = self.top_rect.center)
here is function for drawing and also detecting if it was clicked
def draw_button(self):
action = False
pos = pygame.mouse.get_pos()
self.top_rect.y = self.original_y_pos - self.dynamic_elecation
self.text_rect.center = self.top_rect.center
self.bottom_rect.midtop = self.top_rect.midtop
self.bottom_rect.height = self.top_rect.height + self.dynamic_elecation
pygame.draw.rect(screen,self.bottom_color, self.bottom_rect, border_radius = 12)
pygame.draw.rect(screen,self.top_color, self.top_rect, border_radius = 12)
screen.blit(self.text_surf, self.text_rect)
if self.top_rect.collidepoint(pos):
self.top_color = self.color
if pygame.mouse.get_pressed()[0]:
self.dynamic_elecation = 0
self.clicked = True
elif pygame.mouse.get_pressed()[0] == 0 and self.clicked == True:
self.clicked = False
action = True
else:
self.dynamic_elecation = self.elevation
self.top_color = self.hover
else:
# self.dynamic_elecation = self.elevation
self.top_color = self.color
screen.blit(self.image, (self.top_rect))
return action
Here I am creating that button
button_snake = '#191919'
hover_snake = '#999999'
shadow_snake = '#191919'
black = button('',600,180,(100,30),0, menu_img, '#191919', '#191919', '#191919')
red_snake = pygame.image.load('Graphics/snake_r.png').convert_alpha()
In conclusion I want to have another value in class button (self,text,...) and there would be opacity
example
See How to separately change the opacity of a text on a button pygame? and Draw a transparent rectangles and polygons in pygame. You have to draw the rectangle on a transparent pygame.Surface and blit the Surface on the screen. A transparent pygame.Surface can be crate with the pygame.SRCALPHA flag:
top_surf = pygame.Surface(self.top_rect.size, pygame.SRCALPHA)
pygame.draw.rect(top_surf, self.top_color, (0, 0, *self.top_rect.size), border_radius = 12)
screen.blit(top_surf, self.top_rect.topleft)
Coplete example:
import pygame
class Button():
def __init__(self, text, width, height, pos, elevation, image, color, shadow, hover):
#self.image = pygame.transform.scale(image, (int(width), int(height)))
#self.rect = self.image.get_rect()
self.elevation = elevation
self.original_y_pos = pos[1]
self.color = color
self.color_shadow = shadow
self.hover = hover
self.clicked = False
self.top_rect = pygame.Rect(pos,(width,height))
self.top_color = color
self.bottom_rect = pygame.Rect(pos,(width,height))
self.bottom_color = shadow
font = pygame.font.SysFont('rockwell', 50)
self.text_surf = font.render(text,True,'#FFFFFF')
self.text_rect = self.text_surf.get_rect(center = self.top_rect.center)
def draw_button(self, screen):
action = False
pos = pygame.mouse.get_pos()
top_rect = self.top_rect.copy()
bottom_rect = self.bottom_rect.copy()
bottom_rect.x += 20
bottom_rect.y += 20
if top_rect.collidepoint(pos):
self.top_color = self.color
if pygame.mouse.get_pressed()[0]:
self.clicked = True
bottom_rect.inflate_ip(self.elevation, self.elevation)
top_rect.inflate_ip(self.elevation, self.elevation)
elif pygame.mouse.get_pressed()[0] == 0 and self.clicked == True:
self.clicked = False
action = True
self.top_color = self.hover
else:
self.top_color = self.color
bottom_surf = pygame.Surface(bottom_rect.size, pygame.SRCALPHA)
pygame.draw.rect(bottom_surf, self.bottom_color, (0, 0, *bottom_rect.size), border_radius = 12)
screen.blit(bottom_surf, bottom_rect.topleft)
top_surf = pygame.Surface(top_rect.size, pygame.SRCALPHA)
pygame.draw.rect(top_surf, self.top_color, (0, 0, *top_rect.size), border_radius = 12)
screen.blit(top_surf, top_rect.topleft)
screen.blit(self.text_surf, self.text_rect)
return action
pygame.init()
screen = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
background = pygame.Surface(screen.get_size())
ts, w, h, c1, c2 = 50, *screen.get_size(), (128, 128, 128), (96, 96, 96)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
for rect, color in tiles:
pygame.draw.rect(background, color, rect)
font = pygame.font.SysFont(None, 80)
text = font.render("Button", True, (255, 255, 255))
button = Button("Button", 200, 70, (80, 120), 20, None, (128, 128, 255, 128), (64, 64, 128, 128), (255, 128, 255, 128))
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
screen.blit(background, (0, 0))
button.draw_button(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
exit()

How do my make my image (rect) collide with my randomly generated circles to end the game? [duplicate]

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Closed 1 year ago.
I have been trying to solve this for weeks. This is a free-falling pit game, where my character (in this case a chimpanzee png) falls from the top of the screen to the bottom while trying to dodge the random black circles. I have tried so many angles at tackling this, I have tried the standard collision I was taught (pygame.sprite.groupcollide(Group1, Group2, False, True, collided = None) I have tried doing collisions with the colour black only, different formats of spawning my image and all that, and I haven't been able to find anything that works with my code. It has resulted in the code being very messy. I have tried to clean it up for this, but it still might be hard to understand, but if anybody has any solution to this, please let me know as I have been stumped for weeks. I just want the game to close or "game over" when they touch a circle Code:
import sys
import pygame as pg
RED = (255, 0, 0)
GRAY = (150, 150, 150)
GREEN =(34, 177, 76)
BLACK = (0,0,0)
import random
import math
def main():
width, height = 1024, 768
hbox, vbox = 80, 80
w, h = 640, 240
screen = pg.display.set_mode((width, height))
BG = pg.image.load('jungle.jpg').convert()
img = pg.image.load('MONKEY.png')
img = pg.transform.scale(img, (80, 80))
img.convert()
rect = img.get_rect()
rect.center = w//2, h//2
clock = pg.time.Clock()
Score = 0
class Circle(pg.sprite.Sprite):
def __init__(self):
#You can initialise the size to a random value
self.pos = [random.randint(0, 1000), random.randint(180, 600)]
self.color = (0,0, 0)
self.radius = 20
def draw(self):
pg.draw.circle(screen, self.color, (self.pos[0], self.pos[1]), self.radius)
circles = []
for i in range(20):
circles.append(Circle())
def checkIntersection(c1, c2):
dx = c1.pos[0] - c2.pos[0]
dy = c1.pos[1] - c2.pos[1]
d = math.hypot(dx, dy)
if d < c1.radius + c2.radius:
return True
return False
for i in range(19):
while checkIntersection(circles[i], circles[i + 1]):
circles[i].pos = random.randint(0, 1000), random.randint(0, 700)
velocity = (0, 0)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
keys = pg.key.get_pressed()
# booster
move = 8 if keys[pg.K_LSHIFT] else 4
if keys[pg.K_a]: #to move left
rect.x -= move
if rect.x < 0 : rect.x = 0
if keys[pg.K_d]: #to move right
rect.x += move
if rect.x > width-hbox : rect.x = width - hbox
Score += 1
rect.y += 2.5
screen.blit(BG, (0,0))
screen.blit(img,rect)
pg.draw.rect(screen, RED, rect, 1)
pg.draw.polygon(screen, GREEN, ((1024,768), (0,768), (0,640),(1024,640)))
font = pg.font.SysFont("comicsansms", 45)
text = font.render (" " + str(Score), 1, BLACK)
screen.blit(text,(480,700))
pg.event.get()
for circle in circles:
circle.draw()
pg.display.update()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
sys.exit()
Use a "mask" collision. See How can I made a collision mask? and Pygame mask collision
Create a Sprite class with mask (see pygame.mask.from_surface):
class Circle(pg.sprite.Sprite):
def __init__(self):
super().__init__()
self.pos = [random.randint(0, 1000), random.randint(180, 600)]
self.color = (0,0, 0)
self.radius = 20
self.image = pg.Surface((self.radius*2, self.radius*2), pg.SRCALPHA)
pg.draw.circle(self.image , self.color, (self.radius, self.radius), self.radius)
self.rect = self.image.get_rect(center = self.pos)
self.mask = pg.mask.from_surface(self.image)
Create a Sprite class for the player (also with a mask)
class Player(pg.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pg.image.load('MONKEY.png')
self.image = pg.transform.scale(self.image, (80, 80)).convert()
self.rect = self.image.get_rect()
self.rect.center = x, y
self.mask = pg.mask.from_surface(self.image)
Manage the Sprites in pygame.sprite.Group and use pygame.sprite.spritecollide and pygame.sprite.collide_mask() for the collision test:
if pg.sprite.spritecollide(player, circles, False, collided = pg.sprite.collide_mask):
done = True
Complete example:
import sys
import pygame as pg
RED = (255, 0, 0)
GRAY = (150, 150, 150)
GREEN =(34, 177, 76)
BLACK = (0,0,0)
import random
import math
class Circle(pg.sprite.Sprite):
def __init__(self):
super().__init__()
self.pos = [random.randint(0, 1000), random.randint(180, 600)]
self.color = (0,0, 0)
self.radius = 20
self.image = pg.Surface((self.radius*2, self.radius*2), pg.SRCALPHA)
pg.draw.circle(self.image , self.color, (self.radius, self.radius), self.radius)
self.rect = self.image.get_rect(center = self.pos)
self.mask = pg.mask.from_surface(self.image)
class Player(pg.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pg.image.load('MONKEY.png')
self.image = pg.transform.scale(self.image, (80, 80)).convert()
self.rect = self.image.get_rect()
self.rect.center = x, y
self.mask = pg.mask.from_surface(self.image)
def main():
width, height = 1024, 768
hbox, vbox = 80, 80
w, h = 640, 240
screen = pg.display.set_mode((width, height))
BG = pg.image.load('jungle.jpg').convert()
clock = pg.time.Clock()
Score = 0
player = Player(w//2, h//2)
all_sprites = pg.sprite.Group(player)
circles = pg.sprite.Group()
for i in range(20):
circle = Circle()
circles.add(circle)
all_sprites.add(circle)
def checkIntersection(c1, c2):
dx = c1.pos[0] - c2.pos[0]
dy = c1.pos[1] - c2.pos[1]
d = math.hypot(dx, dy)
if d < c1.radius + c2.radius:
return True
return False
c = circles.sprites()
for i in range(19):
while checkIntersection(c[i], c[i + 1]):
c[i].pos = random.randint(0, 1000), random.randint(0, 700)
velocity = (0, 0)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
keys = pg.key.get_pressed()
# booster
move = 8 if keys[pg.K_LSHIFT] else 4
if keys[pg.K_a]: #to move left
player.rect.x -= move
if player.rect.x < 0 : player.rect.x = 0
if keys[pg.K_d]: #to move right
player.rect.x += move
if player.rect.x > width-hbox : player.rect.x = width - hbox
Score += 1
player.rect.y += 2.5
screen.blit(BG, (0,0))
pg.draw.rect(screen, RED, player.rect, 1)
pg.draw.polygon(screen, GREEN, ((1024,768), (0,768), (0,640),(1024,640)))
font = pg.font.SysFont("comicsansms", 45)
text = font.render (" " + str(Score), 1, BLACK)
screen.blit(text,(480,700))
pg.event.get()
all_sprites.draw(screen)
pg.display.update()
clock.tick(30)
if pg.sprite.spritecollide(player, circles, False, collided = pg.sprite.collide_mask):
done = True
if __name__ == '__main__':
pg.init()
main()
pg.quit()
sys.exit()

Change image of character when travelled specific number of pixels

I am making a game in pygame. I want to change the image of the character whenever it moves a certain amount of pixels to make it seem like he's walking, but I can't really understand how to do that. Here's the code:
import pygame
import time
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREY = (129, 129, 129)
frame = 0
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name).convert()
def get_image(self, x, y, width, height, colour):
image = pygame.Surface([width, height]).convert()
image.set_colorkey(colour)
image.blit(self.sprite_sheet, (0, 0), (x, y, width, height))
return image
class Bomb(pygame.sprite.Sprite):
change_x =0
change_y = 0
def __init__(self):
super().__init__()
sprite_sheet = SpriteSheet("Untitled.png")
self.image = sprite_sheet.get_image(2, 2, 48, 48, WHITE)
self.rect = self.image.get_rect()
def move(self, y):
self.rect.y += y
if self.rect.y == 400:
self.kill()
class Soldier(pygame.sprite.Sprite):
def __init__(self):
self.change_x = 0
self.change_y = 0
self.direction = "R"
super().__init__()
self.walking_frames_l = []
self.walking_frames_r = []
sprite_sheet = SpriteSheet("Picture2.png")
self.image = sprite_sheet.get_image(0, 0, 150, 205, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(233, 0, 140, 210, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(425, 5, 123, 210, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(0, 0, 150, 205, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = sprite_sheet.get_image(233, 0, 140, 210, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = sprite_sheet.get_image(425, 5, 123, 210, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = self.walking_frames_r[0]
self.rect = self.image.get_rect()
self.rect.y = 297
self.rect.x = 100
def move(self):
self.rect.x += self.change_x
def walk(self):
global frame
if self.change_x > 0:
frame +=1
time.sleep(.1)
if frame == 3:
frame = 0
self.image = self.walking_frames_r[frame]
def go_left(self):
self.change_x = -6
def go_right(self):
self.change_x = 6
def stop(self):
self.change_x = 0
self.image = self.walking_frames_r[2]
pygame.init()
screen_width = 1000
screen_height = 500
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Game")
clock = pygame.time.Clock()
done = False
bomb = Bomb()
soldier = Soldier()
all_sprites = pygame.sprite.Group()
all_sprites.add(bomb)
all_sprites.add(soldier)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
soldier.go_left()
if event.key == pygame.K_RIGHT:
soldier.go_right()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and soldier.change_x < 0:
soldier.stop()
if event.key == pygame.K_RIGHT and soldier.change_x > 0:
soldier.stop()
screen.fill(RED)
all_sprites.draw(screen)
bomb.move(2)
soldier.move()
soldier.walk()
clock.tick(60)
pygame.display.flip()
pygame.quit()
I also tried to change the image after a particular amount of time (This part):
def walk(self):
global frame
if self.change_x > 0:
frame +=1
time.sleep(.1)
if frame == 3:
frame = 0
self.image = self.walking_frames_r[frame]
When I add time.sleep(.1) and try to move the character, it somehow affects the bomb. It moves 2 pixels, waits for .1 seconds and again moves 2 pixels.
Is there any way I can do either of the things mentioned above (either change the image after a particular amount of time or after a specific amount of pixels travelled)?
Please help. Thanks!
frame has to be an attribute of the Soldier class. Additionally you need an attribute for the number of pixels the player has moved:
class Soldier(pygame.sprite.Sprite):
def __init__(self):
# [...]
self.frame = 0
self.moved = 0
Add the absolute movement to self.moved. Increment frame when the movement exceeds a certain number of pixels (pixel_for_one_step ):
class Soldier(pygame.sprite.Sprite):
# [...]
def walk(self):
self.moved += abs(self.change_x)
pixels_for_one_step = 60
if self.moved > pixels_for_one_step:
self.moved -= pixels_for_one_step
self.frame += 1
if self.frame >= len(self.walking_frames_r):
self.frame = 0
self.image = self.walking_frames_r[self.frame]
Complete example:
import pygame
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREY = (129, 129, 129)
class SpriteSheet(object):
def __init__(self, file_name):
self.sprite_sheet = pygame.image.load(file_name).convert()
def get_image(self, x, y, width, height, colour):
image = pygame.Surface([width, height]).convert()
image.set_colorkey(colour)
image.blit(self.sprite_sheet, (0, 0), (x, y, width, height))
return image
class Bomb(pygame.sprite.Sprite):
change_x =0
change_y = 0
def __init__(self):
super().__init__()
sprite_sheet = SpriteSheet("Untitled.png")
self.image = sprite_sheet.get_image(2, 2, 48, 48, WHITE)
self.rect = self.image.get_rect()
def move(self, y):
self.rect.y += y
if self.rect.y == 400:
self.kill()
class Soldier(pygame.sprite.Sprite):
def __init__(self):
self.change_x = 0
self.change_y = 0
self.direction = "R"
super().__init__()
self.walking_frames_l = []
self.walking_frames_r = []
sprite_sheet = SpriteSheet("Picture2.png")
self.image = sprite_sheet.get_image(0, 0, 150, 205, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(233, 0, 140, 210, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(425, 5, 123, 210, GREY)
self.walking_frames_l.append(self.image)
self.image = sprite_sheet.get_image(0, 0, 150, 205, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = sprite_sheet.get_image(233, 0, 140, 210, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = sprite_sheet.get_image(425, 5, 123, 210, GREY)
self.image = pygame.transform.flip(self.image, True, False)
self.walking_frames_r.append(self.image)
self.image = self.walking_frames_r[0]
self.rect = self.image.get_rect()
self.rect.y = 297
self.rect.x = 100
self.frame = 0
self.moved = 0
def move(self):
self.rect.x += self.change_x
def walk(self):
self.moved += abs(self.change_x)
pixels_for_one_step = 60
if self.moved > pixels_for_one_step:
self.moved -= pixels_for_one_step
self.frame += 1
if self.frame >= len(self.walking_frames_r):
self.frame = 0
self.image = self.walking_frames_r[self.frame]
def go_left(self):
self.change_x = -6
def go_right(self):
self.change_x = 6
def stop(self):
self.change_x = 0
self.image = self.walking_frames_r[2]
pygame.init()
screen_width = 1000
screen_height = 500
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Game")
clock = pygame.time.Clock()
done = False
bomb = Bomb()
soldier = Soldier()
all_sprites = pygame.sprite.Group()
all_sprites.add(bomb)
all_sprites.add(soldier)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
soldier.go_left()
if event.key == pygame.K_RIGHT:
soldier.go_right()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and soldier.change_x < 0:
soldier.stop()
if event.key == pygame.K_RIGHT and soldier.change_x > 0:
soldier.stop()
screen.fill(RED)
all_sprites.draw(screen)
bomb.move(2)
soldier.move()
soldier.walk()
clock.tick(60)
pygame.display.flip()
pygame.quit()

Update one sprite among a group of sprites [Pygame]

First post here. So I am trying to implement a Civilization type of movement game. At the moment, I have one sprite in a cell. I can click it and then if I click another grid, the sprite moves there. What I now want is to spawn 5-6 such sprites, and then do the same thing. Click on a sprite and then click another grid, and that specific sprite moves there without affecting the other sprites. I cannot seem to do that. I can spawn 5-6 random sprites at different grids, but when I click on one of them and then click another grid, all the other sprites are gone. The code is below (not the best as I am learning Pygame). I understand that I have to somehow only update the sprite that was clicked, but I am not sure how to do that.
import pygame
import random
WIDTH = 900
HEIGHT = 700
FPS = 2
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
TURN = "TeamOne"
def main():
# Pygame sprite Example
global x_lines
global y_lines
x_lines = [WIDTH-i*WIDTH/20 for i in range(20,0, -1)]
y_lines = [HEIGHT-j*HEIGHT/20 for j in range(20,0, -1)]
class TeamOne(pygame.sprite.Sprite):
# sprite for the Player
def __init__(self):
# this line is required to properly create the sprite
pygame.sprite.Sprite.__init__(self)
# create a plain rectangle for the sprite image
self.image = pygame.Surface((WIDTH / 20, HEIGHT / 20))
self.image.fill(GREEN)
# find the rectangle that encloses the image
self.rect = self.image.get_rect()
# center the sprite on the screen
self.rect.center = ((random.randint(1,19)*2+1)* WIDTH/ 40, (random.randint(1,19)*2+1)*HEIGHT/40)
def update(self, position):
# any code here will happen every time the game loop updates
(a, b) = position
for index, i in enumerate(x_lines):
if i > a:
self.rect.x = x_lines[index-1]
break
for index, j in enumerate(y_lines):
if j > b:
self.rect.y = y_lines[index-1]
break
# initialize pygame and create window
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("A Game")
clock = pygame.time.Clock()
clicked_sprites = pygame.sprite.Group()
teamone_sprites = pygame.sprite.Group()
for i in range(5):
mob1 = TeamOne()
teamone_sprites.add(mob1)
# Game loop
running = True
j=0
while running:
# keep loop running at the right speed
clock.tick(FPS)
# Process input (events)
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and j == 0:
pos = pygame.mouse.get_pos()
for s in teamone_sprites:
if s.rect.collidepoint(pos):
#teamone_sprites.add(s)
clicked_sprites.add(s)
print (clicked_sprites)
j = 1
elif event.type == pygame.MOUSEBUTTONDOWN and j == 1:
new_pos = pygame.mouse.get_pos()
#teamone_sprites.update(new_pos)
clicked_sprites.update(new_pos)
j = 0
# Update
# Draw / render
## screen.fill(BLACK)
## draw_grid(screen)
##
## teamone_sprites.draw(screen)
##
##
##
## # *after* drawing everything, flip the display
## pygame.display.flip()
# Draw / render
screen.fill(BLACK)
draw_grid(screen)
teamone_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
def draw_grid(screen):
for i in range(1, HEIGHT, int(HEIGHT/20)):
pygame.draw.line(screen, GREEN, (1,i) ,(WIDTH,i), 2)
for j in range(1, WIDTH, int(WIDTH/20)):
pygame.draw.line(screen, GREEN, (j,1) ,(j,HEIGHT), 2)
if __name__ == '__main__':
main()
Some tips for you:
Keep your main loop clean
Put logic where it belongs
Only call pygame.display.flip()/pygame.display.update() once
Don't use variable names like j
Since your game is grid based, you should have a way to translate between grid coordinates and screen coordinates
Here's a simple runnable example I hacked together (see the comments for some explanations):
import pygame
import random
WIDTH = 900
HEIGHT = 700
ROWS = 20
COLUMNS = 20
TILE_SIZE = WIDTH / COLUMNS, HEIGHT / ROWS
TILE_W, TILE_H = TILE_SIZE
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
TURN = "TeamOne"
# some functions to translate grid <-> screen coordinates
def posToScreen(pos):
column, row = pos
return column * TILE_W, row * TILE_H
def screenToPos(pos):
column, row = pos
return column / TILE_W, row / TILE_H
def draw_grid(screen):
for i in range(1, HEIGHT, TILE_H):
pygame.draw.line(screen, GREEN, (1,i) ,(WIDTH,i), 2)
for j in range(1, WIDTH, TILE_W):
pygame.draw.line(screen, GREEN, (j,1) ,(j,HEIGHT), 2)
# a class that handles selecting units
class Cursor(pygame.sprite.Sprite):
def __init__(self, units, *groups):
pygame.sprite.Sprite.__init__(self, *groups)
# group of the units that can be controlled
self.units = units
# we create two images
# to indicate if we are selecting or moving
self.image = pygame.Surface(TILE_SIZE)
self.image.set_colorkey((43,43,43))
self.image.fill((43,43,43))
self.rect = self.image.get_rect()
self.selected_image = self.image.copy()
pygame.draw.rect(self.image, pygame.Color('red'), self.image.get_rect(), 4)
pygame.draw.rect(self.selected_image, pygame.Color('purple'), self.image.get_rect(), 4)
self.base_image = self.image
self.selected = None
def update(self):
# let's draw the rect on the grid, based on the mouse position
pos = pygame.mouse.get_pos()
self.rect.topleft = posToScreen(screenToPos(pos))
def handle_click(self, pos):
if not self.selected:
# if we have not selected a unit, do it now
for s in pygame.sprite.spritecollide(self, self.units, False):
self.selected = s
self.image = self.selected_image
else:
# if we have a unit selected, just set its target attribute, so it will move on its own
self.selected.target = posToScreen(screenToPos(pos))
self.image = self.base_image
self.selected = None
class TeamOne(pygame.sprite.Sprite):
def __init__(self, *groups):
pygame.sprite.Sprite.__init__(self, *groups)
self.image = pygame.Surface(TILE_SIZE)
self.image.fill(GREEN)
self.pos = random.randint(0, COLUMNS), random.randint(0, ROWS)
self.rect = self.image.get_rect(topleft = posToScreen(self.pos))
self.target = None
def update(self):
# do nothing until target is set
# (maybe unset it if we reached our target)
if self.target:
if self.rect.x < self.target[0]:
self.rect.move_ip(1, 0)
elif self.rect.x > self.target[0]:
self.rect.move_ip(-1, 0)
elif self.rect.y < self.target[1]:
self.rect.move_ip(0, 1)
elif self.rect.y > self.target[1]:
self.rect.move_ip(0, -1)
self.pos = screenToPos(self.rect.topleft)
def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("A Game")
clock = pygame.time.Clock()
all_sprites = pygame.sprite.LayeredUpdates()
team_ones = pygame.sprite.Group()
for i in range(5):
TeamOne(all_sprites, team_ones)
cursor = Cursor(team_ones, all_sprites)
# a nice, simple, clean main loop
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# we could also pass all events to all sprites
# so we would not need this special clause for the cursor...
if event.type == pygame.MOUSEBUTTONDOWN:
cursor.handle_click(event.pos)
all_sprites.update()
screen.fill(BLACK)
draw_grid(screen)
all_sprites.draw(screen)
pygame.display.flip()
if __name__ == '__main__':
main()
I have pretty much the same Problem i have a healthbar for my enemie but i want all enemys to have one so its a spritegroup now if i want to change an attribute of one object out of my spritegroup i dont know how to properly access it. The Problem lays in the Healthbaranimation function. I tried self.healthbar.sprites() self.healthbar.sprites and spritedict nothing really semms to work. Is there an easy way to fix this? P.s sorry for my bad code It is my first real attempt making a small game
from os import path
import pygame
from elements.ammo import AMMO
from elements.bigenemy import BIGENEMY
from elements.enemy import ENEMY
from elements.player import PLAYER
from .base import BaseState
from elements.healthbar import HEALTHBAR
class Gameplay(BaseState):
def __init__(self):
super(Gameplay, self).__init__()
self.next_state = "GAME_OVER"
self.x, self.y = 100, 1030
self.playersprite = PLAYER((self.x, self.y))
self.bigenemy = pygame.sprite.GroupSingle(BIGENEMY())
self.bottomrect = pygame.Rect((0, 1030), (1920, 50))
self.enemysprite = ENEMY()
self.ammosprite = AMMO()
self.healthbar = pygame.sprite.Group(HEALTHBAR())
self.displayedimage = self.playersprite.image
self.displayedrect = self.playersprite.rect
self.highscore = self.load_data()
self.points = 0
self.scoretext = f"SCORE: {self.points}"
self.scoresurf = self.font.render(self.scoretext, True, "red")
self.nhstext = "NEW HIGHSCORE!"
self.nhssurf = self.font.render(self.nhstext, True, "red")
self.ammotext = f"AMMO:{self.playersprite.ammunition}"
self.ammosurf = self.font.render(self.ammotext, True, "red")
self.bulletgroup = pygame.sprite.Group()
self.time_active = 0
self.bigenemyexisting = True
def get_event(self, event):
if event.type == pygame.QUIT:
self.quit = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LCTRL:
self.playersprite.crouching = True
elif event.key == pygame.K_SPACE:
self.playersprite.jumping = True
elif event.key == pygame.K_q and self.playersprite.ammunition != 0:
self.playersprite.shooting = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_ESCAPE:
self.done = True
elif event.key == pygame.K_LCTRL:
self.playersprite.crouching = False
elif event.key == pygame.K_q:
self.playersprite.shooting = False
def draw(self, surface):
surface.fill(pygame.Color("black"))
pygame.draw.rect(surface, "red", self.bottomrect)
surface.blit(self.displayedimage, (self.displayedrect))
surface.blit(self.enemysprite.image, (self.enemysprite.rect))
surface.blit(self.ammosprite.image, (self.ammosprite.rect))
self.healthbar.draw(surface)
self.bigenemy.draw(surface)
self.bulletgroup.draw(surface)
surface.blit(self.scoresurf, (0, 0))
surface.blit(self.ammosurf, (0, 1000))
if self.points > self.highscore: surface.blit(self.nhssurf, (1920 / 2 - 100, 1080 / 2))
def lost(self):
self.enemysprite.startposx = 1920
self.enemysprite.startposy = self.enemysprite.gettypeenemy()
self.enemysprite.speed = 10
self.highscorefunc()
self.points = 0
self.playersprite.ammunition = 30
def collidecheck(self):
self.playermask = pygame.mask.from_surface(self.displayedimage)
self.enemymask = pygame.mask.from_surface(self.enemysprite.image)
offsetx = self.enemysprite.rect.left - self.displayedrect.left
offsety = self.enemysprite.rect.top - self.displayedrect.top
if self.displayedrect.colliderect(self.enemysprite.rect):
if self.playermask.overlap(self.enemymask, (offsetx, offsety)):
self.lost()
self.done = True
elif self.enemysprite.rect.x < 0 and self.enemysprite.speed < 25:
self.points += 1
self.enemysprite.speed += 1
elif self.enemysprite.speed > 25:
self.enemysprite.speed += .5
elif self.displayedrect.colliderect(self.ammosprite.rect):
self.ammosprite.startposx = 2300
self.playersprite.ammunition += 30
elif pygame.sprite.groupcollide(self.bigenemy,self.bulletgroup,False,True):
self.bigenemy.sprite.health -= 10
def shooting(self, dt):
if self.playersprite.ammunition != 0:
if self.playersprite.shooting and not self.playersprite.jumping and not self.playersprite.crouching:
self.time_active += dt
if self.time_active >= 100:
self.bulletgroup.add(self.playersprite.createbullet())
self.time_active = 0
self.playersprite.ammunition -= 1
else:
self.playersprite.shooting = False
def highscorefunc(self):
if self.points > self.highscore:
self.highscore = self.points
with open(path.join(self.dir, self.HS_FILE), 'w') as f:
f.write(str(self.highscore))
def animation(self):
if not self.playersprite.shooting and not self.playersprite.jumping and not self.playersprite.crouching:
if self.playersprite.index >= len(self.playersprite.basicanimation):
self.playersprite.index = 0
self.displayedimage = self.playersprite.basicanimation[int(self.playersprite.index)]
self.playersprite.index += .1
elif self.playersprite.shooting and not self.playersprite.jumping:
if self.playersprite.index >= len(self.playersprite.shootanimation):
self.playersprite.index = 0
self.displayedimage = self.playersprite.shootanimation[int(self.playersprite.index)]
self.playersprite.index += .1
elif self.playersprite.jumping:
self.displayedimage = self.playersprite.imagejump
elif self.playersprite.crouching:
self.displayedimage = self.playersprite.slidingimage
def healthbaranimation(self):
if self.bigenemy.sprite.health < 90:
self.healthbar.spritedict.index = 1
if self.bigenemy.sprite.health < 80:
self.healthbar.sprite.index = 2
if self.bigenemy.sprite.health < 70:
self.healthbar.sprite.index = 3
if self.bigenemy.sprite.health < 60:
self.healthbar.sprite.index = 4
if self.bigenemy.sprite.health < 50:
self.healthbar.sprite.index = 5
if self.bigenemy.sprite.health < 40:
self.healthbar.sprite.index = 6
if self.bigenemy.sprite.health < 30:
self.healthbar.sprite.index = 7
if self.bigenemy.sprite.health < 20:
self.healthbar.sprite.index = 8
if self.bigenemy.sprite.health < 10:
self.healthbar.sprite.index = 9
def spawnbigenemies(self):
if self.bigenemyexisting:
if self.bigenemy.sprite.health < 3:
self.bigenemy.add(BIGENEMY())
self.bigenemyexisting = True
def update(self, dt):
try:
self.bigenemy.sprite.update()
except:
pass
self.healthbaranimation()
self.healthbar.update()
self.playersprite.jump()
self.animation()
self.shooting(dt)
self.bulletgroup.update()
self.enemysprite.update()
self.ammosprite.update()
self.collidecheck()
self.spawnbigenemies()
self.scoretext = f"SCORE: {self.points}"
self.scoresurf = self.font.render(self.scoretext, True, "black")
self.ammotext = f"AMMO:{self.playersprite.ammunition}"
self.ammosurf = self.font.render(self.ammotext, True, "red")

Display Surface quit error when quitting

I made a pygame program what is working fine, but when I try to quit it, error occurs: pygame.error: display Surface quit, and show the code part: DS.blit(bg, (back_x - bg.get_rect().width, 0)). I use quit() command in my events and also at the end of the loop. Can't figure out where is the problem.
import pygame, os, random
pygame.init()
pygame.mixer.init()
W, H = 800,600
HW, HH = W/2,H/2
WHITE = (255,255,255)
PURPLE = (139,34,82)
FPS = 60
DS = pygame.display.set_mode((800, 600))
pygame.display.set_caption('Purpleman')
clock = pygame.time.Clock()
#Allalaadimised
bg = pygame.image.load(os.path.join('Pildid', 'Taust3.png'))
bg = pygame.transform.scale(bg, (2000, 600))
startscreen = pygame.image.load(os.path.join('Pildid', 'Start.png'))
startscreen = pygame.transform.scale(startscreen, (800, 600))
endscreen = pygame.image.load(os.path.join('Pildid', 'dead.png'))
endscreen = pygame.transform.scale(endscreen, (800, 600))
PLAYER_SHEET = pygame.image.load(os.path.join('Pildid', 'karakter.png')).convert_alpha()
menuu = pygame.mixer.Sound(os.path.join('Helid', 'Taust_laul.ogg'))
ohno = pygame.mixer.Sound(os.path.join('Helid', 'ohno.ogg'))
sad = pygame.mixer.Sound(os.path.join('Helid', 'sad.ogg'))
pygame.mixer.music.load(os.path.join('Helid', 'taustalaul.ogg'))
pygame.display.set_icon(bg)
# Sprite sheeti loikamine ja lisamine listi
PLAYER_IMAGES = []
width = PLAYER_SHEET.get_width() / 4
height = PLAYER_SHEET.get_height()
for x in range(4):
PLAYER_IMAGES.append(PLAYER_SHEET.subsurface(x*width, 0, width, height))
class Player(pygame.sprite.Sprite):
'''Mangija'''
def __init__(self, x, y, py):
super(Player,self).__init__()
self.x = x
self.y = y
self.jumping = False
self.platform_y = py
self.velocity_index = 0
self.velocity = list([(i/ 1.5)-25 for i in range (0,60)]) #huppe ulatus ja kiirus
self.frame_index = 0
self.image = PLAYER_IMAGES[self.frame_index] #kaadri valimine
self.rect = self.image.get_rect()
self.mask = pygame.mask.from_surface(self.image) #hitbox
def do_jump(self):
'''Huppemehaanika'''
if self.jumping:
self.y += self.velocity[self.velocity_index]
self.velocity_index += 2
if self.velocity_index >= len(self.velocity) - 1: #huppe aeglustus (nagu gravitatsioon)
self.velocity_index = len(self.velocity) - 1
if self.y > self.platform_y: #platvormi tagades ei huppa
self.y = self.platform_y
self.jumping = False
self.velocity_index = 0
def update(self):
'''Kaadrite vahetus ja huppamine'''
self.rect.center = self.x, self.y
self.do_jump()
# Animatsiooni kaadri uuendamine.
self.frame_index += 1
self.frame_index %= len(PLAYER_IMAGES) * 7
# Pildi vahetamine.
self.image = PLAYER_IMAGES[self.frame_index//7]
def keys(player):
'''Mangija inputi saamine'''
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] or keys[pygame.K_UP] and player.jumping == False:
player.jumping = True
class Obstacle(pygame.sprite.Sprite):
'''Mangu takistused'''
def __init__(self, x, y):
super(Obstacle,self).__init__()
self.image = pygame.image.load(os.path.join('Pildid', 'kivi.png')).convert_alpha()
self.image = pygame.transform.scale(self.image, (90,90))
self.rect = self.image.get_rect(center=(x, y))
self.x = x
self.y = y
self.mask = pygame.mask.from_surface(self.image)
def update(self):
'''Takistuse kustutamine'''
if self.x < -64:
self.kill()
self.x += speed
self.rect.center = self.x, self.y
class Scoring():
'''Punktide lugemine ja menuud'''
def __init__(self):
with open('highscore.txt', 'w') as f: #high score salvestamine
try:
self.highscore = int(f.read())
except:
self.highscore = 0
def score(self,points):
self.font = pygame.font.Font('freesansbold.ttf',30)
self.text = self.font.render('Score: ' + str(points) , True, PURPLE)
DS.blit(self.text, (0,0))
def text_objects(self,text, font):
self.textSurface = font.render(text, True, PURPLE)
return self.textSurface, self.textSurface.get_rect()
def message_display(self,text):
self.largeText = pygame.font.Font('freesansbold.ttf',60)
self.TextSurf, self.TextRect = self.text_objects(text, self.largeText)
self.TextRect.center = ((W/2),(H/4))
DS.blit(self.TextSurf, self.TextRect)
pygame.display.update()
self.waiting = True
def startscreen(self):
'''Algusaken'''
menuu.play(-1)
DS.blit(startscreen, [0,0])
self.draw_text('Purpleman', 48, PURPLE, W/2, H/4)
self.draw_text('Space to jump', 22, PURPLE, W/2, H*3/7)
self.draw_text('Press key to play', 22, PURPLE, W/2, H*5/9)
self.draw_text('High score: ' + str(self.highscore), 22, PURPLE, W/2, 15)
self.draw_text('All made by TaaviR', 14, WHITE, W/2, 570)
pygame.display.update()
self.wait_for_key()
def pause_endscreen(self):
'''Lopuaken'''
sad.play()
DS.blit(endscreen, [0,0])
self.draw_text('GAME OVER', 48, PURPLE, W/2, H/4)
self.draw_text('You ran ' + str(points), 22, PURPLE, W/2, H/2)
self.draw_text('Press key to play again', 22, WHITE, W/2, H*5/6)
if points > self.highscore: #high score mehhanism
self.highscore = points
self.draw_text('NEW HIGH SCORE!', 22, PURPLE, W/2, H/2 + 40)
with open('highscore.txt', 'w') as f:
f.write(str(points))
else:
self.draw_text('Highscore ' + str(self.highscore), 22, PURPLE, W/2, H/2 + 40)
pygame.display.update()
self.wait_for_key()
self.waiting = True
def wait_for_key(self):
'''Mangija input menuu jaoks'''
self.waiting = True
while self.waiting:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
self.waiting = False
pygame.mixer.quit()
elif event.type == pygame.KEYUP:
self.waiting = False
menuu.stop()
pygame.mixer.music.play(-1)
sad.stop()
def draw_text(self,text, size, color, x, y):
self.font = pygame.font.Font('freesansbold.ttf', size)
self.text_surface = self.font.render(text, True, color)
self.text_rect = self.text_surface.get_rect()
self.text_rect.midtop = (x, y)
DS.blit(self.text_surface, self.text_rect)
def crash(self):
self.message_display('Purpleman got hurt')
self.waiting = True
def background():
'''Liikuv taust'''
back_x = x % bg.get_rect().width
# ---Draw everything.---
DS.blit(bg, (back_x - bg.get_rect().width, 0))
if back_x < W:
DS.blit(bg, (back_x, 0))
pygame.time.set_timer(pygame.USEREVENT+2, random.choice([2500, 3000, 1500,1000])) #valjastamaks suvaliselt takistusi
#klassid
obstacle = Obstacle(832, 412)
player = Player(190, 359, 359)
#sprite grupid
all_sprites = pygame.sprite.Group(player, obstacle)
obstacles = pygame.sprite.Group(obstacle)
#vajalikud vaartused
index = 3
points = 0
x = 0
x -= 1
speed = -5
start = Scoring()
start.startscreen()
pygame.mixer.music.play(-1)
running = True
while running:
# ---Mangumootor.---
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.mixer.quit()
pygame.quit()
elif event.type == pygame.USEREVENT+2:
r = random.randrange(0, 2)
if r == 0:
obstacle = Obstacle(832, 412)
# Lisamaks takistuse gruppidesse
obstacles.add(obstacle)
all_sprites.add(obstacle)
# ---Mangu loogika---
all_sprites.update()
collided = pygame.sprite.spritecollide(player, obstacles, True, pygame.sprite.collide_mask) #kokkupuutumine
if collided:
ohno.play()
pygame.mixer.music.stop()
start.crash()
pygame.time.delay(3000)
pygame.event.clear()
obstacles.empty()
start.pause_endscreen()
points = 0
speed = -5
else:
points += 1
#vajalikud vaartused
index += 1
x -= 2
speed += -0.008
#funktsioonid
background()
start.score(points)
all_sprites.draw(DS)
keys(player)
pygame.display.update()
clock.tick(60)
pygame.mixer.quit()
pygame.quit()
Don't call pygame.mixer.quit() and pygame.quit() in the event loop when a pygame.QUIT event occurs. When you call pygame.quit(), you can't use some pygame functions like pygame.display.update anymore because all modules have been uninitialized, and since the while loop is still running, this exception gets raised.
So just remove the pygame.quit and pygame.mixer.quit() in the event loop and call them at the end of the program (as you already do).
Actually, you don't even have to call these functions and can just let the program finish as any other program. I think pygame.quit is only needed to close the window if you run your game with the IDLE IDE (and maybe with other tkinter based applications).

Categories

Resources