repl.it/@Rabbid76/PyGame-collidepoint
import pygamepygame.init()window = pygame.display.set_mode((250, 250))rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(100, 100)run = Truewhile run:for event in pygame.event.get():if event.type == pygame.QUIT:run = Falsepoint = pygame.mouse.get_pos()collide = rect.collidepoint(point)color = (255, 0, 0) if collide else (255, 255, 255)window.fill(0)pygame.draw.rect(window, color, rect)pygame.display.flip()pygame.quit()exit()
pygame.Rect.colliderect
Test if two rectangles overlap
See also How to detect collisions between two rectangular objects or images in pygame
repl.it/@Rabbid76/PyGame-colliderect
import pygamepygame.init()window = pygame.display.set_mode((250, 250))rect1 = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)rect2 = pygame.Rect(0, 0, 75, 75)run = Truewhile run:for event in pygame.event.get():if event.type == pygame.QUIT:run = Falserect2.center = pygame.mouse.get_pos()collide = rect1.colliderect(rect2)color = (255, 0, 0) if collide else (255, 255, 255)window.fill(0)pygame.draw.rect(window, color, rect1)pygame.draw.rect(window, (0, 255, 0), rect2, 6, 1)pygame.display.flip()pygame.quit()exit()
Furthermore, pygame.Rect.collidelist
and pygame.Rect.collidelistall
can be used for the collision test between a rectangle and a list of rectangles. pygame.Rect.collidedict
and pygame.Rect.collidedictall
can be used for the collision test between a rectangle and a dictionary of rectangles.
The collision of pygame.sprite.Sprite
and pygame.sprite.Group
objects, can be detected by pygame.sprite.spritecollide()
, pygame.sprite.groupcollide()
or pygame.sprite.spritecollideany()
. When using these methods, the collision detection algorithm can be specified by the collided
argument:
The collided argument is a callback function used to calculate if two sprites are colliding.
Possible collided
callables are collide_rect
, collide_rect_ratio
, collide_circle
, collide_circle_ratio
, collide_mask
Some examples:
pygame.sprite.spritecollide()
repl.it/@Rabbid76/PyGame-spritecollide
import pygamepygame.init()window = pygame.display.set_mode((250, 250))sprite1 = pygame.sprite.Sprite()sprite1.image = pygame.Surface((75, 75))sprite1.image.fill((255, 0, 0))sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)sprite2 = pygame.sprite.Sprite()sprite2.image = pygame.Surface((75, 75))sprite2.image.fill((0, 255, 0))sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(75, 75)all_group = pygame.sprite.Group([sprite2, sprite1])test_group = pygame.sprite.Group(sprite2)run = Truewhile run:for event in pygame.event.get():if event.type == pygame.QUIT:run = Falsesprite1.rect.center = pygame.mouse.get_pos()collide = pygame.sprite.spritecollide(sprite1, test_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()exit()
For a collision with masks, see How can I make a collision mask? or Pygame mask collision
See also Collision and Intersection
pygame.sprite.spritecollide()
/ collide_circle
repl.it/@Rabbid76/PyGame-spritecollidecollidecircle
import pygamepygame.init()window = pygame.display.set_mode((250, 250))sprite1 = pygame.sprite.Sprite()sprite1.image = pygame.Surface((80, 80), pygame.SRCALPHA)pygame.draw.circle(sprite1.image, (255, 0, 0), (40, 40), 40)sprite1.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(80, 80)sprite1.radius = 40sprite2 = pygame.sprite.Sprite()sprite2.image = pygame.Surface((80, 89), pygame.SRCALPHA)pygame.draw.circle(sprite2.image, (0, 255, 0), (40, 40), 40)sprite2.rect = pygame.Rect(*window.get_rect().center, 0, 0).inflate(80, 80)sprite2.radius = 40 all_group = pygame.sprite.Group([sprite2, sprite1])test_group = pygame.sprite.Group(sprite2)run = Truewhile run:for event in pygame.event.get():if event.type == pygame.QUIT:run = Falsesprite1.rect.center = pygame.mouse.get_pos()collide = pygame.sprite.spritecollide(sprite1, test_group, False, pygame.sprite.collide_circle)window.fill(0)all_group.draw(window)for s in collide:pygame.draw.circle(window, (255, 255, 255), s.rect.center, s.rect.width // 2, 5)pygame.display.flip()pygame.quit()exit()
What does this all mean for your code?
pygame.Surface.get_rect.get_rect()
returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument. For example, the centre of the rectangle can be specified with the keyword argument center
. These keyword arguments are applied to the attributes of the pygame.Rect
before it is returned (see pygame.Rect
for a list of the keyword arguments).
See *Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
You do not need the x
and y
attributes of Sprite
and Bullet
at all. Use the position of the rect
attribute instead:
#Define the sprite classclass Sprite:def __init__(self, x, y, name):self.image = pygame.image.load(name)self.rect = self.image.get_rect(topleft = (x, y))def render(self):window.blit(self.image, self.rect)# Define the bullet class to create bullets class Bullet:def __init__(self, x, y):self.bullet = pygame.image.load("user_bullet.BMP")self.rect = self.bullet.get_rect(topleft = (x + 23, y))def render(self):window.blit(self.bullet, self.rect)
Use pygame.Rect.colliderect()
to detect collisions between instances of Sprite
and Bullet
.
See How to detect collisions between two rectangular objects or images in pygame:
my_sprite = Sprite(sx, sy, name)my_bullet = Bullet(by, by)
while True:# [...]if my_sprite.rect.colliderect(my_bullet.rect):printe("hit")
From what I understand of pygame you just need to check if the two rectangles overlap using the colliderect
method. One way to do it is to have a method in your Bullet
class that checks for collisions:
def is_collided_with(self, sprite):return self.rect.colliderect(sprite.rect)
Then you can call it like:
sprite = Sprite(10, 10, 'my_sprite')bullet = Bullet(20, 10)if bullet.is_collided_with(sprite):print('collision!')bullet.kill()sprite.kill()
There is a very simple method for what you are trying to do using built in methods.
here is an example.
import pygameimport sysclass Sprite(pygame.sprite.Sprite):def __init__(self, pos):pygame.sprite.Sprite.__init__(self)self.image = pygame.Surface([20, 20])self.image.fill((255, 0, 0))self.rect = self.image.get_rect()self.rect.center = posdef main():pygame.init()clock = pygame.time.Clock()fps = 50bg = [255, 255, 255]size =[200, 200]screen = pygame.display.set_mode(size)player = Sprite([40, 50])player.move = [pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN]player.vx = 5player.vy = 5wall = Sprite([100, 60])wall_group = pygame.sprite.Group()wall_group.add(wall)player_group = pygame.sprite.Group()player_group.add(player)# I added loop for a better exit from the gameloop = 1while loop:for event in pygame.event.get():if event.type == pygame.QUIT:loop = 0key = pygame.key.get_pressed()for i in range(2):if key[player.move[i]]:player.rect.x += player.vx * [-1, 1][i]for i in range(2):if key[player.move[2:4][i]]:player.rect.y += player.vy * [-1, 1][i]screen.fill(bg)# first parameter takes a single sprite# second parameter takes sprite groups# third parameter is a do kill command if true# all group objects colliding with the first parameter object will be# destroyed. The first parameter could be bullets and the second one# targets although the bullet is not destroyed but can be done with# simple trick bellowhit = pygame.sprite.spritecollide(player, wall_group, True)if hit:# if collision is detected call a function in your case destroy# bulletplayer.image.fill((255, 255, 255))player_group.draw(screen)wall_group.draw(screen)pygame.display.update()clock.tick(fps)pygame.quit()# sys.exitif __name__ == '__main__':main()
Make a group for the bullets, and then add the bullets to the group.
What I would do is this:In the class for the player:
def collideWithBullet(self):if pygame.sprite.spritecollideany(self, 'groupName'):print("CollideWithBullet!!")return True
And in the main loop somewhere:
def run(self):if self.player.collideWithBullet():print("Game Over")
Hopefully that works for you!!!
Inside the Sprite class, try adding a self.mask
attribute withself.mask = pygame.mask.from_surface(self.image)
and a collide_mask
function inside of the Sprite class with this code:
def collide_mask(self, mask):collided = Falsemask_outline = mask.outline()self.mask_outline = self.mask.outline()for point in range(len(mask_outline)):mask_outline[point] = list(mask_outline[point])mask_outline[point][0] += bullet.xmask_outline[point][1] += bullet.yfor point in range(len(self.mask_outline)):self.mask_outline[point] = list(mask_outline[point])self.mask_outline[point][0] += self.xself.mask_outline[point][1] += self.yfor point in mask_outline:for self_mask_point in self.mask_outline:if point = self_mask_point:collided = Truereturn collided