Rect Collision with List of Rects

rect collision with list of rects

Use pygame.Rect.collidelist to test whether a rectangle collides with one of a list of rectangles.

collidelist:

Test whether the rectangle collides with any in a sequence of rectangles. The index of the first collision found is returned. If no collisions are found an index of -1 is returned.

if player_rect.collidelist(tile_rects) >= 0:
# [...]

How to detect collision between a list of Rect and another list of Rects

There is no function that can directly test for collisions between 2 lists of rectangles in pygame, unless you are using pygame.sprite.Group and pygame.sprite.groupcollide. If you have 2 pygame.sprite.Group objects (group1 and group2) you can do the following:

if pygame.sprite.groupcollide(group1, group2, True, True):
print("hit")

If you have to lists of pygame.Rect objects (rect_list1 and rect_list2) you can use collidelist() or collidelistall() in a loop. e.g.:

for rect1 in rect_list1:
index = rect1.collidelist(rect_list2)
if index >= 0:
print("hit")
for rect1 in rect_list1:
collide_list = rect1.collidelistall(rect_list2)
if collide_list:
print("hit")

If you don't have pygame.Rect objects, you need to create them and run the collision test in nested loops:

for zombie in self.zombies:
zombieRect = pygame.Rect(zombie.x, zombie.y, zombie.width, zombie.height)
for bullet in self.bullets:
bulletRect = pygame.Rect(bullet.x, bullet.y, bullet.width, bullet.height)
if zombieRect.colliderect(bulletRect):
print("hit")

How do I make a rect check for collisions with a lot of different rects? Pygame

As mentioned by Alian, you have to use a list to store multiple rects (or anything at all if you want more than just a few). Then you can iterate through that list and check for collisions. Here is a quick fresh example since your code does not provide anything related to it.

import pygame

#make a list and add 30 rects in it
rects = []
for x in range(5):
for y in range(6):
rects.append(pygame.Rect(x * 50 + 10, y * 50 + 10, 40, 40))


pygame.init()
screen = pygame.display.set_mode((260, 310))

running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

screen.fill((255, 255, 255))

#go through all the rects and check for collision
for rect in rects:
color = (255, 0, 0)
if (rect.collidepoint(pygame.mouse.get_pos())):
color = (0, 255, 0)
pygame.draw.rect(screen, color, rect)

pygame.display.update()

pygame-How do I check if there is collision with any rect in an array?

Every time the code is executed in the loop, all 4 states (can_move_up, can_move_down , can_move_left, can_move_right ) are set. In each loop iteration, the results of the previous loop are overwritten. At the end only the results of the last run are set.

Set the status variables before the loop, but reset them inside the loop:

def detect_collisions(self, player_obj):

player_obj.can_move_up = True
player_obj.can_move_down = True
player_obj.can_move_left = True
player_obj.can_move_right = True

for b in self.collision_boxes:
if player_obj.top_rect.colliderect(b.rect):
player_obj.can_move_up = False
if player_obj.bottom_rect.colliderect(b.rect):
player_obj.can_move_down = False
if player_obj.left_rect.colliderect(b.rect):
player_obj.can_move_left = False
if player_obj.right_rect.colliderect(b.rect):
player_obj.can_move_right = False

You can simplify your code by creating a list of pygame.Rect objects and using pygame.Rect.collidelist:

collidelist(list) -> index

Test whether the rectangle collides with any in a sequence of rectangles. The index of the first collision found is returned. If no collisions are found an index of -1 is returned.

def detect_collisions(self, player_obj):

rect_list = [b.rect for b in self.collision_boxes]

player_obj.can_move_up = player_obj.top_rect.collidelist(rect_list) == -1
player_obj.can_move_down = player_obj.bottom_rect.collidelist(rect_list) == -1
player_obj.can_move_left = player_obj.left_rect.collidelist(rect_list) == -1
player_obj.can_move_right = player_obj.right_rect.collidelist(rect_list) == -1

using colliderect in an array of random coordinates

Use collidelist() to test test if one rectangle in a list intersects:

for i in self.imagenes1_array:
s = pygame.image.load(i)
self.images.append(s)
r = s.get_rect()

position_set = False
while not position_set:
r.x = random.randint(300,1000)
r.y = random.randint(200,700)

margin = 10
rl = [rect.inflate(margin*2, margin*2) for rect in self.rects]
if len(self.rects) == 0 or r.collidelist(rl) < 0:
self.rects.append(r)
position_set = True

See the minimal example, that uses the algorithm to generate random not overlapping rectangles:

Sample Image

import pygame
import random

pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

def new_recs(rects):
rects.clear()
for _ in range(10):
r = pygame.Rect(0, 0, random.randint(30, 40), random.randint(30, 50))

position_set = False
while not position_set:
r.x = random.randint(10, 340)
r.y = random.randint(10, 340)

margin = 10
rl = [rect.inflate(margin*2, margin*2) for rect in rects]
if len(rects) == 0 or r.collidelist(rl) < 0:
rects.append(r)
position_set = True
rects = []
new_recs(rects)

run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
new_recs(rects)

window.fill(0)
for r in rects:
pygame.draw.rect(window, (255, 0, 0), r)
pygame.display.flip()

pygame.quit()
exit()

How do I test if list collides with point?

I'm not familiar with pygame, but from I can see, you should be using the collidelist from an instance of Rect, rather than passing the instance as a parameter to the method from the class Rect. Also, you shouldn't be using "list" as a variable name.

if rect.collidelist(list) != -1:
#yadda_yadda_yadda

If you want to check just a single point, you can create a rectangle with all of its corners at rect.midbottom, or you can do

if any(rect_from_list.collidepoint(rect.midbottom) for rect_fram_list in list):
#yadda_yadda_yadda

Looking for a concise way to check for point collision in a list of Rects

You could use a simple generator expression and collidepoint(), like

>>> rects = [pygame.Rect(0,0,100,100), pygame.Rect(30,30,30,30)]
>>> next((r for r in rects if r.collidepoint(10, 10)), None)
<rect(0, 0, 100, 100)>
>>> next((r for r in rects if r.collidepoint(200, 200)), None)
>>>

or, if you really want the index instead of the Rect itself:

>>> rects = [pygame.Rect(0,0,100,100), pygame.Rect(30,30,30,30)]
>>> next((i for (i, r) in enumerate(rects) if r.collidepoint(10, 10)), -1)
0
>>> next((i for (i, r) in enumerate(rects) if r.collidepoint(100, 200)), -1)
-1
>>>


Related Topics



Leave a reply



Submit