Example #1
0
    def MouseDown(self, p):
        """
        Indicates that there was a left click at point p (world coordinates)
        """
        if self.mouseJoint != None:
            return

        # Create a mouse joint on the selected body (assuming it's dynamic)

        # Make a small box.
        aabb = box2d.b2AABB()
        d = box2d.b2Vec2(0.001, 0.001)
        aabb.lowerBound = p - d
        aabb.upperBound = p + d

        # Query the world for overlapping shapes.
        body = None
        k_maxCount = 10 # maximum amount of shapes to return

        (count, shapes) = self.world.Query(aabb, k_maxCount)
        for shape in shapes:
            shapeBody = shape.GetBody()
            if shapeBody.IsStatic() == False and shapeBody.GetMass() > 0.0:
                if shape.TestPoint(shapeBody.GetXForm(), p): # is it inside?
                    body = shapeBody
                    break
        
        if body:
            md = box2d.b2MouseJointDef()
            md.body1   = self.world.GetGroundBody()
            md.body2   = body
            md.target  = p
            md.maxForce= 1000.0 * body.GetMass()
            self.mouseJoint = self.world.CreateJoint(md).getAsType()
            body.WakeUp()
Example #2
0
def update_shapes(world):
    for body in get_bodies(world):
        v = body.GetLinearVelocity()
        if body.IsSleeping() or v.LengthSquared() < 0.2:
            i = body.GetWorldVector(box2d.b2Vec2(box2d.b2Random(-200, 200), box2d.b2Random(-200, 200)))
            p = body.GetWorldPoint(box2d.b2Vec2(0.0, 0.0))
            body.ApplyImpulse(i, p)
Example #3
0
    def __init__(self):
        # Pygame Initialization
        pygame.init()

        caption= "Python Box2D Testbed - " + self.name
        pygame.display.set_caption(caption)

        self.screen = pygame.display.set_mode( (640,480) )
        self.screenSize = box2d.b2Vec2(*self.screen.get_size())
        self.font = pygame.font.Font(None, 15)

        # GUI Initialization
        self.gui_app = gui.App()
        self.gui_table=fwGUI(self.settings)
        container = gui.Container(align=1,valign=-1)
        container.add(self.gui_table,0,0)
        self.gui_app.init(container)

        # Box2D Initialization
        self.worldAABB.lowerBound.Set(-200.0, -100.0)
        self.worldAABB.upperBound.Set( 200.0, 200.0)
        gravity = box2d.b2Vec2(0.0, -10.0)

        doSleep = True
        self.world = box2d.b2World(self.worldAABB, gravity, doSleep)
        self.destructionListener = fwDestructionListener()
        self.boundaryListener = fwBoundaryListener()
        self.contactListener = fwContactListener()
        self.debugDraw = fwDebugDraw()

        self.debugDraw.surface = self.screen

        self.destructionListener.test = self
        self.boundaryListener.test = self
        self.contactListener.test = self
        
        self.world.SetDestructionListener(self.destructionListener)
        self.world.SetBoundaryListener(self.boundaryListener)
        self.world.SetContactListener(self.contactListener)
        self.world.SetDebugDraw(self.debugDraw)

        self.updateCenter()
Example #4
0
    def LaunchBomb(self):
        """
        Create a new bomb and launch it at the testbed.
        A bomb is a simple circle which has a random position and velocity.
        """
        if self.bomb:
            self.world.DestroyBody(self.bomb)
            self.bomb = None
        bd = box2d.b2BodyDef()
        bd.allowSleep = True
        bd.position.Set(box2d.b2Random(-15.0, 15.0), 30.0)
        bd.isBullet = True
        self.bomb = self.world.CreateBody(bd)
        self.bomb.SetLinearVelocity(-5.0 * bd.position)

        sd = box2d.b2CircleDef()
        sd.radius = 0.3
        sd.density = 20.0
        sd.restitution = 0.1
        self.bomb.CreateShape(sd)
        
        self.bomb.SetMassFromShapes()
Example #5
0
    def checkEvents(self):
        """
        Check for pygame events (mainly keyboard/mouse events).
        Passes the events onto the GUI also.
        """
        for event in pygame.event.get():
            if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                return False
            elif event.type == KEYDOWN:
                self._Keyboard_Event(event.key)
            elif event.type == MOUSEBUTTONDOWN:
                p = self.ConvertScreenToWorld(*event.pos)
                if event.button == 1: # left
                    self.MouseDown( p )
                elif event.button == 2: #middle
                    pass
                elif event.button == 3: #right
                    self.rMouseDown = True
                elif event.button ==4:
                    self.viewZoom *= 1.1
                    self.updateCenter()
                elif event.button == 5:
                    self.viewZoom /= 1.1
                    self.updateCenter()
            elif event.type == MOUSEBUTTONUP:
                if event.button == 3: #right
                    self.rMouseDown = False
                else:
                    self.MouseUp()
            elif event.type == MOUSEMOTION:
                p = self.ConvertScreenToWorld(*event.pos)

                self.MouseMove(p)

                if self.rMouseDown:
                    self.viewCenter -= box2d.b2Vec2(event.rel[0], -event.rel[1])
                    self.updateCenter()

            self.gui_app.event(event) #Pass the event to the GUI

        return True
