Example #1
0
  def add_poly(self, points, density=0.1, friction=2.0, elasticity=0.3):
    """ Mass will be calculated out of mass = A * density 
        Parameter: points == [(int(x), int(y)), (int(x), int(y)), ...]
        Optional: See #physical_parameters
        Returns: pymunk.Shape() (=> .Poly())
    """
    # Make Vec2d's out of the points
    poly_points = []
    for p in points:
      poly_points.append(self.Vec2df(p))
      
    # Reduce polygon points
    poly_points = util.reduce_poly(poly_points)
    if len(poly_points) < 3: 
      return False
    
    # Make a convex hull
    poly_points = util.convex_hull(poly_points)
    
    # Make it counter-clockwise
    if not util.is_clockwise(poly_points):
      poly_points.reverse()
    
    # Change vectors to the point of view of the center
    poly_points_center = util.poly_vectors_around_center(poly_points)
    
    U, A = util.get_poly_UA(poly_points_center)
    A *= 2.5   # get_poly_UA is not working properly with the area :)
    mass = A * density
    
    # Calculate A Good Momentum
    moment = pm.moment_for_poly(mass, poly_points_center, Vec2d(0,0))

    # Create Body
    body = pm.Body(mass, moment)

    center = cx, cy = util.calc_center(poly_points)
    body.position = Vec2d((cx, cy))

    # Create Shape
    shape = pm.Poly(body, poly_points_center, Vec2d(0,0))
    shape.friction = friction
    shape.elasticity = elasticity

    shape.color = self.get_color()
    shape.color2 = self.get_color()
    
    # Append to Space
    self.space.add(body, shape)
    self.element_count += 1
    return shape
Example #2
0
  def add_segment(self, points, inertia=500, mass=150.0, friction=3.0):
    # Add A Multi-Line Segment 
    # Problem: They don't Collide yet

    # Reduce Points
    pointlist = self.reduce_points(points)
    print "Reduced Segment Points: %i -> %i" % (len(points), len(pointlist))

    # Get the Center of the Segment
    center = cx, cy = util.calc_center(pointlist)
    
    # Arrange vectors around center
    pointlist = util.poly_vectors_around_center(pointlist, False)

    # Get Moment of Inertia
    moment = pm.moment_for_poly(mass, pointlist, Vec2d(0,0))

    # Create Body
    body = pm.Body(mass, inertia)          
    body.position = self.Vec2df(center)

    # Create Shapes
    a = b = None
    clr = self.get_color()

    shapes = []
    for p in pointlist:
      if a == None:
        # Starting Point
        a = p
        
      else:
        # Ending Point
        b = p

        # add shape beween a and b
        shape = pm.Segment(body, Vec2d(a), Vec2d(b), 2.0)
        shape.group = 1
        shape.friction = friction
        shape.color = clr
        shapes.append(shape)
        
        # Last Ending Point gets next starting Point
        a = b
          
        # Append to Space
        self.space.add(body, shapes)
    self.element_count += 1
