SkillAgentSearch skills...

PyPhysicsSandbox

pyPhysicsSandbox is a simple wrapper around Pymunk that makes it easy to write code to explore 2D physics simulations. It's intended for use in introductory programming classrooms.

Install / Use

/learn @jshaffstall/PyPhysicsSandbox
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Synopsis

pyPhysicsSandbox is a simple wrapper around Pymunk that makes it easy to write code to explore 2D physics simulations. It's intended for use in introductory programming classrooms.

Caution! The simulation does not behave well if you start out with shapes overlapping each other, especially if overlapping shapes are connected with joints. To have overlapping shapes connected by joints, set the group on each shape to the same number to disable collision detection between those shape.

On the other hand, see the volcano example for a situation where overlapping shapes that collide with each other are useful.

Shapes far enough outside the simulation window (generally, above or below by the height of the window, or to either side by the width of the window) are automatically removed from the simulation and their active property set to False. The distance can be modified, but be wary of making it too large...this keeps shapes that are not visible in the simulation and can slow the simulation down if the number of shapes grows too large.

Code Example

from pyphysicssandbox import *

window("My Window", 400, 300)
gravity(0.0, 500.0)

b1          = ball((100, 10), 30)
b1.color    = Color('green')
b1.friction = 0.25

b2       = static_ball((98, 100), 30)
b2.color = Color('blue')

box1       = static_rounded_box((0, 290), 400, 10, 3)
box1.color = Color('red')

tri1       = triangle((260, 35), (250, 35), (240, -15))
tri1.color = Color('red')

poly1       = polygon(((195, 35), (245, 35), (220, -15)))
poly1.color = Color('blue')
poly1.wrap  = True

run()

print('Done!')

Motivation

My introductory programming students love writing physics simulations, but the previous physics engine we used did not expose enough features (pins and motors, for example) to be interesting enough to more advanced students. PyPhysicsSandbox retains the simplicity needed for intro programming students, but exposes more advanced tools.

Also, being IDE agnostic, this library can be used with your favorite IDE.

In Use At

If you use PyPhysicsSandbox, let me know where and I'll add you here.

Muskingum University for their Intro to Computer Science course

John Glenn High School for their after school coding club

Summary of Features

pyPhysicsSandbox provides an easy Python interface to a rigid-body physics sandbox. Features include:

Shapes

  • Circles
  • Rectangles
  • Triangles
  • Solid Polygons (both convex and concave)
  • Line Segments
  • Text

Constraints

  • Pivot Joints
  • Pin Joints
  • Motors
  • Slip Motors
  • Springs
  • Gears

Other

  • User Specified Collision Handlers
  • User Specified Observer Functions
  • Disable Collisions Between Specific Objects
  • Custom Shape Properties - color, friction, gravity, damping, elasticity
  • Set shapes to constant velocities
  • Allow Shapes to Wrap Around the Screen
  • Conveyor Belt Like Behavior
  • Pasting One Shape Onto Another - so they behave as one shape
  • Hit shapes in a specific direction with a given force
  • Handles Thousands of Shapes
  • Built in debug output that can be turned on for individual shapes

Tutorials

Screencasts highlighting various features of the sandbox are available on the PyPhysicsSandbox YouTube channel

Installation

Python 3

https://www.python.org/

This library was written with Python 3.5, but should run on any Python 3. Python 3 must be installed first.

pyPhysicsSandbox

Given a suitable Python 3 installation, you should be able to install pyPhysicsSandbox by opening a command prompt in the Scripts folder of your Python installation and typing:

pip install pyphysicssandbox

Dependencies

http://www.pygame.org/ http://www.pymunk.org/

Both pygame and pymunk should be automatically installed when you install pyPhysicsSandbox. If something goes wrong and you need to install them manually, see their respective sites for directions.

API Reference

Simulation-wide functions

window(caption, width, height)

Specifies the width and height and caption of the simulation window. Multiple calls to this overwrite the old values. You only get one window regardless.

set_margins(x, y)

Sets the minimum distance outside the visible window a shape can be and still be in the simulation. Outside of this distance the shape is deactivated. The default x margin is the window's width and the default y margin is the window's height.

Note that if you create a shape and give it an initial position outside these margins, the simulation will expand the margins to include the shape.