Example #6
0
 def ConvertScreenToWorld(self, x, y):
     """
     Return a b2Vec2 in world coordinates of the passed in screen coordinates x, y
     """
     return box2d.b2Vec2((x + self.viewOffset.x) / self.viewZoom, ((self.screenSize.y - y + self.viewOffset.y) / self.viewZoom))
Example #7
0
    def Step(self, settings):
        """
        The main physics step.

        Takes care of physics drawing (callbacks are executed after the world.Step() )
        and drawing additional information.
        """

        # Update the settings based on the GUI
        self.gui_table.updateSettings(settings)

        # Don't do anything if the setting's Hz are <= 0
        if settings.hz > 0.0:
            timeStep = 1.0 / settings.hz
        else:
            timeStep = 0.0
        
        # If paused, display so
        if settings.pause:
            if settings.singleStep:
                settings.singleStep=False
            else:
                timeStep = 0.0

            self.DrawString(5, self.textLine, "****PAUSED****")
            self.textLine += 15

        # Set the flags based on what the settings show (uses a bitwise or mask)
        flags = 0
        if settings.drawShapes:     flags |= box2d.b2DebugDraw.e_shapeBit
        if settings.drawJoints:     flags |= box2d.b2DebugDraw.e_jointBit
        if settings.drawCoreShapes: flags |= box2d.b2DebugDraw.e_coreShapeBit
        if settings.drawAABBs:      flags |= box2d.b2DebugDraw.e_aabbBit
        if settings.drawOBBs:       flags |= box2d.b2DebugDraw.e_obbBit
        if settings.drawPairs:      flags |= box2d.b2DebugDraw.e_pairBit
        if settings.drawCOMs:       flags |= box2d.b2DebugDraw.e_centerOfMassBit
        self.debugDraw.SetFlags(flags)

        # Set the other settings that aren't contained in the flags
        self.world.SetWarmStarting(settings.enableWarmStarting)
    	self.world.SetPositionCorrection(settings.enablePositionCorrection)
    	self.world.SetContinuousPhysics(settings.enableTOI)

        # Reset the collision points
        self.points = []

        # Tell Box2D to step
        self.world.Step(timeStep, settings.iterationCount)
        self.world.Validate()

        # If the bomb is frozen, get rid of it.
        if self.bomb and self.bomb.IsFrozen():
            self.world.DestroyBody(self.bomb)
            self.bomb = None

        if settings.drawStats:
            self.DrawString(5, self.textLine, "proxies(max) = %d(%d), pairs(max) = %d(%d)" % (
                self.world.GetProxyCount(), box2d.b2_maxProxies, self.world.GetPairCount(), box2d.b2_maxPairs) )
            self.textLine += 15

            self.DrawString(5, self.textLine, "bodies/contacts/joints = %d/%d/%d" %
                (self.world.GetBodyCount(), self.world.GetContactCount(), self.world.GetJointCount()))
            self.textLine += 15

            self.DrawString(5, self.textLine, "hz %d iterations %d" %
                (settings.hz, settings.iterationCount))
            self.textLine += 15

            #self.DrawString(5, self.textLine, "heap bytes = %d" % box2d.b2_byteCount) # not wrapped?
            #self.textLine += 15

        if settings.drawFPS: #python version only
            self.DrawString(5, self.textLine, "FPS %d" % self.fps)
            self.textLine += 15
        
        # If there's a mouse joint, draw the connection between the object and the current pointer position.
        if self.mouseJoint:
            body = self.mouseJoint.GetBody2()
            p1 = body.GetWorldPoint(self.mouseJoint.m_localAnchor)
            p2 = self.mouseJoint.m_target

            self.debugDraw.DrawPoint(p1, settings.pointSize, box2d.b2Color(0,1.0,0))
            self.debugDraw.DrawPoint(p2, settings.pointSize, box2d.b2Color(0,1.0,0))
            self.debugDraw.DrawSegment(p1, p2, box2d.b2Color(0.8,0.8,0.8))

        # Draw each of the contact points in different colors.
        if self.settings.drawContactPoints:
            #k_impulseScale = 0.1
            k_axisScale = 0.3

            for point in self.points:
                if point.state == fwContactTypes.contactAdded:
                    self.debugDraw.DrawPoint(point.position, settings.pointSize, box2d.b2Color(0.3, 0.95, 0.3))
                elif point.state == fwContactTypes.contactPersisted:
                    self.debugDraw.DrawPoint(point.position, settings.pointSize, box2d.b2Color(0.3, 0.3, 0.95))
                else: #elif point.state == fwContactTypes.contactRemoved:
                    self.debugDraw.DrawPoint(point.position, settings.pointSize, box2d.b2Color(0.95, 0.3, 0.3))

                if settings.drawContactNormals:
                    p1 = point.position
                    p2 = p1 + k_axisScale * point.normal
                    self.debugDraw.DrawSegment(p1, p2, box2d.b2Color(0.4, 0.9, 0.4))
