concepts.simulator.pymunk.world.PymunkWorld#

class PymunkWorld[source]#

Bases: Space

A wrapper pymunk.Space providing a manager for screen size and body labels.

Methods

add(*objs)

Add one or many shapes, bodies or constraints (joints) to the space

add_body(body[, shapes, selectable, label])

Add a body to the space.

add_collision_handler(collision_type_a, ...)

Return the CollisionHandler for collisions between objects of type collision_type_a and collision_type_b.

add_default_collision_handler()

Return a reference to the default collision handler or that is used to process all collisions that don't have a more specific handler.

add_post_step_callback(callback_function, ...)

Add a function to be called last in the next simulation step.

add_wildcard_collision_handler(collision_type_a)

Add a wildcard collision handler for given collision type.

bb_query(bb, shape_filter)

Query space to find all shapes near bb.

copy()

Create a deep copy of this object.

debug_draw(options)

Debug draw the current state of the space using the supplied drawing options.

get_body_by_label(name)

get_body_poses()

get_body_states()

get_collision_free_pspace(controlling_object)

point_query(point, max_distance, shape_filter)

Query space at point for shapes within the given distance range.

point_query_nearest(point, max_distance, ...)

Query space at point the nearest shape within the given distance range.

random_body_pos([body])

reindex_shape(shape)

Update the collision detection data for a specific shape in the space.

reindex_shapes_for_body(body)

Reindex all the shapes for a certain body.

reindex_static()

Update the collision detection info for the static shapes in the space.

remove(*objs)

Remove one or many shapes, bodies or constraints from the space

segment_query(start, end, radius, shape_filter)

Query space along the line segment from start to end with the given radius.

segment_query_first(start, end, radius, ...)

Query space along the line segment from start to end with the given radius.

select_body(point)

Select a body by a point.

shape_query(shape)

Query a space for any shapes overlapping the given shape

step(dt)

Update the space for the given time step.

use_spatial_hash(dim, count)

Switch the space to use a spatial hash instead of the bounding box tree.

Attributes

bodies

A list of the bodies added to this space

bodies_extra

collision_bias

Determines how fast overlapping shapes are pushed apart.

collision_persistence

The number of frames the space keeps collision solutions around for.

collision_slop

Amount of overlap between shapes that is allowed.

constraints

A list of the constraints added to this space

current_time_step

Retrieves the current (if you are in a callback from Space.step()) or most recent (outside of a Space.step() call) timestep.

damping

Amount of simple damping to apply to the space.

gravity

Global gravity applied to the space.

idle_speed_threshold

Speed threshold for a body to be considered idle.

iterations

Iterations allow you to control the accuracy of the solver.

shapes

A list of all the shapes added to this space

sleep_time_threshold

Time a group of bodies must remain idle in order to fall asleep.

static_body

A dedicated static body for the space.

threads

The number of threads to use for running the step function.

__init__(*args, screen_width=None, screen_height=None, **kwargs)[source]#

Create a new instance of the Space.

If you set threaded=True the step function will run in threaded mode which might give a speedup. Note that even when you set threaded=True you still have to set Space.threads=2 to actually use more than one thread.

Also note that threaded mode is not available on Windows, and setting threaded=True has no effect on that platform.

Parameters:
  • screen_width (int | None)

  • screen_height (int | None)

__new__(**kwargs)#
add(*objs)#

Add one or many shapes, bodies or constraints (joints) to the space

Unlike Chipmunk and earlier versions of pymunk its now allowed to add objects even from a callback during the simulation step. However, the add will not be performed until the end of the step.

Parameters:

objs (Body | Shape | Constraint)

Return type:

None

add_body(body, shapes=None, selectable=False, label=None)[source]#

Add a body to the space.

Parameters:
  • body – the body to be added.

  • selectable – whether the body is selectable.

  • label – the label of the body.

Returns:

The body added.

Return type:

Body

add_collision_handler(collision_type_a, collision_type_b)#

Return the CollisionHandler for collisions between objects of type collision_type_a and collision_type_b.

Fill the desired collision callback functions, for details see the CollisionHandler object.

