Libraries and Tabs Issue

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!

2 Likes

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.

3 Likes

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)
3 Likes

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))
1 Like

For CircleShape() you’ll have to import the shapes:

add_library('box2d_processing')
from org.jbox2d.collision.shapes import *
...
2 Likes

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
3 Likes