Example #8
0
def main():
    # gui initialization

    screen = pygame.display.set_mode((width, height))

    caption = "Python Box2D Testbed Demos"
    pygame.display.set_caption(caption)

    theme = gui.Theme("default")
    app = gui.Desktop(theme=theme)

    app.connect(gui.QUIT, app.quit, None)

    main = gui.Container(width=width, height=height)

    main.add(gui.Label("Box2D Testbed Demos", cls="h1"), 20, 20)

    list_size = (width / 2, height / 2)
    list_pos = (width / 2 - list_size[0] / 2, height / 2 - list_size[1] / 2)

    demolist = gui.List(width=list_size[0], height=list_size[1])
    main.add(demolist, list_pos[0], list_pos[1])

    add_demos(demolist)

    buttonw = list_size[0] / 2 - 20
    bottom = list_pos[1] + list_size[1] + 20

    b = gui.Button("Run", width=buttonw)
    main.add(b, list_pos[0], bottom)
    b.connect(gui.CLICK, run_demo, demolist)

    b = gui.Button("Quit", width=buttonw)
    main.add(b, list_pos[0] + buttonw + 30, bottom)
    b.connect(gui.CLICK, lambda x: pygame.event.post(pygame.event.Event(pygame.QUIT)), None)

    # box2d initialization
    z = 10  # scale
    renderer = fwDebugDraw()
    renderer.surface = screen
    renderer.viewZoom = z
    renderer.viewCenter = box2d.b2Vec2(0, 0)
    renderer.width, renderer.height = width, height
    renderer.viewOffset = renderer.viewCenter - box2d.b2Vec2(width, height) / 2
    renderer.SetFlags(box2d.b2DebugDraw.e_shapeBit)
    renderer.DrawSolidPolygon = lambda a, b, c: 0
    renderer.DrawPolygon = lambda a, b, c: 0
    worldAABB = box2d.b2AABB()
    worldAABB.lowerBound.Set(-100.0, -100.0)
    worldAABB.upperBound.Set(100.0, 100.0)
    gravity = box2d.b2Vec2(0.0, -10.0)

    world = box2d.b2World(worldAABB, gravity, True)
    world.SetDebugDraw(renderer)

    bd = box2d.b2BodyDef()
    bd.position.Set(0.0, 0.0)
    ground = world.CreateBody(bd)

    # the borders and the world shapes for the file listing, etc.
    sd = box2d.b2PolygonDef()
    sd.SetAsBox(1, height / z, box2d.b2Vec2(-width / (2 * z) - 1, 0), 0)
    ground.CreateShape(sd)
    sd.SetAsBox(1, height / z, box2d.b2Vec2(width / (2 * z) + 1, 0), 0)
    ground.CreateShape(sd)
    sd.SetAsBox(width / z, 1, box2d.b2Vec2(0, -height / (2 * z) - 1), 0)
    ground.CreateShape(sd)
    sd.SetAsBox(width / z, 1, box2d.b2Vec2(0, height / (2 * z) + 1), 0)
    ground.CreateShape(sd)
    sd.SetAsBox(list_size[0] / (2 * z), list_size[1] / (2 * z))
    ground.CreateShape(sd)

    for i in range(10):
        bd = box2d.b2BodyDef()
        bd.allowSleep = True
        bd.position.Set(
            box2d.b2Random(-width / (2 * z), width / (2 * z)), box2d.b2Random(-height / (2 * z), height / (2 * z))
        )
        bd.isBullet = True
        bomb = world.CreateBody(bd)
        bomb.SetLinearVelocity(-5.0 * bd.position)

        sd = box2d.b2CircleDef()
        sd.radius = 1
        sd.density = 1.0
        sd.restitution = 0.7
        bomb.CreateShape(sd)

        bomb.SetMassFromShapes()

    app.init(main)
    main_loop(world, screen, demolist, app)