Whenever shapes with collision types (Shape.collision_type) a and b collide, this handler will be used to process the collision events. When a new collision handler is created, the callbacks will all be set to builtin callbacks that perform the default behavior (call the wildcard handlers, and accept all collisions).

Parameters:
  • collision_type_a (int) – Collision type a

  • collision_type_b (int) – Collision type b

Return type:

CollisionHandler

add_default_collision_handler()#

Return a reference to the default collision handler or that is used to process all collisions that don’t have a more specific handler.

The default behavior for each of the callbacks is to call the wildcard handlers, ANDing their return values together if applicable.

Return type:

CollisionHandler

add_post_step_callback(callback_function, key, *args, **kwargs)#

Add a function to be called last in the next simulation step.

Post step callbacks are registered as a function and an object used as a key. You can only register one post step callback per object.

This function was more useful with earlier versions of pymunk where you weren’t allowed to use the add and remove methods on the space during a simulation step. But this function is still available for other uses and to keep backwards compatibility.

Note

If you remove a shape from the callback it will trigger the collision handler for the ‘separate’ event if it the shape was touching when removed.

Note

Post step callbacks are not included in pickle / copy of the space.

Parameters:
  • callback_function (func(space : Space, key, *args, **kwargs)) – The callback function

  • key (Any) – This object is used as a key, you can only have one callback for a single object. It is passed on to the callback function.

  • args (Any) – Optional parameters passed to the callback

  • kwargs (Any) – Optional keyword parameters passed on to the callback

Returns:

True if key was not previously added, False otherwise

Return type:

bool

add_wildcard_collision_handler(collision_type_a)#

Add a wildcard collision handler for given collision type.

This handler will be used any time an object with this type collides with another object, regardless of its type. A good example is a projectile that should be destroyed the first time it hits anything. There may be a specific collision handler and two wildcard handlers. It’s up to the specific handler to decide if and when to call the wildcard handlers and what to do with their return values.