Example #3
0
    def loop(self):       
        for event in pygame.event.get():
            if event.type == QUIT:
                self.running = False
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                self.running = False
            elif event.type == KEYDOWN and event.key == K_p:
                pygame.image.save(self.screen, "playground.png")
                
            elif event.type == MOUSEBUTTONDOWN and event.button == 1: # LMB
                if pygame.key.get_mods() & KMOD_SHIFT:
                    p = self.flipyv(Vec2d(event.pos))
                    self.polys.append(self.create_box(pos = p))
                else:
                    #t = -10000
                    p = self.flipyv(Vec2d(event.pos))
                    self.balls.append(self.create_ball(p))
                    
            elif event.type == MOUSEBUTTONDOWN and event.button == 3: #RMB
                if pygame.key.get_mods() & KMOD_SHIFT:
                    pass
                    
                elif pygame.key.get_mods() & KMOD_CTRL:
                    p = self.flipyv(Vec2d(event.pos))
                    self.wall_points.append(p)
                elif self.shape_to_remove is not None:
                    
                    self.balls = filter(lambda a: a != self.shape_to_remove, self.balls)
                    self.walls = filter(lambda a: a != self.shape_to_remove, self.walls)
                    self.polys = filter(lambda a: a != self.shape_to_remove, self.polys)
                    self.space.remove(self.shape_to_remove.body, self.shape_to_remove)
                    
            elif event.type == KEYUP and event.key in (K_RCTRL, K_LCTRL):
                ### Create Wall
                self.create_wall_segments(self.wall_points)
                self.wall_points = []
            elif event.type == KEYUP and event.key in (K_RSHIFT, K_LSHIFT):
                ### Create Polygon
                 
                if len(self.poly_points) > 0:
                    self.poly_points = u.reduce_poly(self.poly_points, tolerance=5)
                if len(self.poly_points) > 2:
                    self.poly_points = u.convex_hull(self.poly_points)
                    if not u.is_clockwise(self.poly_points):
                        self.poly_points.reverse()
                        
                    center = u.calc_center(self.poly_points)
                    self.poly_points = u.poly_vectors_around_center(self.poly_points)
                    self.polys.append(self.create_poly(self.poly_points, pos=center))
                self.poly_points = []
            elif event.type == KEYDOWN and event.key == K_SPACE:    
                self.run_physics = not self.run_physics
            elif event.type == KEYDOWN and event.key == K_k:
                for x in range (-100,100,25):
                    for y in range(-100,100,25):
                        p = pygame.mouse.get_pos()
                        p = self.flipyv(Vec2d(p)) + (x,y)
                        self.polys.append(self.create_box(pos=p))                
            elif event.type == KEYDOWN and event.key == K_b:
                p = flipyv(Vec2d(pygame.mouse.get_pos())) 
                self.polys.append(self.create_box(p, size=10, mass = 1))
            elif event.type == KEYDOWN and event.key == K_f:
                bp = Vec2d(100,500)
                p = self.flipyv(Vec2d(pygame.mouse.get_pos())) -bp
                ball = self.create_ball(bp)
                p = p.normalized()
                ball.body.apply_impulse(p*1000, (0,0))
                self.balls.append(ball)      
            elif event.type == KEYDOWN and event.key == K_g:
                g = self.space.gravity
                g.rotate(45)
                self.space.gravity = g
                
        mpos = pygame.mouse.get_pos()
        
        if pygame.key.get_mods() & KMOD_SHIFT and pygame.mouse.get_pressed()[2]:
            p = self.flipyv(Vec2d(mpos))
            self.poly_points.append(p)
        self.shape_to_remove = self.space.point_query_first( self.flipyv(Vec2d(mpos)) )
        
        ### Update physics
        if self.run_physics:
            x = 1
            dt = 1.0/60.0/x            
            for x in range(x):
                self.space.step(dt)
                for ball in self.balls:
                    #ball.body.reset_forces()
                    pass
                for poly in self.polys:
                    #poly.body.reset_forces()
                    pass

        ### Draw stuff
        self.draw()

        ### Check for objects outside of the screen, we can remove those
        # Balls
        xs = []
        for ball in self.balls:
            if ball.body.position.x < -1000 or ball.body.position.x > 1000 \
                or ball.body.position.y < -1000 or ball.body.position.y > 1000:
                xs.append(ball)
        for ball in xs:
            self.space.remove(ball, ball.body)
            self.balls.remove(ball)

        # Polys
        xs = []
        for poly in self.polys:
            if poly.body.position.x < -1000 or poly.body.position.x > 1000 \
                or poly.body.position.y < -1000 or poly.body.position.y > 1000:
                xs.append(poly)
        
        for poly in xs:
            self.space.remove(poly, poly.body)
            self.polys.remove(poly)
        
        ### Tick clock and update fps in title
        self.clock.tick(50)
        pygame.display.set_caption("fps: " + str(self.clock.get_fps()))