Esempio n. 1
0
  def createShape(self, verticies):
    assert len(verticies) >= 2
    
    verticies = self.verticies = map(Vec2d, verticies)
    if is_clockwise(verticies): # fix it if it is clockwise
      average = sum(verticies) / len(verticies)
      verticies.sort(key=lambda v: (average-v).get_angle())

    assert not is_clockwise(verticies), 'OMG, my code is wrong! the poly points are still clockwise'
    assert is_convex(verticies), 'Shape verticies must be convex!'

    if len(verticies) in self.specialPolyTypes:
      self.polyType = self.specialPolyTypes[len(verticies)]
    else:
      self.polyType = pg.GL_POLYGON

    self.shape = Poly(self.body, verticies)


    # note: collisionLayers and collisionType get created by physics.py
    self.shape.layers = self.collisionLayers
    self.shape.collision_type = self.collisionType
    self.shapes = [self.shape]

    bb = self.shape.cache_bb()
    self.size = Vec2d(bb.right-bb.left, bb.top-bb.bottom)
Esempio n. 2
0
    def __init__(self, body, vertices, offset=(0,0), auto_order_vertices=True):
        """Create a polygon
        
            body : `Body`
                The body to attach the poly to
            vertices : [(x,y)] or [`Vec2d`]
                Define a convex hull of the polygon with a counterclockwise
                winding.
            offset : (x,y) or `Vec2d`
                The offset from the body's center of gravity in body local 
                coordinates. 
            auto_order_vertices : bool 
                Set to True to automatically order the vertices. If you know 
                the vertices are in the correct (clockwise) orded you can gain 
                a little performance by setting this to False.
        """
        
        self._body = body
        self.offset = offset
        #self.verts = (Vec2d * len(vertices))(*vertices)
        self.verts = (Vec2d * len(vertices))
        self.verts = self.verts(Vec2d(0, 0))
        
        i_vs = enumerate(vertices)
        if auto_order_vertices and not u.is_clockwise(vertices):
            i_vs = zip(xrange(len(vertices)-1, -1, -1), vertices)
        
        for (i, vertex) in i_vs:
            self.verts[i].x = vertex[0]
            self.verts[i].y = vertex[1]

        self._shape = cp.cpPolyShapeNew(body._body, len(vertices), self.verts, offset)
        self._shapecontents = self._shape.contents
Esempio n. 3
0
 def draw_poly(self, poly):
     body = poly.body
     ps = poly.get_vertices()
     ps.append(ps[0])
     ps = list(map(self.flipyv, ps))
     if u.is_clockwise(ps):
         color = THECOLORS["green"]
     else:
         color = THECOLORS["red"]
     pygame.draw.lines(self.screen, color, False, ps)
Esempio n. 4
0
 def draw_poly(self, poly):
     body = poly.body
     ps = [p.rotated(body.angle) + body.position for p in poly.get_vertices()]
     ps.append(ps[0])
     ps = list(map(self.flipyv, ps))
     if u.is_clockwise(ps):
         color = THECOLORS["green"]
     else:
         color = THECOLORS["red"]
     pygame.draw.lines(self.screen, color, False, ps)
Esempio n. 5
0
 def draw_poly(self, poly):
     body = poly.body
     ps = [p.rotated(body.angle) + body.position for p in poly.get_vertices()]
     ps.append(ps[0])
     ps = list(map(self.flipyv, ps))
     if u.is_clockwise(ps):
         color = THECOLORS["green"]
     else:
         color = THECOLORS["red"]
     pygame.draw.lines(self.screen, color, False, ps)
Esempio n. 6
0
def assert_valid(verts):
    if len(verts) < 3:
        raise TypeError('need 3 or more verts: %s' % (verts,))
    if not is_convex(verts):
        raise TypeError('not convex: %s' % (verts,))
    if area(verts) == 0.0:
        raise TypeError("colinear: %s" % (verts,))
    # note: pymunk considers y-axis points down, ours points up,
    # hence we consider pymunk's 'clockwise' to be anticlockwise
    if not is_clockwise(verts):
        raise TypeError('anticlockwise winding: %s' % (verts,))
Esempio n. 7
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
Esempio n. 8
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()))