check for multiple collisions at sprites in pygame - python

I am currently working with pygame, and I want to create multiple sprites and check for at least two collisions. I came up with the idea of having two while - loops but it ended up being really complicated. Is there any other way I could try it?

Use pygame.sprite.spritecollide to get a list of the sprites that collide with the player, then loop over this list to do something with the collided sprites.
There's also groupcollide which you can use to detect collisions between two sprite groups. It returns a dictionary with sprites of group 1 as the keys and the collided sprites of group 2 as the values.
import sys
import pygame as pg
from pygame.math import Vector2
class Player(pg.sprite.Sprite):
def __init__(self, pos, *groups):
super().__init__(*groups)
self.image = pg.Surface((120, 60))
self.image.fill(pg.Color('dodgerblue'))
self.rect = self.image.get_rect(center=pos)
class Enemy(pg.sprite.Sprite):
def __init__(self, pos, *groups):
super().__init__(*groups)
self.image = pg.Surface((120, 60))
self.image.fill(pg.Color('sienna1'))
self.rect = self.image.get_rect(center=pos)
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
all_sprites = pg.sprite.Group()
enemy_group = pg.sprite.Group(Enemy((200, 250)), Enemy((350, 250)))
all_sprites.add(enemy_group)
player = Player((100, 300), all_sprites)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.MOUSEMOTION:
player.rect.center = event.pos
all_sprites.update()
# Check which enemies collided with the player.
# spritecollide returns a list of the collided sprites.
collided_enemies = pg.sprite.spritecollide(player, enemy_group, False)
screen.fill((30, 30, 30))
all_sprites.draw(screen)
for enemy in collided_enemies:
# Draw rects around the collided enemies.
pg.draw.rect(screen, (0, 190, 120), enemy.rect, 4)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
sys.exit()

Related

How to make the bird fall [duplicate]

I am trying to make objects fall like they would on earth. I already got them to blit where I wanted them to but I can't seem to animate them.
This is the object that I want to fall
import pygame
class circle():
def __init__(self, screen):
planet_color = (255,0,0)
planet_radius = 20
self.screen = screen
ev = pygame.event.get()
self.image = pygame.image.load('../images/jupiter.bmp')
self.image = pygame.transform.scale(self.image, (80, 80))
def blitme(self):
self.x = pygame.mouse.get_pos()
self.rect = self.image.get_rect()
self.rect.center = self.x
self.screen.blit(self.image, self.rect)
And this is the code that runs it. When the mouse is clicked a little picture of Jupiter is made where the mouse was clicked. How do I get this image to fall?
import pygame
import gravfunc as gf
from gravfunc import circle
import sys
def run_game():
screen_height = 670
screen_width = 1270
pygame.init()
screen = pygame.display.set_mode((screen_width, screen_height))
screen.fill((10,10,30))
running = True
circ = circle(screen)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
circ.blitme()
pygame.display.flip()
run_game()
Give your class a self.speed_y attribute and add the GRAVITY to it each frame to accelerate the object. I've also added a self.pos_y attribute because pygame.Rects can't have floating point numbers as their coordinates. So,
increase the speed
add the speed to the position (self.pos_y)
assign the self.pos_y to self.rect.y.
Since you are already using a class, I recommend to make it a pygame sprite subclass (inherit from pygame.sprite.Sprite). Then you can add all circles to a pygame.sprite.Group and update and draw them by calling sprite_group.update() and sprite_grop.draw(screen).
import pygame
GRAVITY = .2 # Pretty low gravity.
class Circle(pygame.sprite.Sprite):
def __init__(self, pos, screen):
super().__init__()
self.screen = screen
self.image = pygame.Surface((80, 80), pygame.SRCALPHA)
pygame.draw.circle(self.image, (30, 90, 150), (40, 40), 40)
self.rect = self.image.get_rect(center=pos)
self.pos_y = pos[1]
self.speed_y = 0
def update(self):
self.speed_y += GRAVITY
self.pos_y += self.speed_y
self.rect.y = self.pos_y
if self.pos_y > self.screen.get_height():
self.kill() # Remove off-screen circles.
def run_game():
pygame.init()
screen = pygame.display.set_mode((1270, 670))
clock = pygame.time.Clock()
running = True
circles = pygame.sprite.Group(Circle((600, 0), screen))
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEBUTTONDOWN:
circles.add(Circle(event.pos, screen))
circles.update()
screen.fill((10, 10, 30))
circles.draw(screen)
pygame.display.flip()
clock.tick(60)
run_game()
pygame.quit()

