As an example, I wrote a program that creates 100 sprites, and draws
them with batch.draw() during on_draw(). And I scheduled an update
that, 60 times a second, randomly changes the sprites's x or y
position a few pixels each loop. This runs great, very fast.
Then, I compare each sprite to each other with this code I found on
someone's blog:
def collide(a, b):
if a.y + a.height < b.y:
return False
if a.y > b.y + b.height:
return False
if a.x + a.width < b.x:
return False
if a.x > b.x + b.width:
return False
return True
It works, but it's really, really slow (on a modern E8400 CPU). It
may be that this is a perfectly good technique, but I'm not using it
correctly...
Also, this treats all sprites like boxes, and wouldn't work well if
the sprite is supposed to be a circle, a ball, etc.
Does anyone have any code that handles this?
If some of the sprites are close together, you can also create some kind of
bounding colliders which just have the attributes x, y, width and height.
The following is a simplified version. To make it really elegant, you can add
a collide function to the collider, which automatically recurses into its
contents (which can also be colliders in colliders) and at the end return
tuples of sprites which collide.
class Collider(object):
def __init__(self, *args):
self.sprites = args
self.x = min([i.x for i in args])
self.y = min([i.y for i in args])
right = max([i.x + i.width for i in args])
self.width = right - self.x
del right
top = max([i.y + i.height for i in args])
self.height = top - self.y
del top
When you have some connected objects, you first only compare bounding boxes
and when something collides with the bounding box, you do a collision test
against all included sprites.
coll = Collider(sprite1, sprite2, sprite3)
coll2 =Collider(sprite4, sprite5, sprite6)
colliders = [coll, coll2]
colliding = []
for i in collliders:
for j in colliders[i:]
if collide(i, j):
for a in i.sprites:
for b in j.sprites:
if collide(a, b):
colliding.append((a, b))
This still doesn't really scale linearly, but it scales far better than
quadratic.
I hope this helps you get going in optimizing collision performance,
Arne
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
- singing a part of the history of free software -
http://infinite-hands.draketo.de
Im interested in the answer of this problem but what I would do is if
the player is moving left and up, and its upper-left corner hits
another object. I would check if I bounced into the object to the
left, or that i am more to the right.
Another way of saying:
The points where 2 (1 standing still and 1 is moving left and up)
squares collide is an rectangle. If the rectangle is width>height then
It bounced onto the bottom. If the rengtangle is height>width it
bounced on the left.
I think that should suffice :-)
Im interested in the answer of this problem but what I would do is if
the player is moving left and up, and its upper-left corner hits
another object. I would check if I bounced into the object to the
left, or that i am more to the right.
Another way of saying:
The points where 2 (1 standing still and 1 is moving left and up)
squares collide is an rectangle. If the rectangle is width>height then
It bounced onto the bottom. If the rengtangle is height>width it
bounced on the left.
I think that should suffice :-)
> Right now, I am thinking this: Instead of changing a moving sprite's
> X/Y, then doing collision checking, I should loop forward from its
> starting point, 1 "step" at a time
If the collision shapes are assumed to be rectangles,
and the objects are moving in a straight line with
constant speed, then you don't need to move it a
step at a time -- you can directly calculate the
time at which the two rectangles begin to touch.
Do this twice, once for the x direction and once
for the y direction. Whichever of these gives you
the earliest collision time tells you which side
they collided on.
This technique can also help you deal with the
problem of objects passing through each other due
to large time steps. Find all the objects that the
sprite could possibly collide with (perhaps using
a bounding rectangle) and calculate the collision
time with each one. The object having the earliest
collision time is the one that gets hit.
--
Greg