pymunk
pymunk copied to clipboard
Wildcard collision handler
for the lack of a better place to ask. I don't know if it is a issue or i'm doing things wrong but a wildcard collision handler isn't supposed to be called every time a certain type of shape collides? I've done something like that :
myshape = pymunk.Circle(mybody, radius) myshape.collision_type = 0 space.add(mybody, myshape)
def mybegin(): print('collision confirmed') return true
myhandler = space.add_wildcard_collision_handler(0) myhandler.begin = mybegin
with no results, the shapes collides as they do normally, but i never get the message 'collision confirmed'. Also when I use something like:
myhandler = space.add_collision_handler(0, 0) myhandler.begin = mybegin
I get the message 'collision confirmed' every time myshape collides with anything else, instead of only when 2 of myshape collide, the behavior I was expecting, because when using:
myshape1 = pymunk.Circle(mybody1, radius) myshape1.collision_type = 1 space.add(mybody1, myshape1)
myhandler = space.add_collision_handler(0, 1) myhandler.begin = mybegin
I only get the message 'collision confirmed' when myshape collides with myshape1, the behavior I assume is the intended.
Its difficult to say without more code. See this example that will print out wildcard collision
import pymunk
space = pymunk.Space()
b1 = pymunk.Body(1,2)
c1 = pymunk.Circle(b1, 10)
c1.collision_type = 0
space.add(b1,c1)
b2 = pymunk.Body(1,2)
c2 = pymunk.Circle(b2, 10)
c2.collision_type = 1
space.add(b2,c2)
h = space.add_wildcard_collision_handler(0)
def f(*args):
print('wildcard collision')
return True
h.begin = f
space.step(1)
your example worked, I tried a few different scenarios, and i think I know what I'm doing that is causing the issue. The issue only happens when i use a default_collision_handler with an wildcard_collision_handler in the same space:
import pyglet import pymunk from pymunk.pyglet_util import DrawOptions
window = pyglet.window.Window(600, 600, 'pymunk test') options = DrawOptions()
space = pymunk.Space() space.gravity = 0, -500
line = pymunk.Segment(space.static_body, (0, 10), (600, 10), 2) line.elasticity = 0.7 line.friction = 0.5 line.collision_type = 1 space.add(line)
circle_body = pymunk.Body(1, 999) circle_body.position = (300, 500) circle_shape = pymunk.Circle(circle_body, 50) circle_shape.elasticity = 0.7 circle_shape.friction = 0.9 circle_shape.collision_type = 0 space.add(circle_body, circle_shape)
circle_body = pymunk.Body(1, 999) circle_body.position = (300, 300) circle_shape = pymunk.Circle(circle_body, 50) circle_shape.elasticity = 0.7 circle_shape.friction = 0.9 circle_shape.collision_type = 0 space.add(circle_body, circle_shape)
def collision_begin(arbiter, space, data): print('a collision happen') return True
def circle_begin(arbiter, space, data): print('a circle collided') return True
def circle_circle_begin(arbiter, space, data): print('two circles collided') return True
#handler = space.add_default_collision_handler() #handler.begin = collision_begin circle_handler = space.add_wildcard_collision_handler(0) circle_handler.begin = circle_begin circle_circle_handler = space.add_collision_handler(0,0) circle_circle_handler.begin = circle_circle_begin
@window.event def on_draw(): window.clear() space.debug_draw(options)
def update(dt): space.step(dt)
if name == 'main' : pyglet.clock.schedule_interval(update, 1/60.0) pyglet.app.run()
this code returns:
a circle collided two circles collided a circle collided a circle collided a circle collided two circles collided two circles collided two circles collided two circles collided
uncommenting the two lines it returns:
a collision happen two circles collided a collision happen two circles collided a collision happen a collision happen a collision happen two circles collided a collision happen a collision happen two circles collided a collision happen two circles collided a collision happen
Ah, ok, now I get the same result as you. I will do some more investigation as to why,
I have a question that relates to this issue, dunno if it's worth opening another issue for so I'll leave a comment here for now. I'm trying to add both a wildcard collision handler for type 1 and a specific handler for types 1 and 2, but I want the wildcard handler to always be called. Currently, the specific handler overrides the wildcard when a shape of type 2 is involved. In the doc, it says you need to call the wildcard yourself using Arbiter.call_wildcard*()
- however, this is the only mention of this function anywhere - it doesn't show up anywhere else in the docs or in the source code AFAICT. How should i call the wildcard from the specific handler?
Oh, well spotted. It must be a leftover in the docs. I will update them when I have the chance. I think the best way to do what you want is to just call it manually like any other function.