0

I defined a function named add_spring in the following code

import pymunk
import pymunk.pygame_util
import math

pygame.init()
wid, hei = 800, 700
window = pygame.display.set_mode((wid, hei))


def draw(space, window, draw_options):
    window.fill("white")
    space.debug_draw(draw_options)
    pygame.display.update()

def wall(space, wid, hei):
    rects = [
        [(wid/2, hei - 10), (wid, 20)],
        [(wid/2, 10), (wid, 20)]
    ]
    for pos, size in rects:
        body = pymunk.Body(body_type=pymunk.Body.STATIC)
        body.position = pos
        shape  = pymunk.Poly.create_box(body, size)
        shape.elasticity = 0.4
        shape.friction = 0.5
        space.add(body, shape)

def create_ball(space, radius, mass):
    body = pymunk.Body()
    body.position = (500, 350)
    shape = pymunk.Circle(body, radius)
    shape.mass = mass
    shape.color = (55, 0, 0, 100)
    space.add(body, shape)
    shape.elasticity = 0.9
    shape.friction = 0.4
    return shape

def add_ball(space):
    body = pymunk.Body()
    body.position = (500, 500)
    shape = pymunk.Circle(body, 20)
    shape.mass = 1
    shape.friction = 0.7
    space.add(body, shape)
    return body

def create_ball_a(space, radius, mass):
    body = pymunk.Body(body_type=pymunk.Body.STATIC)
    body.position = (500, 300)
    shape = pymunk.Circle(body, radius)
    shape.mass = mass
    shape.color = (55, 0, 0, 100)
    space.add(body, shape)
    shape.elasticity = 0.9
    shape.friction = 0.4
    return shape

def create_ball_b(space, radius, mass):
    body = pymunk.Body(body_type=pymunk.Body.STATIC)
    body.position = (550, 300)
    shape = pymunk.Circle(body, radius)
    shape.mass = mass
    shape.color = (55, 0, 0, 100)
    space.add(body, shape)
    shape.elasticity = 0.9
    shape.friction = 0.4
    return shape
def add_spring(var1, var2):
    dlx = pymunk.DampedSpring(var1, var2, (0, 0), (0, 0), 5, 70, 0)
    space.add(dlx)



def run(window, wid, hei):
    run = True
    clock = pygame.time.Clock()
    fps = 60
    dt = 1 / fps
    space = pymunk.Space()
    space.gravity = (0, 981)
    big_ball = create_ball(space, 30, 10)
    joina = create_ball_a(space, 5, 10)
    joinb = create_ball_b(space, 5, 10)
    j = pymunk.DampedSpring(big_ball.body, joina.body, (0, 0), (0, 0), 5, 70, 0)
    space.add(j)
    add_spring(joina, big_ball)
    space.add(pymunk.DampedSpring(big_ball.body, joinb.body, (0, 0), (0, 0), 100, 100, 10))
    wall(space, wid, hei)
    draw_options = pymunk.pygame_util.DrawOptions(window)

    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                break
        draw(space, window, draw_options)
        space.step(dt)
        clock.tick(fps)
    pygame.quit()

if __name__ == "__main__":
    run(window, wid, hei)

But the following error shows up when I run it.

