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:
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
Screenshot of Inactive Window Printwindow + Win32Gui
How to Extract Info Within a #Shadow-Root (Open) Using Selenium Python
How to Convert a Password into Asterisks While It Is Being Entered
Fitting a 2D Gaussian Function Using Scipy.Optimize.Curve_Fit - Valueerror and Minpack.Error
How to Get a List of Column Names in SQLite
Using Self.Xxxx as a Default Parameter - Python
Panda's Dataframe - Renaming Multiple Identically Named Columns
Python: Use MySQLdb to Import a MySQL Table as a Dictionary
Catch Exception and Continue Try Block in Python
Directing Print Output to a .Txt File
How to Left Align a Fixed Width String
How to Search a Word in a Word 2007 .Docx File
Sqlite3, Operationalerror: Unable to Open Database File
How to Change the Datetime Tick Label Frequency for Matplotlib Plots