Use set_margins to increase the y margin particularly if you expect a shape on screen to be fired high above the top of the screen.

color(v)

Sets the default color for shapes drawn after this function is called. Color must be a string containing a valid color name.

See https://sites.google.com/site/meticulosslacker/pygame-thecolors for a list of colors. Hover your mouse over a color to see its name.

gravity(x, y)

Sets the gravity of the simulation. Positive y is downward, positive x is rightward. Default is (0, 500).

resistance(v)

Sets how much velocity each object in the simulation keeps each second. Must be a floating point number. Default is 0.95. Values higher than 1.0 cause objects to increase in speed rather than lose it. A value of 1.0 means objects will not lose any velocity artificially.

add_observer(observer_func)

Provide a function of yours that will get called once per frame. In this function you can use the various objects you've created to either affect the simulation or simply measure something.

You may call add_observer multiple times to add different observer functions.

The function should be defined like this:

        def function_name(keys):
            # do something each time step

The observer function must take a single parameter which is a list of keys pressed this step. To see if a particular key has been pressed, use something like this:

            if constants.K_UP in keys:
                # do something based on the up arrow being pressed
mouse_clicked ()

Returns True if the mouse has been clicked this time step. Usable only in an observer function.

mouse_point ()

Returns the current location of the mouse pointer as an (x, y) tuple.

If the mouse is out of the simulation window, this will return the last location of the mouse that was in the simulation window.

num_shapes()

Returns the number of active shapes in the simulation. Mostly useful for debugging.

deactivate(shape)

Removes the given shape from the simulation.

reactivate(shape)

Adds the given shape back to the simulation.

add_collision(shape1, shape2, handler)

Tells the sandbox to call a function when the two given shapes collide. The handler function is called once per collision, at the very start of the collision.

The handler function is passed three parameters. The first two are the colliding shapes, the third is the point of the collision, e.g.:

        handler(shape1, shape2, p)

The handler function must return True to allow the collision to happen. If the handler returns False, then the collision will not happen.

Note that you will never have a collision with a deactivated object or with a cosmetic object.

run(do_physics=True)

Call this after you have created all your shapes to actually run the simulation. This function returns only when the user has closed the simulation window.

Pass False to this method to do the drawing but not activate physics. Useful for getting the scene right before running the simulation.

draw()

Call this after you have created all your shapes to draw the shapes. This function returns only when the user has closed the window.

This is an alias for run(False).

Shape creation functions

All the shapes have both a static and cosmetic variation shown.

Static shapes will interact with the physics simulation but will never move. Other shapes will collide with the static shapes, but the static shapes are immovable objects.

Cosmetic shapes also will never move, but they also do not interact with the physics simulation in any way. Other shapes will fall through the cosmetic shapes. This means you may not also use a cosmetic shape as part of a paste_on call.

ball(p, radius, mass)
static_ball(p, radius)
cosmetic_ball(p, radius)

Create a ball object and return its instance.

p is a tuple containing the x and y coordinates of the center of the ball.

You can omit the mass parameter and the mass will be set proportional to the area of the shape.

box(p, width, height, mass)
static_box(p, width, height)
cosmetic_box(p, width, height)

Create a box object and return its instance.

p is a tuple containing the x and y coordinates of the upper left corner of the box.

You can omit the mass parameter and the mass will be set proportional to the area of the shape.

rounded_box(p, width, height, radius, mass)
static_rounded_box(p, width, height, radius)
cosmetic_rounded_box(p, width, height, radius)

Create a box object and returns its instance. These boxes are drawn with rounded corners.

p is a tuple containing the x and y coordinates of the upper left corner of the box. radius is the radius of the corner curve. 3 works well, but you can pass any integer.

You can omit the mass parameter and the mass will be set proportional to the area of the shape.

triangle(p1, p2, p3, mass)
static_triangle(p1, p2, p3)
cosmetic_triangle(p1, p2, p3)

Creates a triangle out of the given points and returns its instance.

You can omit the mass parameter and the mass will be set proportional to the area of the shape.

View on GitHub
GitHub Stars48
CategoryEducation
Updated5mo ago
Forks9

Languages

Python

Security Score

92/100

Audited on Oct 6, 2025

No findings