Hi,

I'm a new user of ODE, working with the PyODE interface in order to build games with PyGame. I've written a test program (attached) but it doesn't seem to work right. Basically, it involves two objects (a box and a sphere) dropping onto a floor (a plane). When they collide with the floor, they are supposed to stop.

It all works fine, until I give the objects mass. Once I add the following lines:

        M = ode.Mass()
        M.setSphere(10, self.radius)
        self.body.setMass(M)

The Circle object starts to significantly penetrate the floor, and bounce a lot. It eventually comes to rest half-embedded in the floor.

If I reduce the density from 10 to 1, the problem is significantly reduced, but still there is a lot of bouncing before the objects come to rest on the surface.

Can anyone explain what is going on here?

Thanks,

Malcolm
--
           "Cleanliness is not next to godliness nowadays,
                for cleanliness is made an essential
              and godliness is regarded as an offence.
                                    - G.K.Chesterton, On Lying in Bed

import pygame, ode
from pygame.locals import *

SCREENRECT = Rect(0, 0, 800, 600)
TRANSPARENT = (1,2,3)

class Circle(pygame.sprite.Sprite):
    def __init__(self, world, space, (x,y), r):
        pygame.sprite.Sprite.__init__(self, self.containers)
        
        self.image = pygame.Surface((r*2+1, r*2+1))
        self.image.fill(TRANSPARENT)
        self.image.set_colorkey(TRANSPARENT)

        pygame.draw.circle(self.image, (255,0,0), (r, r), r)
        pygame.draw.circle(self.image, (0,0,0), (r, r), r, 1)

        self.rect = self.image.get_rect(center=(x,y))
        self.hitmask = pygame.surfarray.array_colorkey(self.image)

        self.body = ode.Body(world)
        self.body.setPosition((x,y,0))

        # comment out these lines to make it work
        M = ode.Mass()
        M.setSphere(10, r)
        self.body.setMass(M)

        geom = ode.GeomSphere(space, r)
        geom.setBody(self.body)
        geom.setCollideBits(1)

        self.join2d = ode.Plane2DJoint(world)
        self.join2d.attach(self.body, ode.environment)        

    def update(self):
        (x,y,z) = self.body.getPosition()        
        self.rect.center = (x,y)


class Block(pygame.sprite.Sprite):
   
    def __init__(self, world, space, rect):
        pygame.sprite.Sprite.__init__(self, self.containers)
        
        x = rect.centerx
        y = rect.centery
        w = rect.width
        h = rect.height
                       
        self.image = pygame.Surface((w, h))
        
        r = Rect(0,0,w,h)
        pygame.draw.rect(self.image, (0,255,0), r)
        pygame.draw.rect(self.image, (0,0,0), r, 1)

        self.rect = self.image.get_rect(center=rect.center)

        self.body = ode.Body(world)
        self.body.setPosition((x,y,0))

        # comment out these lines to make it work
        M = ode.Mass()
        M.setBox(10, w, h, 10)
        self.body.setMass(M)

        geom = ode.GeomBox(space, (w,h, 10))
        geom.setBody(self.body)
        geom.setCollideBits(1)

        self.join2d = ode.Plane2DJoint(world)
        self.join2d.attach(self.body, ode.environment)        

    def update(self):
        (x,y,z) = self.body.getPosition()        
        self.rect.center = (x,y)


# Collision callback
def collision(args, geom1, geom2):
    """Callback function for the collide() method.

    This function checks if the given geoms do collide and
    creates contact joints if they do.
    """

    # Check if the objects do collide
    contacts = ode.collide(geom1, geom2)

    # Create contact joints
    world,contactgroup = args
    for c in contacts:
        c.setBounce(0.0)
        c.setMu(5000)
        j = ode.ContactJoint(world, contactgroup, c)
        j.attach(geom1.getBody(), geom2.getBody())

def main():

    pygame.init()

    bestdepth = pygame.display.mode_ok(SCREENRECT.size, 0, 32)
    screen = pygame.display.set_mode(SCREENRECT.size, 0, bestdepth)

    world = ode.World()
    world.setGravity((0,9.81,0))
    space = ode.Space()

    contactgroup = ode.JointGroup()

    background = pygame.Surface(SCREENRECT.size)
    background.fill((255,255,255))

    fh = 50
    fy = SCREENRECT.height - fh
    floor = ode.GeomPlane(space, (0,-1,0), -fy)
    floor.setCollideBits(1)

    fr = Rect(0, fy, SCREENRECT.width, fh)
    pygame.draw.rect(background, (0,0,0), fr, 1)

    screen.blit(background, (0,0))
    pygame.display.flip()

    # assign default groups to each sprite class
    all = pygame.sprite.RenderUpdates()
    Block.containers = all
    Circle.containers = all

    rect = Rect(200,300,50,50)
    Block(world, space, rect)

    Circle(world, space, (400,325), 25)

    clock = pygame.time.Clock()

    while True:
        #cap the framerate
        dt = clock.tick(60) / 1000.0
                
        pygame.event.pump()
        for event in pygame.event.get():
            if event.type == QUIT or \
            (event.type == KEYDOWN and event.key == K_ESCAPE):
                return                

        # run the ODE sim

        n = 2
        for i in range(n):

            # Detect collisions and create contact joints
            space.collide((world,contactgroup), collision)

            # Simulation step
            world.step(dt / n)

            # Remove all contact joints    
            contactgroup.empty()

        # clear/erase the last drawn sprites
        all.clear(screen, background)

        # update all the sprites
        all.update()

        #draw the scene
        dirty = all.draw(screen)
        pygame.display.update(dirty)

if __name__ == '__main__': main()


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Pyode-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/pyode-user

Reply via email to