Page 1 of 1

Static Circle Pymunk

Posted: Fri Jul 16, 2010 7:42 am
by jmachete
Hi Guys, Im trying to do a simple static circle and some balls colliding with it, but when I use the method space.add_static(body, shape) is given an error. Maybe is not the correct way to do static circle with colisions....

this is the code Im using to draw the small balls and the main static circle called group:

Code: Select all

def add_ball(space): #balls
    mass = 1
    radius = 10
    inertia = pm.moment_for_circle(mass, 0, radius, Vec2d(0,0))
    body = pm.Body(mass, inertia)
    x = random.randint(120,380)
    body.position = x, 550
    shape = pm.Circle(body, radius, Vec2d(0,0))
    space.add(body, shape)
    return shape

def add_group(space): #groups
    mass = 1
    radius = 40
    inertia = pm.moment_for_circle(mass, 0, radius, Vec2d(0,0))
    body = pm.Body(mass, inertia)
    x = random.randint(120,380)
    #y = random.randint(480,120)
    body.position = x, 550
    shape = pm.Circle(body, radius, Vec2d(0,0))
    space.add(body, shape)
    #space.add_static(body, shape)
    return shape

def draw_ball(screen, ball): #draw the falling balls to teh screen
    p = int(ball.body.position.x), 600-int(ball.body.position.y)
    pygame.draw.circle(screen, (0, 255, 072), p, int(ball.radius), 0)

def draw_group(screen, ball): #draw the static group on the screen
    p = int(ball.body.position.x), 600-int(ball.body.position.y)
    pygame.draw.circle(screen, (0, 136, 252), p, int(ball.radius), 0) 

Hope someone can give me a advice.... :)

Re: Static Circle Pymunk

Posted: Fri Jul 16, 2010 11:25 am
by slembcke
For something to be a static shape it needs to have an infinite mass and moment of inertia. That makes it so that it cannot be moved when something collides with it. You also shouldn't add it to the space because you don't want it to simulate falling under gravity.

Also, you mentioned that it gave you an error, but not what the error is.

Re: Static Circle Pymunk

Posted: Fri Jul 16, 2010 7:33 pm
by viblo
The error probably says that 'Body object is not an 'iterable'. Its because the method doesnt accept bodies as input for the reasons slembcke wrote.

The method definition is add_static(*objs) so its very flexible, you can send in many shapes at once in many different ways if you want, for example like this:

Code: Select all

space.add_static(s1)
space.add_static(s1,s2,s3)
space.add_static(s1,[s2,s3])
space.add_static([s1,(s2,s3), s4, [s5]])
The downside of this is the bad error message you get when the object is not a shape or an 'iterable' of shapes..

Re: Static Circle Pymunk

Posted: Sun Jul 18, 2010 9:28 am
by jmachete
Hi guys, yes...the error was "line 173, in add_static, for oo in o: TypeError: 'Body' object is not iterable".
@slembcke and @vibro thanks for the advice, now everything works fine.

The next step I wanted to do is connect each ball to the static main ball"group" through a constrain, like a rope with some elasticity...Im thinking in use the Pin join or damped spring, but Im a little confuse how I can implement that.

To set a constrains between two objects should I do something like this?

pymunk.PinJoint(self, a, b, anchr1, anchr2)
or
pymunk.DampedSpring(self, a, b, anchr1, anchr2, rest_length, stiffness, damping)

Look foward to ear some advice.....

I include here the code of the exercise for better understanding.

Code: Select all

import pygame, sys, random
from pygame.locals import *
from pygame.color import *
import pymunk as pm
from pymunk import Vec2d

def add_ball(space): #balls
    mass = 1
    radius = 10
    inertia = pm.moment_for_circle(mass, 0, radius, Vec2d(0,0))
    body = pm.Body(mass, inertia)
    x = random.randint(120,380)
    body.position = x, 550
    shape = pm.Circle(body, radius, Vec2d(0,0))
    space.add(body, shape)
    return shape

def add_group(space): #groups
    radius = 50
    body = pm.Body(pm.inf, pm.inf)
    x = random.randint(120,380)
    y = random.randint(200,350)
    body.position = x, y
    shape = pm.Circle(body, radius, Vec2d(0,0))
    shape.friction = 1.00
    space.add_static(shape)
    return shape

def draw_ball(screen, ball): #draw the falling balls to the screen
    p = int(ball.body.position.x), 600-int(ball.body.position.y)
    pygame.draw.circle(screen, (0, 255, 072), p, int(ball.radius), 0)

def draw_group(screen, ball): #draw the static group on the screen
    p = int(ball.body.position.x), 600-int(ball.body.position.y)
    pygame.draw.circle(screen, (0, 136, 252), p, int(ball.radius), 0) 

def main():
    pygame.init()
    background = (255, 255, 255)
    w=640
    h= 480
    screen=pygame.display.set_mode((w,h),0,32)
    pygame.display.set_caption("FCQView")
    clock = pygame.time.Clock()
    running = True

    points=[(20,120),(140,140),(110,30)]
    color=(255,255,0)
    gravity = -900.0

    #Create Physics
    pm.init_pymunk()
    space = pm.Space()
    space.gravity = Vec2d(0.0, gravity)

    space.resize_static_hash()
    space.resize_active_hash()    

    #groups
    group = add_group(space)

    #balls
    balls= []

    ticks_to_next_ball = 10

    #main loop
    while running:
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                running = False

        ticks_to_next_ball -= 1
        
        if ticks_to_next_ball <= 0:
            ticks_to_next_ball = 25
            ball_shape = add_ball(space)
            balls.append(ball_shape)
            
        screen.fill(background)

        # Draw stuff
        draw_group(screen, group) #draw the groups

        balls_to_remove = []
        
        for ball in balls: 
            draw_ball(screen, ball)#draw the balls
            if ball.body.position.y < 100:#remove the balls after they fall
                balls_to_remove.append(ball)

        for ball in balls_to_remove:
            space.remove(ball, ball.body)
            balls.remove(ball)            
                   
        # Update physics
        dt = 1.0/60.0
        for x in range(1):
            space.step(dt)
            
        # Flip screen
        pygame.display.flip()
        clock.tick(50)
        pygame.display.set_caption("fps: " + str(clock.get_fps()))

if __name__ == '__main__':
    sys.exit(main())
    

Re: Static Circle Pymunk

Posted: Sun Jul 18, 2010 1:35 pm
by jmachete
Ok forget my last post, now its working the constrains but how I can draw the constrain on the screen? right now its invisible...

any clue? How I can get the coordinates of the constrain? im a little bit confuse :(


Thanks

Re: Static Circle Pymunk

Posted: Mon Jul 19, 2010 6:44 pm
by viblo
It depends on the constraint. If its a PinJoint then the easiest is to draw a line between the end points of it. Thats the way I did it in the newtons_cradle.py example that is included in pymunk:

Code: Select all

for c in space.constraints:
    pv1 = c.a.position + c.anchr1
    pv2 = c.b.position + c.anchr2
    p1 = to_pygame(pv1)
    p2 = to_pygame(pv2)
    pygame.draw.aalines(screen, THECOLORS["lightgray"], False, [p1,p2])
If you need inspiration on how to draw the constraints check out the nice video from the chipmunk documentation: http://www.youtube.com/watch?v=ZgJJZTS0aMM I often take a look there to get some visual help on what the different constraints do :)

Re: Static Circle Pymunk

Posted: Wed Jul 21, 2010 3:51 am
by jmachete
Thanks @viblo I will try and then post here the result...

;)