pygame 2.0.1 (SDL 2.0.14, Python 3.8.9)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "e:/pymunk/2D-cloth-simulation/string_d.py", line 104, in <module>
    run(window, wid, hei)
  File "e:/pymunk/2D-cloth-simulation/string_d.py", line 88, in run
    add_spring(joina, big_ball)
  File "e:/pymunk/2D-cloth-simulation/string_d.py", line 71, in add_spring
    dlx = pymunk.DampedSpring(var1, var2, (0, 0), (0, 0), 5, 70, 0)
  File "C:\Users\Kishlay\AppData\Local\Programs\Python\Python38\lib\site-packages\pymunk\constraints.py", line 617, in __init__
    _constraint = lib.cpDampedSpringNew(
TypeError: initializer for ctype 'struct cpBody *' must be a cdata pointer, not Body

When I do the same thing without defining a function for it, it works, but in order to keep the code clean, I need it to convert it to a function so that I can do it multiple times without hassle.

1 Answers1

2

You have two mistakes.

  1. It needs .body (like in other DampedSpring in your code)

    You can get it from var1, var2:

    dlx = pymunk.DampedSpring(var1.body, var2.body, (0, 0), (0, 0), 5, 70, 0)
    

    Or you can send .body:

    add_spring(joina.body, big_ball.body)
    
  2. You have to send also space to this function (to run space.add()

    Get it in function:

    def add_spring(space, var1, var2):
    

    Send it to function:

    add_spring(space, joina.body, big_ball.body)
    

Full code:

import pygame
import pymunk
import pymunk.pygame_util
import math

# --- constants ---  # PEP8: `UPPER_CASE_NAMES`

WIDTH = 800
HEIGHT = 700
FPS = 60

# --- functions ---  # PEP8: all function before main code

def draw(space, window, draw_options):
    window.fill("white")
    space.debug_draw(draw_options)
    pygame.display.update()

def wall(space, width, height):
    rects = [
        [(width/2, height - 10), (width, 20)],
        [(width/2, 10), (width, 20)]
    ]
    
    for pos, size in rects:
        body = pymunk.Body(body_type=pymunk.Body.STATIC)
        body.position = pos
        
        shape  = pymunk.Poly.create_box(body, size)
        shape.elasticity = 0.4
        shape.friction = 0.5
        
        space.add(body, shape)

def create_ball(space, radius, mass):
    body = pymunk.Body()
    body.position = (500, 350)
    
    shape = pymunk.Circle(body, radius)
    shape.mass = mass
    shape.color = (55, 0, 0, 100)
    shape.elasticity = 0.9
    shape.friction = 0.4

    space.add(body, shape)
    
    return shape

def add_ball(space):
    body = pymunk.Body()
    body.position = (500, 500)
    
    shape = pymunk.Circle(body, 20)
    shape.mass = 1
    shape.friction = 0.7
    
    space.add(body, shape)
    
    return body

def create_ball_a(space, radius, mass):
    body = pymunk.Body(body_type=pymunk.Body.STATIC)
    body.position = (500, 300)
    
    shape = pymunk.Circle(body, radius)
    shape.mass = mass
    shape.color = (55, 0, 0, 100)
    shape.elasticity = 0.9
    shape.friction = 0.4
    
    space.add(body, shape)
    
    return shape

def create_ball_b(space, radius, mass):
    body = pymunk.Body(body_type=pymunk.Body.STATIC)
    body.position = (550, 300)
    
    shape = pymunk.Circle(body, radius)
    shape.mass = mass
    shape.color = (55, 0, 0, 100)
    shape.elasticity = 0.9
    shape.friction = 0.4

    space.add(body, shape)
    
    return shape

def add_spring(space, body1, body2):
    dlx = pymunk.DampedSpring(body1, body2, (0, 0), (0, 0), 5, 70, 0)
    
    space.add(dlx)
    
    return dlx

def run(WIDTH, HEIGHT):
    pygame.init()
    window = pygame.display.set_mode((WIDTH, HEIGHT))

    dt = 1 / FPS

    clock = pygame.time.Clock()
    
    space = pymunk.Space()
    space.gravity = (0, 981)
    
    big_ball = create_ball(space, 30, 10)
    joina = create_ball_a(space, 5, 10)
    joinb = create_ball_b(space, 5, 10)
    
    j = pymunk.DampedSpring(big_ball.body, joina.body, (0, 0), (0, 0), 5, 70, 0)
    space.add(j)
    
    add_spring(space, joina.body, big_ball.body)
    
    space.add(pymunk.DampedSpring(big_ball.body, joinb.body, (0, 0), (0, 0), 100, 100, 10))
    
    wall(space, WIDTH, HEIGHT)
    draw_options = pymunk.pygame_util.DrawOptions(window)

    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                break
            
        draw(space, window, draw_options)
        
        space.step(dt)
        clock.tick(FPS)
        
    pygame.quit()

if __name__ == "__main__":
    run(WIDTH, HEIGHT)

PEP 8 -- Style Guide for Python Code

furas
  • 134,197
  • 12
  • 106
  • 148