Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/elements/add_objects.py
diff options
context:
space:
mode:
authorGary Martin <gary@garycmartin.com>2012-10-24 00:40:54 (GMT)
committer Gary Martin <gary@garycmartin.com>2012-10-24 00:40:54 (GMT)
commitdb517f0b40c441158203d69aa34627058f2ab2e9 (patch)
tree3416eca5bca558b995d9c8feff24d76b18e3430f /elements/add_objects.py
parente6cff9307917aa97019785c32fbf0e412ba0e7ea (diff)
Use recent versions of Box2D and elements and ARM platform compatibility.
The version of Box2D and elements as used by the current version of Physics has been migrated over into Bridge and the old versions removed. The Elements egg needed some minor patches for a function used in Bridge hence the change in name to Elements-0.13-py2.5-bridge.egg. The binary blob paths are appended to the system path rather than inserted as the first choice so that builds that included newer versions of Box2d, or versions build for different architectures, will still work (tested on ARM XO-1.75 and XO-4 platforms). Due to the change in Elements/Box2D api some additional code changes were necessary, particularly the calculations in Bridge.py for calculating the joint stress on the rivits.
Diffstat (limited to 'elements/add_objects.py')
-rw-r--r--elements/add_objects.py602
1 files changed, 0 insertions, 602 deletions
diff --git a/elements/add_objects.py b/elements/add_objects.py
deleted file mode 100644
index 66a59cd..0000000
--- a/elements/add_objects.py
+++ /dev/null
@@ -1,602 +0,0 @@
-"""
-This file is part of the 'Elements' Project
-Elements is a 2D Physics API for Python (supporting Box2D2)
-
-Copyright (C) 2008, The Elements Team, <elements@linuxuser.at>
-
-Home: http://elements.linuxuser.at
-IRC: #elements on irc.freenode.org
-
-Code: http://www.assembla.com/wiki/show/elements
- svn co http://svn2.assembla.com/svn/elements
-
-License: GPLv3 | See LICENSE for the full text
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-"""
-from locals import *
-from elements import box2d
-
-# Imports
-from math import pi
-from math import sqrt
-from math import asin
-
-import tools_poly
-
-class Add:
- element_count = 0
-
- def __init__(self, parent):
- self.parent = parent
-
- def ground(self):
- """ Add a static ground to the scene
-
- Return: box2d.b2Body
- """
- return self._rect((-10.0, 0.0), 50.0, 0.1, dynamic=False)
-
- def triangle(self, pos, sidelength, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a triangle | pos & a in the current input unit system (meters or pixels)
-
- Parameters:
- pos .... position (x,y)
- sidelength ...... sidelength
- other .. see [physics parameters]
-
- Return: box2d.b2Body
- """
- vertices = [(-sidelength, 0.0), (sidelength, 0.0), (0.0, 2*sidelength)]
- return self.poly(pos, vertices, dynamic, density, restitution, friction, screenCoord)
-
- def ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a dynamic ball at pos after correcting the positions and legths to the internal
- meter system if neccessary (if INPUT_PIXELS), then call self._add_ball(...)
-
- Parameters:
- pos ..... position (x,y)
- radius .. circle radius
- other ... see [physics parameters]
-
- Return: box2d.b2Body
- """
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
-
-
- if self.parent.input == INPUT_PIXELS:
- x /= self.parent.ppm
- y /= self.parent.ppm
- radius /= self.parent.ppm
-
- return self._ball((x,y), radius, dynamic, density, restitution, friction)
-
- def _ball(self, pos, radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- # Add a ball without correcting any settings
- # meaning, pos and vertices are in meters
- # Define the body
- x, y = pos
- bodyDef = box2d.b2BodyDef()
- bodyDef.position.Set(x, y)
- bodyDef.sleepFlag = True
-# bodyDef.allowSleep(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
- circleDef = box2d.b2CircleDef()
- circleDef.density = density
- circleDef.radius = radius
- circleDef.restitution = restitution
- circleDef.friction = friction
-
- body.CreateShape(circleDef)
- body.SetMassFromShapes();
-
- return body
-
- def rect(self, pos, width, height, angle=0, dynamic=True, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a dynamic rectangle with input unit according to self.input (INPUT_PIXELS or INPUT_METERS)
- Correcting the positions to meters and calling self._add_rect()
-
- Parameters:
- pos ..... position (x,y)
- width ....... horizontal line
- height ....... vertical line
- angle ........ in degrees (0 .. 360)
- other ... see [physics parameters]
-
- Return: box2d.b2Body
- """
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
-
- # If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
- x /= self.parent.ppm
- y /= self.parent.ppm
- width /= self.parent.ppm
- height /= self.parent.ppm
-
- # grad -> radians
- angle = (angle * pi) / 180
-
- return self._rect((x,y), width, height, angle, dynamic, density, restitution, friction)
-
-
- def wall(self, pos1, pos2, width=5, density=1.0, restitution=0.16, friction=0.5, screenCoord=True):
- """ Add a static rectangle between two arbitrary points with input unit according to self.input
- (INPUT_PIXELS or INPUT_METERS) Correcting the positions to meters and calling self._add_rect()
-
- Return: box2d.b2Body
- """
- if width < 5: width = 5
-
- if (pos1[0] < pos2[0]):
- x1, y1 = pos1
- x2, y2 = pos2
- else:
- x1, y1 = pos2
- x2, y2 = pos1
-
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord:
- x1, y1 = self.parent.to_world((x1, y1))
- x2, y2 = self.parent.to_world((x2, y2))
-
- # If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
- x1 /= self.parent.ppm
- y1 /= self.parent.ppm
- x2 /= self.parent.ppm
- y2 /= self.parent.ppm
- width /= self.parent.ppm
-
- length = sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )*0.5
-
- if width > 0:
- halfX = x1 + (x2-x1)*0.5
- halfY = y1 + (y2-y1)*0.5
-
- angle = asin( (y2-halfY)/length )
- return self._rect((halfX, halfY), length, width, angle, False, density, restitution, friction)
-
- 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, screenCoord=True):
- """ Add a dynamic polygon, which has the vertices arranged around the poly's center at pos
- Correcting the positions to meters if INPUT_PIXELS, and calling self._add_poly()
-
- Parameters:
- pos ....... position (x,y)
- vertices .. vertices arranged around the center
- other ... see [physics parameters]
-
- Return: box2d.b2Body
- """
- # Bring coordinates into the world coordinate system (flip, camera offset, ...)
- if screenCoord: x, y = self.parent.to_world(pos)
- else: x, y = pos
-
- # If required, translate pixel -> meters
- if self.parent.input == INPUT_PIXELS:
- # translate pixel -> meters
- x /= self.parent.ppm
- y /= self.parent.ppm
-
- # Translate vertices from pixels to meters
- v_new = []
- for v in vertices:
- vx, vy = v
- v_new.append((vx/self.parent.ppm, vy/self.parent.ppm))
- vertices = v_new
-
- return self._poly((x,y), vertices, dynamic, density, restitution, friction)
-
- 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.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
-
- # Create the reusable Box2D polygon and circle definitions
- polyDef = box2d.b2PolygonDef()
- polyDef.vertexCount = 4 # rectangle
- polyDef.density = density
- polyDef.restitution = restitution
- polyDef.friction = friction
-
- circleDef = box2d.b2CircleDef()
- circleDef.density = density
- circleDef.radius = 0.086
- circleDef.restitution = restitution
- circleDef.friction = friction
-
- # Set the scale factor
- factor = 8.0
-
- v2 = box2d.b2Vec2().fromTuple(vertices[0])
- for v in vertices[1:]:
- v1 = v2.copy()
- v2 = box2d.b2Vec2().fromTuple(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
- for i in range(len(v)):
- polyDef.setVertex(i, v[i] / self.parent.ppm)
-
- if not tools_poly.checkDef(polyDef):
- print "concavePoly: Created an invalid polygon!"
- return [], 0
-
- body.CreateShape(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.CreateShape(circleDef)
-
- # Now, all shapes have been attached
- body.SetMassFromShapes()
-
- # Return hard and soft reduced vertices
- return body
-
- def complexPoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- # 1. Step: Reduce
- # 2. Step: See if start and end are close, if so then close the polygon
- # 3. Step: Detect if convex or concave
- # 4. Step: Start self.convexPoly or self.concavePoly
- vertices, is_convex = tools_poly.reduce_poly_by_angle(vertices)
- #print "->", is_convex
-
- # If start and endpoints are close to each other, close polygon
- x1, y1 = vertices[0]
- x2, y2 = vertices[-1]
- dx = x2 - x1
- dy = y2 - y1
- l = sqrt((dx*dx)+(dy*dy))
-
- if l < 50:
- vertices[-1] = vertices[0]
- else:
- # Never convex if open (we decide so :)
- is_convex = False
-
- if tools_poly.is_line(vertices):
- # Lines shall be drawn by self.concavePoly(...)
- print "is line"
- is_convex = False
-
- if is_convex:
- print "convex"
- return self.convexPoly(vertices, dynamic, density, restitution, friction), vertices
- else:
- print "concave"
- return self.concavePoly(vertices, dynamic, density, restitution, friction), vertices
-
-
- def convexPoly(self, vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5):
- """ Add a complex polygon with vertices in absolute positions (meters or pixels, according
- to INPUT_PIXELS or INPUT_METERS). This function does the reduction and convec hulling
- of the poly, and calls add_poly(...)
-
- Parameters:
- vertices .. absolute vertices positions
- other ..... see [physics parameters]
-
- Return: box2d.b2Body
- """
- # NOTE: Box2D has a maximum poly vertex count, defined in Common/box2d.b2Settings.h (box2d.b2_maxPolygonVertices)
- # We need to make sure, that we reach that by reducing the poly with increased tolerance
- # Reduce Polygon
- tolerance = 10 #5
- v_new = vertices
- while len(v_new) > box2d.b2_maxPolygonVertices:
- tolerance += 1
- v_new = tools_poly.reduce_poly(vertices, tolerance)
-
- print "convexPoly: Polygon reduced from %i to %i vertices | tolerance: %i" % (len(vertices), len(v_new), tolerance)
- vertices = v_new
-
- # So poly should be alright now
- # Continue reducing the vertecs
- vertices_orig_reduced = vertices
- vertices = tools_poly.poly_center_vertices(vertices)
-
- vertices = tools_poly.convex_hull(vertices)
-
- if len(vertices) < 3:
- return
-
- # Define the body
- x, y = c = tools_poly.calc_center(vertices_orig_reduced)
- return self.poly((x,y), vertices, dynamic, density, restitution, friction)
-
- 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
- # Alex Levenson's added joint methods:
- def distanceJoint(self,b1,b2,p1,p2):
- # Distance Joint
- p1 = self.to_b2vec(p1)
- p2 = self.to_b2vec(p2)
-
- jointDef = box2d.b2DistanceJointDef()
- jointDef.Initialize(b1, b2, p1, p2)
- jointDef.collideConnected = True
- self.parent.world.CreateJoint(jointDef)
-
- def fixedJoint(self, *args):
- if len(args) == 2:
- # Fixed Joint to the Background, don't assume the center of the body
- b1 = self.parent.world.GetGroundBody()
- b2 = args[0]
- p1 = self.to_b2vec(args[1])
-
- jointDef = box2d.b2RevoluteJointDef()
- jointDef.Initialize(b1, b2, p1)
- self.parent.world.CreateJoint(jointDef)
- 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 revoluteJoint(self,b1,b2,p1):
- # revolute joint between to bodies
- p1 = self.to_b2vec(p1)
-
- jointDef = box2d.b2RevoluteJointDef()
- jointDef.Initialize(b1, b2, p1)
-
- self.parent.world.CreateJoint(jointDef)
-
- # prismatic joint + pully not fully functional at this point
- 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 pully(self,b1,b2,p1,p2,g1,g2,ratio=1.0,maxLength1=5,maxLength2=5):
- p1 = self.to_b2vec(p1)
- p2 = self.to_b2vec(p2)
- g1 = self.to_b2vec(g1)
- g2 = self.to_b2vec(g2)
-
- jointDef = box2d.b2PulleyJointDef()
- jointDef.Initialize(b1, b2, g1, g2, p1, p2, ratio)
- jointDef.maxLength1 = maxLength1
- jointDef.maxLength2 = maxLength2
-
- self.parent.world.CreateJoint(jointDef)
-
- def motor(self, body,pt,torque=900,speed=-10):
- # Fixed Joint to the Background with a motor on it
- b1 = self.parent.world.GetGroundBody()
- pt = self.to_b2vec(pt)
-
- jointDef = box2d.b2RevoluteJointDef()
- jointDef.Initialize(b1, body, pt)
- jointDef.maxMotorTorque = torque
- jointDef.motorSpeed = speed
- jointDef.enableMotor = True
- self.parent.world.CreateJoint(jointDef)
-
- def jointMotor(self,b1,b2,p1,torque=900,speed=-10):
- p1 = self.to_b2vec(p1)
- jointDef = box2d.b2RevoluteJointDef()
- jointDef.Initialize(b1, b2, p1)
- jointDef.maxMotorTorque = torque
- jointDef.motorSpeed = speed
- jointDef.enableMotor = True
- self.parent.world.CreateJoint(jointDef)
-
- 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 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 remove_mouseJoint(self):
- if self.parent.mouseJoint:
- self.parent.world.DestroyJoint(self.parent.mouseJoint)
- self.parent.mouseJoint = None
-