I'm trying to get proper collision detection with rotating surfaces in pygame. I decided to try using masks. It somewhat works, but it is not as precise as I'd liked/thought. I tried updating the mask at the end of the cycle to get a "fresh" hitbox for the next frame, but it didn't work as expected. What is my mistake?
import pygame
import random
WHITE = [255, 255, 255]
RED = [255, 0, 0]
pygame.init()
FPS = pygame.time.Clock()
fps = 6
winW = 1000
winH = 500
BGCOLOR = WHITE
win = pygame.display.set_mode((winW, winH))
win.fill(WHITE)
pygame.display.set_caption('')
pygame.display.set_icon(win)
class Box(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([w, h], pygame.SRCALPHA)
self.image.fill(random_color())
self.mask = pygame.mask.from_surface(self.image)
self.rect = pygame.Rect(x, y, w, h)
self.angle = 0
def move(self):
self.rect.center = pygame.mouse.get_pos()
def draw(self):
blits = self.rotate()
win.blit(blits[0], blits[1])
self.mask = pygame.mask.from_surface(blits[0])
def rotate(self):
self.angle += 3
new_img = pygame.transform.rotate(self.image, self.angle)
new_rect = new_img.get_rect(center=self.rect.center)
return new_img, new_rect
def update_display():
win.fill(BGCOLOR)
player.draw()
for p in platforms:
p.draw()
pygame.display.update()
def collision():
return pygame.sprite.spritecollide(player, plat_collide, False, pygame.sprite.collide_mask)
def random_color():
return [random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)]
player = Box(100, 400, 50, 50)
platforms = [Box(300, 400, 100, 50)]
plat_collide = pygame.sprite.Group(platforms)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
hits = collision()
if hits:
BGCOLOR = RED
else:
BGCOLOR = WHITE
player.move()
update_display()
FPS.tick(fps)
pygame.quit()
Your application works fine. But note, pygame.sprite.collide_mask() use the .rect and .mask attribute of the sprite object for the collision detection.
You have to update self.rect after rotating the image:
class Box(pygame.sprite.Sprite):
# [...]
def rotate(self):
self.angle += 3
new_img = pygame.transform.rotate(self.image, self.angle)
new_rect = new_img.get_rect(center=self.rect.center)
# update .rect attribute
self.rect = new_rect # <------
return new_img, new_rect
See also Sprite mask
Minimal example: repl.it/#Rabbid76/PyGame-SpriteMask
import pygame
class SpriteObject(pygame.sprite.Sprite):
def __init__(self, x, y, w, h, color):
pygame.sprite.Sprite.__init__(self)
self.angle = 0
self.original_image = pygame.Surface([w, h], pygame.SRCALPHA)
self.original_image.fill(color)
self.image = self.original_image
self.rect = self.image.get_rect(center = (x, y))
self.mask = pygame.mask.from_surface(self.image )
def update(self):
self.rotate()
def rotate(self):
self.angle += 0.3
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = self.rect.center)
self.mask = pygame.mask.from_surface(self.image )
pygame.init()
clock = pygame.time.Clock()
window = pygame.display.set_mode((400, 400))
size = window.get_size()
moving_object = SpriteObject(0, 0, 50, 50, (128, 0, 255))
static_objects = [
SpriteObject(size[0] // 2, size[1] // 3, 100, 50, (128, 128, 128)),
SpriteObject(size[0] // 4, size[1] * 2 // 3, 100, 50, (128, 128, 128)),
SpriteObject(size[0] * 3 // 4, size[1] * 2 // 3, 100, 50, (128, 128, 128))
]
all_sprites = pygame.sprite.Group([moving_object] + static_objects)
static_sprites = pygame.sprite.Group(static_objects)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
moving_object.rect.center = pygame.mouse.get_pos()
all_sprites.update()
collide = pygame.sprite.spritecollide(moving_object, static_sprites, False, pygame.sprite.collide_mask)
window.fill((255, 0, 0) if collide else (255, 255, 255))
all_sprites.draw(window)
pygame.display.update()
pygame.quit()
exit()
Related
I am currently making a game and I want to add a power up. I am essentially trying to make something similar to the spell book from Castlevania. I found a code to help me get the initial position and rotation. The problem is, the cross doesn't move from it's initial location. It just circles in place while the other one leaves it. I am still new to pygame and the math that goes with game dev. It is still pretty confusing.
import pygame
class Crucifix(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.sprite = pygame.image.load('image'). convert_alpha()
self.image = self.sprite
self.rect = self.image.get_rect()
self.rect.x =500
self.rect.y = 500
self.mask = pygame.mask.from_surface(self.image)
def update(self):
self.rect.x -= 2
if self.rect.x == -100:
self.kill()
class EnemiesStrong(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.original_image = pygame.image.load('image').convert_alpha()
self.image = self.original_image
self.rect = self.image.get_rect()
self.angle = 0
def initLoc(self, pos, radius):
self.pos = pos
self.radius = radius
def update(self):
center = pygame.math.Vector2(self.pos) + pygame.math.Vector2(0, -self.radius).rotate(-self.angle)
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = (round(center.x), round(center.y)))
def turnLeft(self):
self.angle = (self.angle + 4) % 360
pygame.init()
window = pygame.display.set_mode((800, 800))
clock = pygame.time.Clock()
cross1= Crucifix()
enemy_s = EnemiesStrong()
pos = cross1.rect.x, cross1.rect.y
enemy_s.initLoc(cross1.rect.center, 100)
all_sprites = pygame.sprite.Group(enemy_s)
all_sprites.add(cross1)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
enemy_s.turnLeft()
all_sprites.update()
window.fill(0)
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()
I am not exactly sure what to try at this point. Any help would be appreciated.
You have to update the position of enemy_s in every frame depending on the position of cross1. Add a updatePos method to the EnemiesStrong class:
class EnemiesStrong(pygame.sprite.Sprite):
# [...]
def updatePos(self, new_pos):
self.pos = new_pos
Call updatePos in the application loop:
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
enemy_s.turnLeft()
enemy_s.updatePos(cross1.rect.center) # <---
all_sprites.update()
window.fill(0)
all_sprites.draw(window)
pygame.display.flip()
Complete and minimal example based on your original code:
import pygame, math
class Crucifix(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((40, 40), pygame.SRCALPHA)
pygame.draw.circle(self.image, "white", (20, 20), 20)
pygame.draw.line(self.image, "magenta", (20, 0), (20, 40), 5)
pygame.draw.line(self.image, "magenta", (0, 20), (40, 20), 5)
self.rect = self.image.get_rect(center = (400, 400))
self.mask = pygame.mask.from_surface(self.image)
self.px = 400
self.a = 0
def update(self):
offset_x = math.sin(self.a) * 100
self.a += 0.05
self.rect.x = round(self.px + offset_x)
class EnemiesStrong(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.original_image = pygame.Surface((40, 40), pygame.SRCALPHA)
pygame.draw.circle(self.original_image, "red", (20, 20), 20)
pygame.draw.polygon(self.original_image, "yellow", ((20, 0), (40, 20), (20, 40), (0, 20)))
self.image = self.original_image
self.rect = self.image.get_rect()
self.angle = 0
def initLoc(self, pos, radius):
self.pos = pos
self.radius = radius
def update(self):
center = pygame.math.Vector2(self.pos) + pygame.math.Vector2(0, -self.radius).rotate(-self.angle)
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = (round(center.x), round(center.y)))
def turnLeft(self):
self.angle = (self.angle + 4) % 360
def updatePos(self, new_pos):
self.pos = new_pos
pygame.init()
window = pygame.display.set_mode((800, 800))
clock = pygame.time.Clock()
cross1 = Crucifix()
enemy_s = EnemiesStrong()
pos = cross1.rect.x, cross1.rect.y
enemy_s.initLoc(cross1.rect.center, 100)
all_sprites = pygame.sprite.Group(enemy_s)
all_sprites.add(cross1)
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *background.get_size(), (32, 32, 32), (48, 48, 48)
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)]
[pygame.draw.rect(background, color, rect) for rect, color in tiles]
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
enemy_s.turnLeft()
enemy_s.updatePos(cross1.rect.center)
all_sprites.update()
window.blit(background, (0, 0))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()
I am trying to:
draw a circle onto my window
let it move AND rotate at the same time to simulate a rolling ball.
Appreciate anyone's solutions! Attached below is my code.
import pygame
#create win
W, H = 700, 700
win = pygame.display.set_mode((W, H))
pygame.display.set_caption("Rotating Ball Simul")
#color lib
BG = (20,20,20)
BLUE = (0,0,255)
#draw circle
ballX, ballY = 0, 0
ballW = 20
ballH = ballW
ball = pygame.draw.circle(win, BLUE, (ballX, ballY), ballW, 1)
def redraw_window():
win.fill(BG)
win.blit(ball, (ballX, ballY))
pygame.display.update()
def main():
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
redraw_window()
if __name__ == '__main__':
main()
A circle always looks the same when you rotate it. You must use a sphere image to see the rotation. Read about How do I rotate an image around its center using PyGame? and move the ball image and change the rotation of the image depending on the movement. The angle of rotation depends on the movement and the diameter of the ball:
angle -= (self.x - prev_x) / self.diameter * 180 / math.pi
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = self.rect.center)
Minimal example:
repl.it/#Rabbid76/PyGame-FollowInGrid
import os
import math
import pygame
class MarbelSprite(pygame.sprite.Sprite):
def __init__(self, x, ground, diameter, velocity, filename):
pygame.sprite.Sprite.__init__(self)
try:
self.image = pygame.transform.smoothscale(pygame.image.load(filename).convert_alpha(), (diameter, diameter))
except:
self.image = pygame.Surface((diameter, diameter), pygame.SRCALPHA)
pygame.draw.circle(self.image, (255, 128, 0), (diameter // 2, diameter // 2), diameter // 2)
self.original_image = self.image
self.rect = self.image.get_rect(midbottom = (x, ground))
self.diameter = diameter
self.x = x
self.velocity = velocity
self.move_x = 0
self.follow = None
self.angle = 0
def update(self, time, restriction):
move_x = 0
prev_x = self.x
if self.move_x != 0:
move_x = self.move_x * self.velocity * time
elif self.follow:
dx = self.follow.rect.centerx - self.x
move_x = (-1 if dx < 0 else 1) * min(self.velocity * time, abs(dx))
self.x += move_x
self.x = max(restriction.left + self.diameter // 2, min(restriction.right - self.diameter // 2, self.x))
self.rect.centerx = round(self.x)
self.angle -= (self.x - prev_x) / self.diameter * 180 / math.pi
self.image = pygame.transform.rotate(self.original_image, self.angle)
self.rect = self.image.get_rect(center = self.rect.center)
pygame.init()
window = pygame.display.set_mode((500, 300))
clock = pygame.time.Clock()
ground_level = 220
object = MarbelSprite(window.get_rect().centerx, ground_level, 100, 0.4, 'BaskteBall.png')
follower = MarbelSprite(window.get_width() // 4, ground_level, 50, 0.2, 'TennisBall.png')
all_sprites = pygame.sprite.Group([object, follower])
run = True
while run:
time = clock.tick(60)
for events in pygame.event.get():
if events.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
object.move_x = keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]
follower.follow = object
all_sprites.update(time, window.get_rect())
window.fill((32, 64, 224))
pygame.draw.rect(window, (80, 64, 64), (0, ground_level, window.get_width(), window.get_height()-ground_level))
all_sprites.draw(window)
pygame.display.flip()
pygame.quit()
exit()
This question already has answers here:
Make a line as a sprite with its own collision in Pygame
(1 answer)
Check collision between a image and a line
(1 answer)
Closed 1 year ago.
This program should print "True", only if green rect touches the red line, but it prints True every time green rect got into red lines "area"(touches the lines sprite). Is there a way to make lines sprite?
In this code green is not on line, but still prints true:
class Line(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((200, 200))
self.rect = self.image.get_rect()
self.rect.x = 50
self.rect.y = 0
def update(self):
pygame.draw.line(screen, (255, 0, 0), (self.rect.x, self.rect.y), (200, 200))
class Rectt(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 50))
self.rect = self.image.get_rect()
self.rect.x = 25
self.rect.y = 100
def update(self):
pygame.draw.rect(screen, (0, 255, 0), self.rect)
pygame.init()
screen = pygame.display.set_mode((300, 300))
screen.fill((0, 0, 0))
running = True
l = Line()
m = Rectt()
while running:
for event in pygame.event.get():
if (event.type == pygame.QUIT):
running = False
if (pygame.sprite.collide_mask(m, l)):
print(True)
else:
print(False)
l.update()
m.update()
pygame.display.flip()
screen.fill((0, 0, 0))
pygame.quit()
See Make a line as a sprite with its own collision in Pygame
You need to create a image (pygame.Surface) in with a per pixel alpha format (pygame.SRCALPHA) or a black color key (pygame.Surface.get_colorkey). Draw the line on the image and blit the image on the screen:
class Line(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((200, 200))
self.image.set_colorkey((0, 0, 0))
pygame.draw.line(self.image, (255, 0, 0), (0, 0), (200, 200))
self.rect = self.image.get_rect()
self.rect.x = 50
self.rect.y = 0
def update(self):
screen.blit(self.image, self.rect)
Do the same for the rectangle:
class Rectt(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 50))
self.image.set_colorkey((0, 0, 0))
pygame.draw.rect(self.image, (0, 255, 0), (0, 0, 50, 50))
self.rect = self.image.get_rect()
self.rect.x = 25
self.rect.y = 100
def update(self):
screen.blit(self.image, self.rect)
You do not need the update methods at all if you are using a pygame.sprite.Group and pygame.sprite.Group.draw:
import pygame
class Line(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((200, 200))
self.image.set_colorkey((0, 0, 0))
pygame.draw.line(self.image, (255, 255, 0), (0, 0), (200, 200), 5)
self.rect = self.image.get_rect(topleft = (50, 50))
class Rectt(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 50))
self.image.set_colorkey((0, 0, 0))
pygame.draw.rect(self.image, (0, 0, 255), (0, 0, 50, 50))
self.rect = self.image.get_rect(topleft = (25, 100))
pygame.init()
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
running = True
l = Line()
m = Rectt()
group = pygame.sprite.Group([l, m])
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
m.rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * 3
m.rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * 3
m.rect.clamp_ip(screen.get_rect())
hit = pygame.sprite.collide_mask(m, l)
screen.fill((0, 0, 0))
group.draw(screen)
if hit:
pygame.draw.rect(screen, (255, 0, 0), m.rect, 5)
pygame.display.flip()
pygame.quit()
I have fixed the problem pointed out in this post, but now I am confused on how to point the gray rectangle (barrel) towards my mouse. Could somebody please help? Thanks!
Here is my code:
import pygame
import math
pygame.init()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption("diep.io")
screen.fill((255,255,255))
auto_shoot = False
class Bullet:
def __init__(self, x_move, y_move, x_loc, y_loc):
self.image = pygame.image.load("C:\\Users\\ender\\OneDrive\\Documents\\repos\\Bullet.png")
self.x_move = x_move
self.y_move = y_move
self.x_loc = x_loc
self.y_loc = y_loc
self.bullet_rect = self.image.get_rect()
def update(self):
self.x_loc += self.x_move
self.y_loc += self.y_move
self.bullet_rect.center = round(self.x_loc), round(self.y_loc)
rect = screen.blit(self.image, self.bullet_rect)
if not screen.get_rect().contains(rect):
bullets.remove(self)
if self.x_loc > 400 or self.y_loc > 400:
bullets.remove(self)
bullet = None
bullets = []
while True:
screen.fill((255, 255, 255))
pygame.draw.rect(screen, (100, 100, 100), (205, 193, 25, 15)) # This is the rectangle I want to point at my mouse
pygame.draw.circle(screen, (82, 219, 255), (200, 200), 15)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONUP:
x = pygame.mouse.get_pos()[0] - 200
y = pygame.mouse.get_pos()[1] - 200
pythag = float(math.sqrt(x**2 + y**2))
bullets.append(Bullet(x/pythag, y/pythag, 200, 200))
for bullet in bullets:
bullet.update()
pygame.display.update()
pygame.time.delay(10)
Note: This is different from other problems because I am trying to point a rectangle at my mouse, and other posts are pointing an image at the mouse. That is not what I want to do. Secondly, pygame rectangles are defined by their bottom left corner, so this further complicates things.
For the rotation of the bullets see How to move a sprite according to an angle in Pygame and calculating direction of the player to shoot PyGmae.
Compute the angle of the direction vector grees(math.atan2(-y_move, x_move)) and rotate the bullet image:
class Bullet:
def __init__(self, x_move, y_move, x_loc, y_loc):
self.image = pygame.image.load("C:\\Users\\ender\\OneDrive\\Documents\\repos\\Bullet.png")
self.image = pygame.transform.rotate(self.image, math.degrees(math.atan2(-y_move, x_move)))
Rotating the rectangle is a little trickier. Draw the cannon on a pygame.Surface:
cannon = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.rect(cannon, (100, 100, 100), (30, 17, 25, 15))
pygame.draw.circle(cannon, (82, 219, 255), (25, 25), 15)
See How do I rotate an image around its center using PyGame?.
Write a function to rotate and blit a Surface:
def blitRotateCenter(surf, image, center, angle):
rotated_image = pygame.transform.rotate(image, angle)
new_rect = rotated_image.get_rect(center = image.get_rect(center = center).center)
surf.blit(rotated_image, new_rect)
Use the function in the application loop to draw the cannon:
while True:
# [...]
x = pygame.mouse.get_pos()[0] - 200
y = pygame.mouse.get_pos()[1] - 200
angle = math.degrees(math.atan2(-y, x))
blitRotateCenter(screen, cannon, (200, 200), angle)
# [...]
See also How to rotate an image(player) to the mouse direction? and How can you rotate the sprite and shoot the bullets towards the mouse position?.
Complete example:
import pygame
import math
pygame.init()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption("diep.io")
screen.fill((255,255,255))
clock = pygame.time.Clock()
class Bullet:
def __init__(self, x_move, y_move, x_loc, y_loc):
#self.image = pygame.image.load("C:\\Users\\ender\\OneDrive\\Documents\\repos\\Bullet.png")
self.image = pygame.Surface((20, 5), pygame.SRCALPHA)
self.image.fill((255, 0, 0))
self.image = pygame.transform.rotate(self.image, math.degrees(math.atan2(-y_move, x_move)))
self.x_move = x_move
self.y_move = y_move
self.x_loc = x_loc
self.y_loc = y_loc
self.bullet_rect = self.image.get_rect()
def update(self):
self.x_loc += self.x_move
self.y_loc += self.y_move
self.bullet_rect.center = round(self.x_loc), round(self.y_loc)
rect = screen.blit(self.image, self.bullet_rect)
if not screen.get_rect().contains(rect):
bullets.remove(self)
if self.x_loc > 400 or self.y_loc > 400:
bullets.remove(self)
cannon = pygame.Surface((50, 50), pygame.SRCALPHA)
pygame.draw.rect(cannon, (100, 100, 100), (30, 17, 25, 15))
pygame.draw.circle(cannon, (82, 219, 255), (25, 25), 15)
def blitRotateCenter(surf, image, center, angle):
rotated_image = pygame.transform.rotate(image, angle)
new_rect = rotated_image.get_rect(center = image.get_rect(center = center).center)
surf.blit(rotated_image, new_rect)
bullet = None
bullets = []
auto_shoot = False
run = True
while run:
x = pygame.mouse.get_pos()[0] - 200
y = pygame.mouse.get_pos()[1] - 200
angle = math.degrees(math.atan2(-y, x))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONUP:
pythag = float(math.sqrt(x**2 + y**2))
bullets.append(Bullet(x/pythag, y/pythag, 200, 200))
screen.fill((255, 255, 255))
for bullet in bullets:
bullet.update()
blitRotateCenter(screen, cannon, (200, 200), angle)
pygame.display.update()
clock.tick(100)
pygame.quit()
exit()
I've been having a hard time getting collision to work. I'm new and don't know the in and outs with coding so please can you explain your reasoning.
Here's a simple of some code:
def __init__(self, x, y, width, height, sprite):
self.x = player_x
self.y = player_y
self.width = player.width
self.height = player.height
self.col = pygame.sprite.collide_rect(self, sprite)
pygame.sprite.Sprite.__init__(self)
def velocity_player(self):
player_vertical_velocity = 0
player_horizontal_velocity = 0
player_y = player_y + player_vertical_velocity
player_x = player_x + player_horizontal_velocity
player_fr = 5
def render(self):
player_surface = pygame.image.load("Bunny.png")
player_surface.set_colorkey(TRANSPARENT_GREEN)
player_left = pygame.image.load("Bunny_left.png")
player_left.set_colorkey(TRANSPARENT_GREEN)
player_left = pygame.image.load("Bunny_left.png")
player_left.set_colorkey(TRANSPARENT_GREEN)
player_fall = pygame.image.load("Bunny_Fall.png")
player_fall.set_colorkey(TRANSPARENT_GREEN)
player_jump = pygame.image.load("Bunny_r_Jump.png")
screen.blit(player_surface, [player_x, player_y])
First, start by learning the concept of Classes (see also Python - Classes and OOP Basics). The collision must be detected in every frame. Usually you don't want to do it in the constrictor of a class. See How do I detect collision in pygame?.
When using pygame.sprite.Sprites and pygame.sprite.Groups, collision is detected by functions like pygame.sprite.spritecollide() and pygame.sprite.groupcollide(). However, collision detection is usually not performed in the Sprite class. This is done in the outer code that manages the Sprites and the interaction between the Sprites.
Minimal example:
import pygame
pygame.init()
window = pygame.display.set_mode((250, 250))
class RectSprite(pygame.sprite.Sprite):
def __init__(self, color, x, y, w, h):
super().__init__()
self.image = pygame.Surface((w, h))
self.image.fill(color)
self.rect = pygame.Rect(x, y, w, h)
player = RectSprite((255, 0, 0), 0, 0, 50, 50)
obstacle1 = RectSprite((128, 128, 128), 50, 150, 50, 50)
obstacle2 = RectSprite((128, 128, 128), 150, 50, 50, 50)
all_group = pygame.sprite.Group([obstacle1, obstacle2, player])
obstacle_group = pygame.sprite.Group([obstacle1, obstacle2])
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
player.rect.center = pygame.mouse.get_pos()
collide = pygame.sprite.spritecollide(player, obstacle_group, False)
window.fill(0)
all_group.draw(window)
for s in collide:
pygame.draw.rect(window, (255, 255, 255), s.rect, 5, 1)
pygame.display.flip()
pygame.quit()