Hi, I’m pretty new to processing and I’ve been learning the .py version for a class. I decided to recreate one of the example codes from the box2d_processing library but in python instead of Java. I was able to do so and it works great, except for one thing: my entire code has to be in the primary tab or it wont work. For some reason none of box2d’s functions work in the tabs I create. I’ve tried importing the library into each tab, but that wont solve the issue either. I get errors like “‘BodyDef’ is not defined.” Any help would be greatly appreciated!
Welcome, atowersm!
I switched to Java mode to take a look at the Box2D examples (File > Examples > Contributed Libraries > Box2D for Processing). Here’s what I quickly slapped together. Just some working imports, but nothing visual yet:
boxes.pyde (main sketch)
add_library('box2d_processing')
# from org.jbox2d.___ import *
from Box import *
def setup():
global box2d
box2d = Box2DProcessing(this)
box2d.createWorld()
box2d.setGravity(0, -10)
box1 = Box()
def draw():
box2d.step()
Box.py (another tab)
from org.jbox2d.dynamics import *
# from org.jbox2d.___ import *
class Box(object):
def __init__(self):
self.bd = BodyDef()
self.bd.type = BodyType.DYNAMIC;
I’m not exactly sure what you intend to do with this? Hope that helps.
That actually helped a lot of it thanks! BodyDef() no longer gets an error. I’m still getting an issue though, for the functions that use the word box2d like ‘box2d.coordPixelsToWorld(x,y)’ or ‘box2d.world.createBody(bd)’ I’m getting a “global name ‘box2d’ is not defined” error. I’m not sure how to fix this. Is there something else I have to import still?
I assume that’s an error in your tab file, not the main sketch?
As I said, I’m not sure what you’re trying to accomplish here. But, what if you passed the box2d
instance to your class?
boxes.pyde (main sketch)
...
def setup():
global box2d
box2d = Box2DProcessing(this)
...
box1 = Box(box2d)
Box.py (another tab)
...
class Box(object):
def __init__(self, box2d):
...
box2d.coordPixelsToWorld(1, 1)
Thanks so much for taking the time to help me with this. It worked perfectly when I set it up just as you are writing it here, but every time I try applying it to my old code another thing is “not defined.” This time it was CircleShape(). To give you some context incase it helps, I’m just trying to recreate the BumpySurfaceNoise.pde example from the box2d_processing library example folder with some tweaks, just to get familiar with the way it works. I haven’t gotten to creating the terrain yet though. Here is the version that works on just one tab:
add_library('box2d_processing')
add_library('jbox2d_library') # for some reason it only works when I do it like this
particles = []
def setup():
size(1000, 700)
global box2d, center, particles
box2d = Box2DProcessing(this)
center = Vec2(width>>1, height>>1)
box2d.createWorld(center)
box2d.setGravity(0, 0)
def draw():
if mousePressed:
sz = abs(map(randomGaussian(),-1,1,10,50))
particles.append(Particle(mouseX,mouseY,sz))
box2d.step()
background(0)
for p in particles:
p.display()
for i in range(len(particles)-1,-1,-1):
if particles[i].done(center):
particles.pop(i)
# Just drawing the framerate to see how many particles it can handle
fill(255);
text("framerate: " + str(int(frameRate)),12,16)
class Particle(object):
def __init__ (self,x,y,r):
self.radius = r
self.body = None #not sure if this is right, maybe fix it once you create makeBody comand
#This function puts the particle in the Box2d world
self.makeBody(x,y,r)
#This function removes the particle from the box2d world
def killBody(self):
box2d.destroyBody(self.body)
#should particle be deleted?
def done(self,centerPos):
#Let's find the screen position of the particle
pos = box2d.getBodyPixelCoord(self.body)
if pos.subLocal(centerPos).lengthSquared() > sq((width/2.8) + (height/2.8)+(2*self.radius)):
#Is it off the bottom of the screen?
#if pos.y > height+self.radius*2:
self.killBody()
return True
else:
return False
def display(self):
#We look at each body and get its screen position
pos = box2d.getBodyPixelCoord(self.body)
#Get its angle of rotation
a = self.body.getAngle()
pushMatrix()
translate(pos.x,pos.y)
rotate(-a)
fill(175,100)
noStroke()
ellipse(0,0,self.radius*2,self.radius*2)
# Let's add a line so we can see the rotation
stroke(0)
strokeWeight(1)
line(0,0,self.radius,0)
popMatrix();
def makeBody(self,x,y,r):
# Define a body
bd = BodyDef()
# Set its position
bd.position = box2d.coordPixelsToWorld(x,y)
bd.type = BodyType.DYNAMIC #KINEMATIC means user controled
self.body = box2d.world.createBody(bd)
# Make the body's shape a circle
cs = CircleShape()
cs.m_radius = box2d.scalarPixelsToWorld(r)
fd = FixtureDef()
fd.shape = cs
# Parameters that affect physics
fd.density = 1
fd.friction = 0.01
fd.restitution = 0.3
# Attach fixture to body
self.body.createFixture(fd)
# Give it a random initial velocity (and angular velocity)
a = random(-1,1)
b = random(-1,1)
v = Vec2(a,b)
self.body.setLinearVelocity(v)
self.body.setAngularVelocity(random(0,0))
and the version with the tab is like this:
add_library('box2d_processing')
add_library('jbox2d_library')
# from org.jbox2d.___ import *
from Particle import Particle
particles = []
def setup():
size(1000, 700)
global box2d, center, particles
box2d = Box2DProcessing(this)
center = Vec2(width>>1, height>>1)
box2d.createWorld(center)
box2d.setGravity(0, 0)
def draw():
if mousePressed:
sz = abs(map(randomGaussian(),-1,1,10,50))
particles.append(Particle(box2d,mouseX,mouseY,sz))
box2d.step()
background(0)
for p in particles:
p.display()
for i in range(len(particles)-1,-1,-1):
if particles[i].done(center):
particles.pop(i)
# Just drawing the framerate to see how many particles it can handle
fill(255);
text("framerate: " + str(int(frameRate)),12,16)
and the other tab called Particle.py
from org.jbox2d.dynamics import *
class Particle(object):
def __init__ (self,box2d,x,y,r):
self.radius = r
self.box2d = box2d
self.body = None #not sure if this is right, maybe fix it once you create makeBody comand
#This function puts the particle in the Box2d world
self.makeBody(x,y,r)
#This function removes the particle from the box2d world
def killBody(self):
self.box2d.destroyBody(self.body)
#should particle be deleted?
def done(self,centerPos):
#Let's find the screen position of the particle
pos = self.box2d.getBodyPixelCoord(self.body)
#Is it off the bottom of the screen?
if pos.subLocal(centerPos).lengthSquared() > sq((width/2.8) + (height/2.8)+(2*self.radius)):
self.killBody()
return True
else:
return False
def display(self):
#We look at each body and get its screen position
pos = self.box2d.getBodyPixelCoord(self.body)
#Get its angle of rotation
a = self.body.getAngle()
pushMatrix()
translate(pos.x,pos.y)
rotate(-a)
fill(175,100)
noStroke()
ellipse(0,0,self.radius*2,self.radius*2)
# Let's add a line so we can see the rotation
stroke(0)
strokeWeight(1)
line(0,0,self.radius,0)
popMatrix();
def makeBody(self,x,y,r):
# Define a body
bd = BodyDef()
# Set its position
bd.position = self.box2d.coordPixelsToWorld(x,y)
bd.type = BodyType.DYNAMIC #KINEMATIC means user controled
self.body = self.box2d.world.createBody(bd)
# Make the body's shape a circle
cs = CircleShape()
cs.m_radius = self.box2d.scalarPixelsToWorld(r)
fd = FixtureDef()
fd.shape = cs
# Parameters that affect physics
fd.density = 1
fd.friction = 0.01
fd.restitution = 0.3
# Attach fixture to body
self.body.createFixture(fd)
# Give it a random initial velocity (and angular velocity)
a = random(-1,1)
b = random(-1,1)
v = Vec2(a,b)
self.body.setLinearVelocity(v)
self.body.setAngularVelocity(random(0,0))
For CircleShape()
you’ll have to import the shapes
:
add_library('box2d_processing')
from org.jbox2d.collision.shapes import *
...
Ohhh, I think I’m starting to get it, I have to individually import everything I need. I just ran across another problem but I was able to fix it and now its working. Vec2 wasn’t defined so I imported org.jbox2d.common.Vec2 but that didn’t work. So I tried importing just org.jbox2d.common and that did work. Im still not exactly sure why one worked over the other. Guess I just need to learn more about importing.
Thanks so much for your help!
only thing I had to change from the last post:
from org.jbox2d.dynamics import *
from org.jbox2d.collision.shapes import * #this one
from org.jbox2d.common import * #and this one