Pygame character movement

I'm practicing with pygame and don't know how to make my character move. If I put 'print' statement, it works, and prints whatever I want when I press 'a' for example, but character stays on his place. I know little about classes, so I think that's the problem
import pygame
pygame.init()
pygame.font.init()
width, height = 924, 500
screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Priest Beast')
clock = pygame.time.Clock()
BG = pygame.transform.scale2x(pygame.image.load('art/background.png')).convert_alpha()
music = pygame.mixer.Sound('sound/music.mp3')
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.transform.scale2x(pygame.image.load('art/Player.png')).convert_alpha()
self.rect = self.image.get_rect(center = (800, 300))
self.x = x
self.y = y
def move(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
self.rect.x += 5
def update(self):
self.move()
#Loop and exit
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# Sounds
music.play()
music.set_volume(0.1)
screen.blit(BG, (0, 0))
player = pygame.sprite.GroupSingle()
player.add(Player(800,200))
#Update everything
player.draw(screen)
player.update()
pygame.display.update()
clock.tick(60)
You continuously recreate the object in its initial position. You need to create the Sprite and Group before the application loop:
player = pygame.sprite.GroupSingle() # <-- INSERT
player.add(Player(800,200))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
# [...]
screen.blit(BG, (0, 0))
# DELETE
# player = pygame.sprite.GroupSingle()
# player.add(Player(800,200))
# [...]

How to put pygame functions into a function? [duplicate]

I am following a video about pygame and I saw this code
crosshair = pygame.sprite.Group()
Could someone explain me this?
Read the documentation of pygame.sprite.Group.
pygame.sprite.Group.update() and pygame.sprite.Group.draw() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update method of the contained pygame.sprite.Sprites - you have to implement the method.
pygame.sprite.Group.update()
Calls the update() method on all Sprites in the Group.
The later uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects - you have to ensure that the pygame.sprite.Sprites have the required attributes
pygame.sprite.Group.draw()
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect for the position.
The Sprites in the Groups can be removed and thus destroyed by calling pygame.sprite.Sprite.kill. When the object is no longer referenced, it is destroyed:
The Sprite is removed from all the Groups that contain it. This won't change anything about the state of the Sprite. It is possible to continue to use the Sprite after this method has been called, including adding it to Groups.
See also Sprite Groups
Minimal example:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((40, 40))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect(center = center_pos)
class Bullet(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((20, 10))
self.image.fill((0, 255, 255))
self.rect = self.image.get_rect(center = center_pos)
def update(self):
self.rect.x += 10
if self.rect.right > 300:
self.kill()
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
player = Player((25, window.get_height() // 2))
all_sprites = pygame.sprite.Group(player)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
all_sprites.add(Bullet(player.rect.center))
all_sprites.update()
print(len(all_sprites))
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), (300, 0, 10, window.get_height()))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()

Why are these targets reappearing after my function deletes them from the list? [duplicate]

I am following a video about pygame and I saw this code
crosshair = pygame.sprite.Group()
Could someone explain me this?
Read the documentation of pygame.sprite.Group.
pygame.sprite.Group.update() and pygame.sprite.Group.draw() are methods which are provided by pygame.sprite.Group.
The former delegates the to the update method of the contained pygame.sprite.Sprites - you have to implement the method.
pygame.sprite.Group.update()
Calls the update() method on all Sprites in the Group.
The later uses the image and rect attributes of the contained pygame.sprite.Sprites to draw the objects - you have to ensure that the pygame.sprite.Sprites have the required attributes
pygame.sprite.Group.draw()
Draws the contained Sprites to the Surface argument. This uses the Sprite.image attribute for the source surface, and Sprite.rect for the position.
The Sprites in the Groups can be removed and thus destroyed by calling pygame.sprite.Sprite.kill. When the object is no longer referenced, it is destroyed:
The Sprite is removed from all the Groups that contain it. This won't change anything about the state of the Sprite. It is possible to continue to use the Sprite after this method has been called, including adding it to Groups.
See also Sprite Groups
Minimal example:
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((40, 40))
self.image.fill((255, 255, 0))
self.rect = self.image.get_rect(center = center_pos)
class Bullet(pygame.sprite.Sprite):
def __init__(self, center_pos):
super().__init__()
self.image = pygame.Surface((20, 10))
self.image.fill((0, 255, 255))
self.rect = self.image.get_rect(center = center_pos)
def update(self):
self.rect.x += 10
if self.rect.right > 300:
self.kill()
pygame.init()
window = pygame.display.set_mode((400, 300))
clock = pygame.time.Clock()
player = Player((25, window.get_height() // 2))
all_sprites = pygame.sprite.Group(player)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
all_sprites.add(Bullet(player.rect.center))
all_sprites.update()
print(len(all_sprites))
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), (300, 0, 10, window.get_height()))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()

Pygame: How do I make my image fall?

I am trying to make objects fall like they would on earth. I already got them to blit where I wanted them to but I can't seem to animate them.
This is the object that I want to fall
import pygame
class circle():
def __init__(self, screen):
planet_color = (255,0,0)
planet_radius = 20
self.screen = screen
ev = pygame.event.get()
self.image = pygame.image.load('../images/jupiter.bmp')
self.image = pygame.transform.scale(self.image, (80, 80))
def blitme(self):
self.x = pygame.mouse.get_pos()
self.rect = self.image.get_rect()
self.rect.center = self.x
self.screen.blit(self.image, self.rect)
And this is the code that runs it. When the mouse is clicked a little picture of Jupiter is made where the mouse was clicked. How do I get this image to fall?
import pygame
import gravfunc as gf
from gravfunc import circle
import sys
def run_game():
screen_height = 670
screen_width = 1270
pygame.init()
screen = pygame.display.set_mode((screen_width, screen_height))
screen.fill((10,10,30))
running = True
circ = circle(screen)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
circ.blitme()
pygame.display.flip()
run_game()
Give your class a self.speed_y attribute and add the GRAVITY to it each frame to accelerate the object. I've also added a self.pos_y attribute because pygame.Rects can't have floating point numbers as their coordinates. So,
increase the speed
add the speed to the position (self.pos_y)
assign the self.pos_y to self.rect.y.
Since you are already using a class, I recommend to make it a pygame sprite subclass (inherit from pygame.sprite.Sprite). Then you can add all circles to a pygame.sprite.Group and update and draw them by calling sprite_group.update() and sprite_grop.draw(screen).
import pygame
GRAVITY = .2 # Pretty low gravity.
class Circle(pygame.sprite.Sprite):
def __init__(self, pos, screen):
super().__init__()
self.screen = screen
self.image = pygame.Surface((80, 80), pygame.SRCALPHA)
pygame.draw.circle(self.image, (30, 90, 150), (40, 40), 40)
self.rect = self.image.get_rect(center=pos)
self.pos_y = pos[1]
self.speed_y = 0
def update(self):
self.speed_y += GRAVITY
self.pos_y += self.speed_y
self.rect.y = self.pos_y
if self.pos_y > self.screen.get_height():
self.kill() # Remove off-screen circles.
def run_game():
pygame.init()
screen = pygame.display.set_mode((1270, 670))
clock = pygame.time.Clock()
running = True
circles = pygame.sprite.Group(Circle((600, 0), screen))
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
elif event.type == pygame.MOUSEBUTTONDOWN:
circles.add(Circle(event.pos, screen))
circles.update()
screen.fill((10, 10, 30))
circles.draw(screen)
pygame.display.flip()
clock.tick(60)
run_game()
pygame.quit()

Categories