When a new wildcard handler is created, the callbacks will all be set to builtin callbacks that perform the default behavior. (accept all collisions in begin() and pre_solve(), or do nothing for post_solve() and separate().

Parameters:

collision_type_a (int) – Collision type

Return type:

CollisionHandler

bb_query(bb, shape_filter)#

Query space to find all shapes near bb.

The filter is applied to the query and follows the same rules as the collision detection.

Note

Sensor shapes are included in the result

Parameters:
  • bb (BB) – Bounding box

  • shape_filter (ShapeFilter) – Shape filter

Return type:

[Shape]

copy()#

Create a deep copy of this object.

Parameters:

self (T)

Return type:

T

debug_draw(options)#

Debug draw the current state of the space using the supplied drawing options.

If you use a graphics backend that is already supported, such as pygame and pyglet, you can use the predefined options in their x_util modules, for example pygame_util.DrawOptions.

Its also possible to write your own graphics backend, see SpaceDebugDrawOptions.

If you require any advanced or optimized drawing its probably best to not use this function for the drawing since its meant for debugging and quick scripting.

Parameters:

options (SpaceDebugDrawOptions)

Return type:

None

get_body_by_label(name)[source]#
Parameters:

name (str)

Return type:

Body

get_body_poses()[source]#
Return type:

Dict[str, Tuple[float, float]]

get_body_states()[source]#
Return type:

Dict[str, Dict[str, Any]]

get_collision_free_pspace(controlling_object, ignore_collision_filter=None, max_diff=2)[source]#
Parameters:

controlling_object (str)

Return type:

PymunkCollisionFreeProblemSpace

point_query(point, max_distance, shape_filter)#

Query space at point for shapes within the given distance range.

The filter is applied to the query and follows the same rules as the collision detection. If a maxDistance of 0.0 is used, the point must lie inside a shape. Negative max_distance is also allowed meaning that the point must be a under a certain depth within a shape to be considered a match.

See ShapeFilter for details about how the shape_filter parameter can be used.

Note

Sensor shapes are included in the result (In Space.point_query_nearest() they are not)

Parameters:
  • point (Vec2d or (float,float)) – Where to check for collision in the Space

  • max_distance (float) – Match only within this distance

  • shape_filter (ShapeFilter) – Only pick shapes matching the filter

Return type:

[PointQueryInfo]

point_query_nearest(point, max_distance, shape_filter)#

Query space at point the nearest shape within the given distance range.

The filter is applied to the query and follows the same rules as the collision detection. If a maxDistance of 0.0 is used, the point must lie inside a shape. Negative max_distance is also allowed meaning that the point must be a under a certain depth within a shape to be considered a match.

See ShapeFilter for details about how the shape_filter parameter can be used.

Note

Sensor shapes are not included in the result (In Space.point_query() they are)

Parameters:
  • point (Vec2d or (float,float)) – Where to check for collision in the Space

  • max_distance (float) – Match only within this distance

  • shape_filter (ShapeFilter) – Only pick shapes matching the filter

Return type:

PointQueryInfo or None

random_body_pos(body=None)[source]#
Parameters:

body (Body | None)

Return type:

Tuple[float, float]

reindex_shape(shape)#

Update the collision detection data for a specific shape in the space.

Parameters:

shape (Shape)

Return type:

None

reindex_shapes_for_body(body)#

Reindex all the shapes for a certain body.

Parameters:

body (Body)

Return type:

None

reindex_static()#

Update the collision detection info for the static shapes in the space. You only need to call this if you move one of the static shapes.

Return type:

None

remove(*objs)#

Remove one or many shapes, bodies or constraints from the space

Unlike Chipmunk and earlier versions of Pymunk its now allowed to remove objects even from a callback during the simulation step. However, the removal will not be performed until the end of the step.

Note

When removing objects from the space, make sure you remove any other objects that reference it. For instance, when you remove a body, remove the joints and shapes attached to it.

Parameters:

objs (Body | Shape | Constraint)

Return type:

None

segment_query(start, end, radius, shape_filter)#

Query space along the line segment from start to end with the given radius.

The filter is applied to the query and follows the same rules as the collision detection.

See ShapeFilter for details about how the shape_filter parameter can be used.

Note

Sensor shapes are included in the result (In Space.segment_query_first() they are not)

Parameters:
Return type:

[SegmentQueryInfo]

segment_query_first(start, end, radius, shape_filter)#

Query space along the line segment from start to end with the given radius.

The filter is applied to the query and follows the same rules as the collision detection.

Note

Sensor shapes are not included in the result (In Space.segment_query() they are)

See ShapeFilter for details about how the shape_filter parameter can be used.

Return type:

SegmentQueryInfo or None

Parameters:
select_body(point)[source]#

Select a body by a point.

Parameters:

point (Tuple[float, float]) – the point to select the body.

Returns:

The body selected. None if no body is selected.

Return type:

Body | None

shape_query(shape)#

Query a space for any shapes overlapping the given shape

Note

Sensor shapes are included in the result

Parameters:

shape (Circle, Poly or Segment) – Shape to query with

Return type:

[ShapeQueryInfo]

step(dt)#

Update the space for the given time step.

Using a fixed time step is highly recommended. Doing so will increase the efficiency of the contact persistence, requiring an order of magnitude fewer iterations to resolve the collisions in the usual case.

It is not the same to call step 10 times with a dt of 0.1 and calling it 100 times with a dt of 0.01 even if the end result is that the simulation moved forward 100 units. Performing multiple calls with a smaller dt creates a more stable and accurate simulation. Therefor it sometimes make sense to have a little for loop around the step call, like in this example:

>>> import pymunk
>>> s = pymunk.Space()
>>> steps = 10
>>> for x in range(steps): # move simulation forward 0.1 seconds:
...     s.step(0.1 / steps)
Parameters:

dt (float) – Time step length

Return type:

None

use_spatial_hash(dim, count)#

Switch the space to use a spatial hash instead of the bounding box tree.

Pymunk supports two spatial indexes. The default is an axis-aligned bounding box tree inspired by the one used in the Bullet Physics library, but caching of overlapping leaves was added to give it very good temporal coherence. The tree requires no tuning, and most games will find that they get the best performance using from the tree. The other available spatial index type available is a spatial hash, which can be much faster when you have a very large number (1000s) of objects that are all the same size. For smaller numbers of objects, or objects that vary a lot in size, the spatial hash is usually much slower. It also requires tuning (usually through experimentation) to get the best possible performance.

The spatial hash data is fairly size sensitive. dim is the size of the hash cells. Setting dim to the average collision shape size is likely to give the best performance. Setting dim too small will cause the shape to be inserted into many cells, setting it too low will cause too many objects into the same hash slot.

count is the suggested minimum number of cells in the hash table. If there are too few cells, the spatial hash will return many false positives. Too many cells will be hard on the cache and waste memory. Setting count to ~10x the number of objects in the space is probably a good starting point. Tune from there if necessary.

Parameters:
  • dim (float) – the size of the hash cells

  • count (int) – the suggested minimum number of cells in the hash table

Return type:

None

property bodies: List[Body]#

A list of the bodies added to this space

property bodies_extra#
property collision_bias: float#

Determines how fast overlapping shapes are pushed apart.

Pymunk allows fast moving objects to overlap, then fixes the overlap over time. Overlapping objects are unavoidable even if swept collisions are supported, and this is an efficient and stable way to deal with overlapping objects. The bias value controls what percentage of overlap remains unfixed after a second and defaults to ~0.2%. Valid values are in the range from 0 to 1, but using 0 is not recommended for stability reasons. The default value is calculated as cpfpow(1.0f - 0.1f, 60.0f) meaning that pymunk attempts to correct 10% of error ever 1/60th of a second.

..Note::

Very very few games will need to change this value.

property collision_persistence: float#

The number of frames the space keeps collision solutions around for.

Helps prevent jittering contacts from getting worse. This defaults to 3.

..Note::

Very very few games will need to change this value.

property collision_slop: float#

Amount of overlap between shapes that is allowed.

To improve stability, set this as high as you can without noticeable overlapping. It defaults to 0.1.

property constraints: List[Constraint]#

A list of the constraints added to this space

property current_time_step: float#

Retrieves the current (if you are in a callback from Space.step()) or most recent (outside of a Space.step() call) timestep.

property damping: float#

Amount of simple damping to apply to the space.

A value of 0.9 means that each body will lose 10% of its velocity per second. Defaults to 1. Like gravity, it can be overridden on a per body basis.

property gravity: Vec2d#

Global gravity applied to the space.

Defaults to (0,0). Can be overridden on a per body basis by writing custom integration functions and set it on the body: pymunk.Body.velocity_func().

property idle_speed_threshold: float#

Speed threshold for a body to be considered idle.

The default value of 0 means the space estimates a good threshold based on gravity.

property iterations: int#

Iterations allow you to control the accuracy of the solver.

Defaults to 10.

Pymunk uses an iterative solver to figure out the forces between objects in the space. What this means is that it builds a big list of all of the collisions, joints, and other constraints between the bodies and makes several passes over the list considering each one individually. The number of passes it makes is the iteration count, and each iteration makes the solution more accurate. If you use too many iterations, the physics should look nice and solid, but may use up too much CPU time. If you use too few iterations, the simulation may seem mushy or bouncy when the objects should be solid. Setting the number of iterations lets you balance between CPU usage and the accuracy of the physics. Pymunk’s default of 10 iterations is sufficient for most simple games.

property shapes: List[Shape]#

A list of all the shapes added to this space

(includes both static and non-static)

property sleep_time_threshold: float#

Time a group of bodies must remain idle in order to fall asleep.

The default value of inf disables the sleeping algorithm.

property static_body: Body#

A dedicated static body for the space.

You don’t have to use it, but many times it can be convenient to have a static body together with the space.

property threads: int#

The number of threads to use for running the step function.

Only valid when the Space was created with threaded=True. Currently the max limit is 2, setting a higher value wont have any effect. The default is 1 regardless if the Space was created with threaded=True, to keep determinism in the simulation. Note that Windows does not support the threaded solver.