Looking for a concise way to check for point collision in a list of Rects
-
22-12-2019 - |
문제
I'm trying to find a way to check if a point lies within any Rect in a list of Rects, and to get the index of that Rect (or the first, if multiple) on the list.
My current solution is to make a single-pixel Rect using the point I want to check for, then using collidelist
to compare that point against the list I want to search for.
It looks like this:
tgtrect = pygame.Rect(coords, (1,1)).collidelist(rectlist)
...wherein coords
is the point checked (usually, not always, a mouse location) and rectlist
is the list of Rects to be evaluated.
tgtrect
receives the index number of a colliding Rect, or -1 if there are none.
I need this index value to resolve the identity of the colliding Rect elsewhere.
I feel like there's a better way to get this information (that is, to check coords
against a list, returning an index (or False/None/-1 if there are no hits), without having to make a Rect each time), but I don't know what it is (or if it exists at all).
Basically, what I need is <Rect>.collidelist(rectlist)
, but for an (x,y) tuple and not a Rect, or <Rect>.collidepoint(coords)
, but for a list of Rects and not a single one. (I could use this second method with an iterator for rectlist, but it would be more difficult to get the index for the colliding Rect.)
I looked around a bit and found this, Pygame action when mouse 'click' on .rect?, which offers a way to check for single Rects, but not a list of many. The significance is that my list of target Rects is dynamic; the number of Rects and their locations changes frequently.
I also read through this, Pygame .Rect won't "collide" with mouse, which gave a solution that didn't really suit the situation for the same reasons.
Thanks!
((Auth. note: This is my first question, so please forgive me if it's kind of ugly. Please let me know if it does not supply enough information, or there are things I can do to improve it.))
해결책
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
>>>