[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] PyODE
I attached my little test from a year ago (I forgot to attach it to my first reply). It's been a while since I looked at it, but I think your last value of the planes are wrong. In my example they are:
frontwall =
ode.GeomPlane(sp,normal=(0,0,1),dist=-1)
backwall = ode.GeomPlane(sp,normal=(0,0,-1),dist=-1)
Both are -1. I forget the math, but the distance is basically moving the plane against the normal that amount. So for the normal pointing into the screen, you want to move it OUT of the screen by 1, which is against the normal, hence the minus. For the normal pointing out of the screen you want to move it IN - again against the normal, again -1. This way you have two planes that are pointing toward each other keeping anything between them locked in.
What you had I think with the +1 and -1 was two planes with opposite normals located at the same z value.
import pygame
import ode
class colmesh:
def __init__(self):
self.mesh = None
self.body = None
def add_to_space(self,space):
space.add(self.mesh)
def addbody(self,body):
if not self.body:
self.body = body
if self.mesh:
self.mesh.setBody(body.body)
if not self.body.mesh:
self.body.addmesh(self)
class raymesh(colmesh):
def __init__(self,pos,dir,length=1000):
colmesh.__init__(self)
self.pos = pos
self.dir = dir
self.length = length
self.mesh = ode.GeomRay(None,self.length)
self.mesh.set(self.pos,self.dir)
class TriMesh(colmesh):
def __init__(self,file):
colmesh.__init__(self)
f = open(file)
verts,faces = eval(f.read())
f.close()
self.data = ode.TriMeshData()
self.data.build(verts,faces)
self.mesh = ode.GeomTriMesh(self.data,space)
class BoxMesh(colmesh):
def __init__(self,dimensions=[1.0,1.0,1.0]):
self.dimensions = dimensions
colmesh.__init__(self)
self.mesh = ode.GeomBox(None,dimensions)
class body(object):
def __init__(self,colworld,pos=[0.0,0.0,0.0],mass=1.0,density=2500.0,sphere=None,box=None):
self.body = ode.Body(colworld.wo)
self.pos = pos
self.mass = ode.Mass()
if box:
self.mass.setBox(density,*box)
if sphere:
self.mass.setSphere(density,sphere)
self.mass.mass = mass
def __setattr__(self,attr,val):
object.__setattr__(self,attr,val)
if attr == "pos":
self.body.setPosition(val)
def addmesh(self,mesh):
self.mesh = mesh
if not self.mesh.body:
self.mesh.addbody(self)
class CollisionWorld:
def __init__(self):
self.sp = ode.Space()
self.wo = ode.World()
self.joints = ode.JointGroup()
def addStatic(self,mesh):
mesh.add_to_space(self.sp)
def raytest(self,pos,dir):
ray = raymesh(pos,dir)
cols = []
for geom in self.sp:
cols.extend(ode.collide(ray.mesh,geom))
highestz = None
for c in [c.getContactGeomParams()[0] for c in cols]:
if not highestz or c>highestz:
highestz = c[2]
if highestz:
return highestz
def step(self):
def near_callback(args,geom1,geom2):
contacts = ode.collide(geom1,geom2)
for c in contacts:
c.setBounce(0.2)
c.setMu(5000)
j = ode.ContactJoint(self.wo,self.joints,c)
j.attach(geom1.getBody(),geom2.getBody())
self.sp.collide(None,near_callback)
def step(sp,wo,joints):
def near_callback(args,geom1,geom2):
contacts = ode.collide(geom1,geom2)
for c in contacts:
param = c.getContactGeomParams()
## if hasattr(geom1,"only_normal"):
## if param[1] != geom1.only_normal:
## continue
if hasattr(geom2,"only_normal"):
if param[1] != geom2.only_normal:
continue
c.setBounce(0.2)
c.setMu(2000)
j = ode.ContactJoint(args[0],args[1],c)
j.attach(geom1.getBody(),geom2.getBody())
for n in range(1):
sp.collide((wo,joints),near_callback)
wo.step(.005)
joints.empty()
wo = ode.World()
wo.setGravity( (0,-9.81,0) )
wo.setERP(0.8)
wo.setCFM(1E-5)
sp = ode.Space()
joints = ode.JointGroup()
m1 = ode.Mass()
m1.setBox(2500.0,1.0,1.0,1.0)
box1body = ode.Body(wo)
box1body.setPosition([1,1,0])
box1body.setMass(m1)
box1mesh = ode.GeomBox(sp,lengths=[1,1,1])
box1mesh.setBody(box1body)
box2body = ode.Body(wo)
box2body.setPosition([1,3,0])
box2body.setMass(m1)
box2mesh = ode.GeomBox(sp,lengths=[1,1,1])
box2mesh.setBody(box2body)
floor = ode.GeomPlane(sp,normal=(0,1,0),dist=0)
frontwall = ode.GeomPlane(sp,normal=(0,0,1),dist=-1)
backwall = ode.GeomPlane(sp,normal=(0,0,-1),dist=-1)
ledge = ode.GeomBox(sp,lengths=[1,1,1])
ledge.setPosition([3,1,0])
ledge.only_normal = [0,1.0,0]
disp = pygame.display.set_mode([320,240],0,32)
square = pygame.Surface([32,32])
square.fill([255,0,0])
play = 1
while play:
disp.fill([0,0,0])
pos1 = [int(32*box1body.getPosition()[0]),-int(32*box1body.getPosition()[1])+200]
pos2 = [int(32*box2body.getPosition()[0]),-int(32*box2body.getPosition()[1])+200]
pos3 = [int(32*ledge.getPosition()[0]),-int(32*ledge.getPosition()[1])+200]
#print pos1,box1body.getPosition()
pygame.draw.rect(disp,[255,255,255],[pos1[0]-16,pos1[1]-16,32,32])
pygame.draw.rect(disp,[255,0,255],[pos2[0]-16,pos2[1]-16,32,32])
pygame.draw.rect(disp,[0,0,255],[pos3[0]-16,pos3[1]-16,32,32])
pygame.draw.line(disp,[255,255,255],[0,200],[320,200])
pygame.display.update()
step(sp,wo,joints)
pygame.event.pump()
for evt in pygame.event.get([pygame.KEYDOWN,pygame.KEYUP]):
if evt.key == pygame.K_ESCAPE:
play = None
if evt.type == pygame.KEYDOWN and evt.key == pygame.K_UP:
box2body.addForce([0,3000000,0])
k = pygame.key.get_pressed()
force = 10000
if k[pygame.K_RIGHT]:
box2body.addForce([force,0,0])
if k[pygame.K_LEFT]:
box2body.addForce([-force,0,0])
pygame.quit()