Search code examples
pythonfiltershapessegmentpymunk

pymunk updated shape filter usage


I am trying to detect the first shape along a segment starting at my player's position, but I do not want to detect the player.

In a previous version of pymunk, the pymunk.Space.segment_query_first function accepted an integer as the shape_filter and it only detected shapes within a group of that integer. That worked perfectly, but now it accepts a list or dictionary instead. I have tried putting the integer into a list and that didn't work. I have no idea what it wants with a dictionary. I have tried everything that I can think of. Nothing seems to stop it from detecting my player. The documentation is not helpful at all. Thanks in advance.


Solution

  • Yes the shape filter have become more powerful in pymunk 5 (and as a result also a little bit more complicated). The shape filter is supposed to be a ShapeFilter object (but . See the api docs http://www.pymunk.org/en/latest/pymunk.html#pymunk.ShapeFilter for details on this filter object.

    The ShapeFilter has 3 properties: categories, mask, and group. In your case I think you want to put the player in a separate category, and mask it out from the filter query. (By default the shape filter object matches all categories and doesnt mask out anything).

    So, you want to do something like in this example:

    >>> import pymunk
    >>> s = pymunk.Space()
    >>> player_b = pymunk.Body(1,1)
    >>> player_c = pymunk.Circle(player_b, 10)
    >>> s.add(player_b, player_c)
    >>>
    >>> player_c.filter = pymunk.ShapeFilter(categories=0x1)
    >>> s.point_query_nearest((0,0), 0, pymunk.ShapeFilter())
    PointQueryInfo(shape=<pymunk.shapes.Circle object at 0x03C07F30>, point=Vec2d(nan, nan), distance=-10.0, gradient=Vec2d(0.0, 1.0))
    >>> s.point_query_nearest((0,0), 0, pymunk.ShapeFilter(mask=pymunk.ShapeFilter.ALL_MASKS ^ 0x1))
    >>>
    >>> other_b = pymunk.Body(1,1)
    >>> other_c = pymunk.Circle(other_b, 10)
    >>> s.add(other_b, other_c)
    >>>
    >>> s.point_query_nearest((0,0), 0, pymunk.ShapeFilter(mask=pymunk.ShapeFilter.ALL_MASKS ^ 0x1))
    PointQueryInfo(shape=<pymunk.shapes.Circle object at 0x03C070F0>, point=Vec2d(nan, nan), distance=-10.0, gradient=Vec2d(0.0, 1.0))
    

    There are tests in the test_space.py file that tests different combinations of the shape filter which might help explain how they work: https://github.com/viblo/pymunk/blob/master/tests/test_space.py#L175