def to_b2vec(self, pt): pt = self.parent.to_world(pt) ptx, pty = pt ptx /= self.parent.ppm pty /= self.parent.ppm pt = box2d.b2Vec2(ptx, pty) return pt
def to_b2vec(self,pt): pt = self.parent.to_world(pt) ptx, pty = pt ptx /= self.parent.ppm pty /= self.parent.ppm pt = box2d.b2Vec2(ptx, pty) return pt
def _rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5): # Add a rect without correcting any settings # meaning, pos and vertices are in meters # angle is now in radians ((degrees * pi) / 180)) x, y = pos bodyDef = box2d.b2BodyDef() bodyDef.position.Set(x, y) userData = { 'color' : self.parent.get_color() } bodyDef.userData = userData # Create the Body if not dynamic: density = 0 bodyDef.sleepFlag = True body = self.parent.world.CreateBody(bodyDef) self.parent.element_count += 1 # Add a shape to the Body boxDef = box2d.b2PolygonDef() boxDef.SetAsBox(width, height, box2d.b2Vec2(0,0), angle) boxDef.density = density boxDef.restitution = restitution boxDef.friction = friction body.CreateShape(boxDef) body.SetMassFromShapes() return body
def _poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5): # add a centered poly at pos without correcting any settings # meaning, pos and vertices are in meters x, y = pos bodyDef = box2d.b2BodyDef() bodyDef.position.Set(x, y) bodyDef.sleepFlag = True userData = { 'color' : self.parent.get_color() } bodyDef.userData = userData # Create the Body if not dynamic: density = 0 body = self.parent.world.CreateBody(bodyDef) self.parent.element_count += 1 # Add a shape to the Body polyDef = box2d.b2PolygonDef() polyDef.vertexCount = len(vertices) for i in range(len(vertices)): vx, vy = vertices[i] polyDef.setVertex(i, box2d.b2Vec2(vx, vy)) polyDef.density = density polyDef.restitution = restitution polyDef.friction = friction body.CreateShape(polyDef) body.SetMassFromShapes() return body
def prismaticJoint(self,b1,b2,Axis=(0.0,1.0),lower=-2,upper=2): jointDef = box2d.b2PrismaticJointDef() worldAxis = box2d.b2Vec2(Axis[0],Axis[1]) jointDef.Initialize(b1, b2, b1.GetWorldCenter(), worldAxis) jointDef.lowerTranslation = lower jointDef.upperTranslation = upper jointDef.enableLimit = True self.parent.world.CreateJoint(jointDef)
def prismaticJoint(self, b1, b2, Axis=(0.0, 1.0), lower=-2, upper=2): jointDef = box2d.b2PrismaticJointDef() worldAxis = box2d.b2Vec2(Axis[0], Axis[1]) jointDef.Initialize(b1, b2, b1.GetWorldCenter(), worldAxis) jointDef.lowerTranslation = lower jointDef.upperTranslation = upper jointDef.enableLimit = True self.parent.world.CreateJoint(jointDef)
def checkDef(pd): """Check the polygon definition for invalid vertices, etc. Return: True if valid, False if invalid """ # if pd.vertexCount < 3 or pd.vertexCount > box2d.b2_maxPolygonVertices: #raise ValueError, "Invalid vertexCount" threshold = FLT_EPSILON * FLT_EPSILON verts = pd.getVertices_b2Vec2() normals = [] v0 = verts[0] for i in range(pd.vertexCount): if i == pd.vertexCount - 1: v1 = verts[0] else: v1 = verts[i + 1] edge = v1 - v0 # if edge.LengthSquared() < threshold: # raise ValueError, "edge.LengthSquared < FLT_EPSILON**2" normals.append(box2d.b2Cross(edge, 1.0)) normals[-1].Normalize() v0 = v1 centroid = ComputeCentroid(pd) d = box2d.b2Vec2() for i in range(pd.vertexCount): i1 = i - 1 if i1 < 0: i1 = pd.vertexCount - 1 i2 = i n1 = normals[i1] n2 = normals[i2] v = verts[i] - centroid d.x = box2d.b2Dot(n1, v) - box2d.b2_toiSlop d.y = box2d.b2Dot(n2, v) - box2d.b2_toiSlop # Shifting the edge inward by b2_toiSlop should # not cause the plane to pass the centroid. # Your shape has a radius/extent less than b2_toiSlop. # if d.x < 0.0 or d.y <= 0.0: # raise ValueError, "Your shape has a radius/extent less than b2_toiSlop." A = box2d.b2Mat22() A.col1.x = n1.x A.col2.x = n1.y A.col1.y = n2.x A.col2.y = n2.y #coreVertices[i] = A.Solve(d) + m_centroid return True
def checkDef(pd): """Check the polygon definition for invalid vertices, etc. Return: True if valid, False if invalid """ # if pd.vertexCount < 3 or pd.vertexCount > box2d.b2_maxPolygonVertices: # raise ValueError, "Invalid vertexCount" threshold = FLT_EPSILON * FLT_EPSILON verts = pd.getVertices_b2Vec2() normals = [] v0 = verts[0] for i in range(pd.vertexCount): if i == pd.vertexCount - 1: v1 = verts[0] else: v1 = verts[i + 1] edge = v1 - v0 # if edge.LengthSquared() < threshold: # raise ValueError, "edge.LengthSquared < FLT_EPSILON**2" normals.append(box2d.b2Cross(edge, 1.0)) normals[-1].Normalize() v0 = v1 centroid = ComputeCentroid(pd) d = box2d.b2Vec2() for i in range(pd.vertexCount): i1 = i - 1 if i1 < 0: i1 = pd.vertexCount - 1 i2 = i n1 = normals[i1] n2 = normals[i2] v = verts[i] - centroid d.x = box2d.b2Dot(n1, v) - box2d.b2_toiSlop d.y = box2d.b2Dot(n2, v) - box2d.b2_toiSlop # Shifting the edge inward by b2_toiSlop should # not cause the plane to pass the centroid. # Your shape has a radius/extent less than b2_toiSlop. # if d.x < 0.0 or d.y <= 0.0: # raise ValueError, "Your shape has a radius/extent less than b2_toiSlop." A = box2d.b2Mat22() A.col1.x = n1.x A.col2.x = n1.y A.col1.y = n2.x A.col2.y = n2.y # coreVertices[i] = A.Solve(d) + m_centroid return True
def joint(self, *args): print "* Add Joint:", args if len(args) == 4: # Distance Joint b1, b2, p1, p2 = args p1 = self.parent.to_world(p1) p2 = self.parent.to_world(p2) p1x, p1y = p1 p2x, p2y = p2 p1x /= self.parent.ppm p1y /= self.parent.ppm p2x /= self.parent.ppm p2y /= self.parent.ppm p1 = box2d.b2Vec2(p1x, p1y) p2 = box2d.b2Vec2(p2x, p2y) jointDef = box2d.b2DistanceJointDef() jointDef.Initialize(b1, b2, p1, p2) jointDef.collideConnected = True self.parent.world.CreateJoint(jointDef) elif len(args) == 3: # Revolute Joint pass elif len(args) == 1: # Fixed Joint to the Background, assume the center of the body b1 = self.parent.world.GetGroundBody() b2 = args[0] p1 = b2.GetWorldCenter() jointDef = box2d.b2RevoluteJointDef() jointDef.Initialize(b1, b2, p1) self.parent.world.CreateJoint(jointDef)
def ComputeCentroid(pd): count = pd.vertexCount if count < 3: return False c = box2d.b2Vec2(0, 0) area = 0.0 # pRef is the reference point for forming triangles. # It's location doesn't change the result (except for rounding error). pRef = box2d.b2Vec2(0.0, 0.0) inv3 = 1.0 / 3.0 for i in range(count): # Triangle vertices. p1 = pRef p2 = pd.getVertex(i) if i + 1 < count: p3 = pd.getVertex(i + 1) else: p3 = pd.getVertex(0) e1 = p2 - p1 e2 = p3 - p1 D = box2d.b2Cross(e1, e2) triangleArea = 0.5 * D area += triangleArea # Area weighted centroid c += triangleArea * inv3 * (p1 + p2 + p3) # Centroid # if area < FLT_EPSILON: # raise ValueError, "ComputeCentroid: area < FLT_EPSILON" return c / area
def ComputeCentroid(pd): count = pd.vertexCount if count < 3: return False c = box2d.b2Vec2(0, 0) area = 0.0 # pRef is the reference point for forming triangles. # It's location doesn't change the result (except for rounding error). pRef = box2d.b2Vec2(0.0, 0.0) inv3 = 1.0 / 3.0 for i in range(count): # Triangle vertices. p1 = pRef p2 = pd.getVertex(i) if i + 1 < count: p3 = pd.getVertex(i + 1) else: p3 = pd.getVertex(0) e1 = p2 - p1 e2 = p3 - p1 D = box2d.b2Cross(e1, e2) triangleArea = 0.5 * D area += triangleArea # Area weighted centroid c += triangleArea * inv3 * (p1 + p2 + p3) # Centroid # if area < FLT_EPSILON: #raise ValueError, "ComputeCentroid: area < FLT_EPSILON" return c / area
def mouseJoint(self, body, pos): pos = self.parent.to_world(pos) x, y = pos x /= self.parent.ppm y /= self.parent.ppm mj = box2d.b2MouseJointDef() mj.body1 = self.parent.world.GetGroundBody() mj.body2 = body mj.target = box2d.b2Vec2(x, y) mj.maxForce = 100.0 * body.GetMass() # give humans POWER! self.parent.mouseJoint = self.parent.world.CreateJoint(mj).getAsType() body.WakeUp()
def _rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5): # Add a rect without correcting any settings # meaning, pos and vertices are in meters # angle is now in radians ((degrees * pi) / 180)) x, y = pos bodyDef = box2d.b2BodyDef() bodyDef.position.Set(x, y) userData = {'color': self.parent.get_color()} bodyDef.userData = userData # Create the Body if not dynamic: density = 0 bodyDef.sleepFlag = True body = self.parent.world.CreateBody(bodyDef) self.parent.element_count += 1 # Add a shape to the Body boxDef = box2d.b2PolygonDef() boxDef.SetAsBox(width, height, box2d.b2Vec2(0, 0), angle) boxDef.density = density boxDef.restitution = restitution boxDef.friction = friction body.CreateShape(boxDef) body.SetMassFromShapes() return body
def _poly(self, pos, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5): # add a centered poly at pos without correcting any settings # meaning, pos and vertices are in meters x, y = pos bodyDef = box2d.b2BodyDef() bodyDef.position.Set(x, y) bodyDef.sleepFlag = True userData = {'color': self.parent.get_color()} bodyDef.userData = userData # Create the Body if not dynamic: density = 0 body = self.parent.world.CreateBody(bodyDef) self.parent.element_count += 1 # Add a shape to the Body polyDef = box2d.b2PolygonDef() polyDef.vertexCount = len(vertices) for i in range(len(vertices)): vx, vy = vertices[i] polyDef.setVertex(i, box2d.b2Vec2(vx, vy)) polyDef.density = density polyDef.restitution = restitution polyDef.friction = friction body.CreateShape(polyDef) body.SetMassFromShapes() return body
def concavePoly( self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True): # 1. Step: Reduce # Detect if the polygon is closed or open if vertices[0] != vertices[-1]: is_closed = False else: is_closed = True # Continue reducing the vertecs x, y = c = tools_poly.calc_center(vertices) vertices = tools_poly.poly_center_vertices(vertices) # Bring coordinates into the world coordinate system (flip, camera # offset, ...) if screenCoord: x, y = self.parent.to_world(c) else: x, y = c # If required, translate pixel -> meters if self.parent.input == INPUT_PIXELS: # translate pixel -> meters x /= self.parent.ppm y /= self.parent.ppm # Let's add the body bodyDef = box2d.b2BodyDef() bodyDef.position = (x, y) userData = {'color': self.parent.get_color()} bodyDef.userData = userData # Create the Body if not dynamic: density = 0 else: bodyDef.type = box2d.b2_dynamicBody body = self.parent.world.CreateBody(bodyDef) self.parent.element_count += 1 # Create the reusable Box2D polygon and circle definitions polyDef = box2d.b2PolygonShape() polyDef.vertexCount = 4 # rectangle polyDef.density = density polyDef.restitution = restitution polyDef.friction = friction circleShape = box2d.b2CircleShape() circleShape.radius = radius circleDef = box2d.b2FixtureDef() circleDef.shape = circleShape circleDef.density = density circleDef.restitution = restitution circleDef.friction = friction # Set the scale factor factor = 8.0 v2 = box2d.b2Vec2(*vertices[0]) for v in vertices[1:]: v1 = v2.copy() v2 = box2d.b2Vec2(*v) vdir = v2 - v1 # (v2x-v1x, v2y-v1y) vdir.Normalize() # we need a little size for the end part vn = box2d.b2Vec2(-vdir.y * factor, vdir.x * factor) v = [v1 + vn, v1 - vn, v2 - vn, v2 + vn] # Create a line (rect) for each part of the polygon, # and attach it to the body polyDef.setVertices([vi / self.parent.ppm for vi in v]) try: polyDef.checkValues() except ValueError: print "concavePoly: Created an invalid polygon!" return None body.CreateFixture(polyDef) # Now add a circle to the points between the rects # to avoid sharp edges and gaps if not is_closed and v2.tuple() == vertices[-1]: # Don't add a circle at the end break circleDef.localPosition = v2 / self.parent.ppm body.CreateFixture(circleDef) # Return hard and soft reduced vertices return body
def concavePoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True): # 1. Step: Reduce # Detect if the polygon is closed or open if vertices[0] != vertices[-1]: is_closed = False else: is_closed = True # Continue reducing the vertecs x, y = c = tools_poly.calc_center(vertices) vertices = tools_poly.poly_center_vertices(vertices) # Bring coordinates into the world coordinate system (flip, camera # offset, ...) if screenCoord: x, y = self.parent.to_world(c) else: x, y = c # If required, translate pixel -> meters if self.parent.input == INPUT_PIXELS: # translate pixel -> meters x /= self.parent.ppm y /= self.parent.ppm # Let's add the body bodyDef = box2d.b2BodyDef() bodyDef.position = (x, y) userData = {'color': self.parent.get_color()} bodyDef.userData = userData # Create the Body if not dynamic: density = 0 else: bodyDef.type = box2d.b2_dynamicBody body = self.parent.world.CreateBody(bodyDef) self.parent.element_count += 1 # Create the reusable Box2D polygon and circle definitions polyDef = box2d.b2PolygonShape() polyDef.vertexCount = 4 # rectangle polyDef.density = density polyDef.restitution = restitution polyDef.friction = friction circleShape = box2d.b2CircleShape() circleShape.radius = radius circleDef = box2d.b2FixtureDef() circleDef.shape = circleShape circleDef.density = density circleDef.restitution = restitution circleDef.friction = friction # Set the scale factor factor = 8.0 v2 = box2d.b2Vec2(*vertices[0]) for v in vertices[1:]: v1 = v2.copy() v2 = box2d.b2Vec2(*v) vdir = v2 - v1 # (v2x-v1x, v2y-v1y) vdir.Normalize() # we need a little size for the end part vn = box2d.b2Vec2(-vdir.y * factor, vdir.x * factor) v = [v1 + vn, v1 - vn, v2 - vn, v2 + vn] # Create a line (rect) for each part of the polygon, # and attach it to the body polyDef.setVertices([vi / self.parent.ppm for vi in v]) try: polyDef.checkValues() except ValueError: print "concavePoly: Created an invalid polygon!" return None body.CreateFixture(polyDef) # Now add a circle to the points between the rects # to avoid sharp edges and gaps if not is_closed and v2.tuple() == vertices[-1]: # Don't add a circle at the end break circleDef.localPosition = v2 / self.parent.ppm body.CreateFixture(circleDef) # Return hard and soft reduced vertices return body