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
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
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()))