viblo / pymunk

Pymunk is a easy-to-use pythonic 2d physics library that can be used whenever you need 2d rigid body physics from Python
http://www.pymunk.org
MIT License
931 stars 191 forks source link

Body.sleep doesn't seem to work properly #251

Open Python-ZZY opened 4 months ago

Python-ZZY commented 4 months ago

When I call sleep on a body,the window keeps sticking and the program exits automatically(I use IDLE as my program editor). Is there a problem?

viblo commented 4 months ago

Humm, sounds strange. The best is if you can make a small example that reproduces this error, otherwise its difficult to troubleshoot.

Also, if you see any error print out please write them here as well.

Python-ZZY commented 4 months ago

Humm, sounds strange. The best is if you can make a small example that reproduces this error, otherwise its difficult to troubleshoot.

Also, if you see any error print out please write them here as well.

There may be a problem with my statement, it seems that the program is stuck while calling sleep() instead of debug_draw(). Here is an example, when you click the mouse will only print "start call sleep()", and then the window remains unresponsive, after a period of time automatically quit with no error.

import pymunk
import pygame as pg
import sys
from pymunk.pygame_util import DrawOptions

screen = pg.display.set_mode((1000, 600))
draw_options = DrawOptions(screen)

space = pymunk.Space()
space.gravity = (0, 100)

body = pymunk.Body()
body.position = (100, 100)
shape = pymunk.Circle(body, 20)
shape.mass = 1
space.add(body, shape)

clock = pg.time.Clock()
while True:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            pg.quit()
            sys.exit()
        elif event.type == pg.MOUSEBUTTONDOWN and event.button == 1:
            ## click the left button of the mouse
            print("start call sleep()")
            body.sleep()
            print("end call sleep()")

    screen.fill((255, 255, 255))

    print("Start debug_draw()")
    space.debug_draw(draw_options)
    print("End debug_draw()")

    space.step(1 / 60)

    pg.display.flip()
    clock.tick(60)
viblo commented 4 months ago

Ah Then I understand. You can see the error printed out I believe:

start call sleep()
Aborting due to Chipmunk error: Sleeping is not enabled on the space. You cannot sleep a body without setting a sleep time threshold on the space.
        Failed condition: cpSpaceGetSleepTimeThreshold(space) < INFINITY
        Source:Chipmunk2D\src\cpSpaceComponent.c:321

When you run it in idle, do you see both the print lines you added and also the Aborting error?

The error is because you did not set a sleep threshold on the space: http://www.pymunk.org/en/latest/pymunk.html#pymunk.Space.sleep_time_threshold

In your code you can set it right after you set the gravity, like this:

space = pymunk.Space()
space.gravity = (0, 100)
space.sleep_time_threshold = 100 # some value here.. 

When you manual call the sleep the value of sleep_time_threshold does not matter as long as its more than 0 and less than infinity. If you want Pymunk to automatically put bodies to sleep when they are still, then this value control how long to wait.

If you want a full example how it can work you can check the box2d_pyramid.py example https://github.com/viblo/pymunk/blob/master/pymunk/examples/box2d_pyramid.py (from the command line you can run it by python -m pymunk.examples.box2d_pyramid)

viblo commented 4 months ago

Answering myself: No, the error is not printed when run from IDLE. I will investigate a bit how to improve this, very difficult to find out whats wrong if you dont see the error!