I Tried to set up a simple ball that would fall using pymunk, but after two frames of running, the print statement outputs Vec2d(nan, nan), and the ball is no longer drawn to the screen.
import pymunk
import pygame
screen = pygame.display.set_mode((500,500))
space = pymunk.Space()
space.gravity = (0,9)
body = pymunk.Body(mass = 20,body_type = pymunk.Body.DYNAMIC)
shape = pymunk.Circle(body,25)
body.position = (250,250)
space.add(body,shape)
clock = pygame.time.Clock()
done = False
while not done:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill((255,255,255))
pygame.draw.circle(screen,(0,0,0),body.position,25)
pygame.display.flip()
print(body.position)
space.step(1/50)
This is the code I wrote, which I expected would draw a ball which would fall off of the screen, but instead it appeared unmoving for two frames, before vanishing.
Even if you solved the issue i might as well clarify some points.
As the documentation says, pymunk needs to estimate the moment of a body to be able to calculate its position. To achieve this, pymunk has its own moment objects to perform this hard calculation.
The solution you applied adds the mass after the object creation and so the moment object will be automatically created later, but another way to do it is to specify at Body object creation both the mass and the moment of the body. In fact the documentation individuates exactly these two ways to create a body, and you can go there for more details. The manual creation of the moment object to pass as parameter of
pymunk.Body()is a more flexible approach though.Here i modified your code with this alternative approach:
Note that i also increased the gravity to adjust the time in milliseconds (and not seconds) of the mainloop.
The main thing to remember here is that you should choose a way to create your pymunk shapes and bodies and you should stick to it without mixing the methods.
You can:
ShapeobjectBodydensityattribute of the Shape object