def _make_star( self, star_npoints: int, star_out_rad: float, star_in_rad: float, ) -> Tuple[List[pm.shapes.Poly], List[List[pm.Vec2d]]]: # Body. star_verts = gtools.compute_star_verts(star_npoints, star_out_rad, star_in_rad) # Create an exact convex decomposition. convex_parts = autogeom.convex_decomposition( star_verts + star_verts[:1], 0) star_hull = autogeom.to_convex_hull(star_verts, 1e-5) star_inertia = pm.moment_for_poly(self.mass, star_hull, (0, 0), 0) self.shape_body = body = pm.Body(self.mass, star_inertia) body.position = self.init_pos body.angle = self.init_angle self.add_to_space(body) # Shape. shapes = [] star_group = self.generate_group_id() for convex_part in convex_parts: shape = pm.Poly(body, convex_part) # Avoid self-intersection with a shape filter. shape.filter = pm.ShapeFilter(group=star_group) shapes.append(shape) del shape return shapes, convex_parts
def _setup_body(self): star_verts = gtools.compute_star_verts(self.star_npoints, self.star_out_rad, self.star_in_rad) self.cvx_parts = autogeom.convex_decomposition( star_verts + star_verts[:1], 0) star_hull = autogeom.to_convex_hull(star_verts, 1e-5) inertia = pm.moment_for_poly(self.mass, star_hull, (0, 0), 0) self.body = pm.Body(self.mass, inertia)
def test_convex_decomposition(self): # TODO: Use a more complicated polygon as test case p1 = [(0,0), (5,0), (10,10), (20,20), (5,5), (0,10), (0,0)] expected = [ [(5.0,5.0), (6.25, 2.5), (20.0,20.0), (5.0,5.0)], [(0.0,0.0), (5.0,0.0), (6.25, 2.5), (5.0,5.0),(0.0,10.0), (0.0,0.0)], ] actual = a.convex_decomposition(p1, .1) actual.sort(key=len)
def test_convex_decomposition(self): # TODO: Use a more complicated polygon as test case p1 = [(0, 0), (5, 0), (10, 10), (20, 20), (5, 5), (0, 10), (0, 0)] expected = [ [(5.0, 5.0), (6.25, 2.5), (20.0, 20.0), (5.0, 5.0)], [(0.0, 0.0), (5.0, 0.0), (6.25, 2.5), (5.0, 5.0), (0.0, 10.0), (0.0, 0.0)], ] actual = a.convex_decomposition(p1, .1) actual.sort(key=len)
def test_convex_decomposition(self) -> None: # TODO: Use a more complicated polygon as test case p1: List[Tuple[float, float]] = [ (0, 0), (5, 0), (10, 10), (20, 20), (5, 5), (0, 10), (0, 0), ] expected = [ [(5.0, 5.0), (6.25, 2.5), (20.0, 20.0), (5.0, 5.0)], [(0.0, 0.0), (5.0, 0.0), (6.25, 2.5), (5.0, 5.0), (0.0, 10.0), (0.0, 0.0)], ] actual = a.convex_decomposition(p1, 0.1) actual.sort(key=len)
def _setup_graphic(self): star_short_verts = gtools.compute_star_verts( self.star_npoints, self.star_out_rad - SHAPE_LINE_THICKNESS, self.star_in_rad - SHAPE_LINE_THICKNESS, ) short_convex_parts = autogeom.convex_decomposition( star_short_verts + star_short_verts[:1], 0) geoms = [] for part in short_convex_parts: geoms.append(r.Poly(part, outline=False)) geoms_outer = [] for part in self.cvx_parts: geoms_outer.append(r.Poly(part, outline=False)) dark_robot_color = darken_rgb(self.robot_color) for g in geoms_outer: g.color = dark_robot_color for g in geoms: g.color = self.robot_color self.graphic_bodies.extend([*geoms_outer, *geoms])
def create_shapes(self, model, transform=None): if not transform: transform = model.transform sprite = model.sprite body = model.body position = model.position shapes = [] sprite.position = position center = Vec2d(position) points = sprite.get_hit_box() #print(points) polys = convex_decomposition(points, SLOP) #print(polys) for poly in polys: shape = pymunk.Poly(body, poly, transform) shape.friction = 10 shape.elasticity = 0.2 shape.collision_type = model.physics.type shapes.append(shape) return shapes
def test_convex_decomposition(self): # TODO: Use a more complicated polygon as test case p1 = [(0,0), (0,10), (5,5), (20, 20), (10,10), (5,0)] expected = [[(0,0), (20,20), (0, 10), (0, 0)]] actual = a.convex_decomposition(p1, .1) self.assertEqual(actual, expected)
def test_convex_decomposition(self): # TODO: Use a more complicated polygon as test case p1 = [(0, 0), (0, 10), (5, 5), (20, 20), (10, 10), (5, 0)] expected = [[(0, 0), (20, 20), (0, 10), (0, 0)]] actual = a.convex_decomposition(p1, .1) self.assertEqual(actual, expected)
def setup(self, *args, **kwargs): super().setup(*args, **kwargs) # Physics. This joint setup was taken form tank.py in the pymunk # examples. if self.shape_type == ShapeType.SQUARE: self.shape_body = body = pm.Body() body.position = self.init_pos body.angle = self.init_angle self.add_to_space(body) side_len = math.sqrt(math.pi) * self.shape_size shape = pm.Poly.create_box( body, (side_len, side_len), # slightly bevelled corners 0.01 * side_len) # FIXME: why is this necessary? Do I need it for the others? shape.mass = self.mass shapes = [shape] del shape elif self.shape_type == ShapeType.CIRCLE: inertia = pm.moment_for_circle(self.mass, 0, self.shape_size, (0, 0)) self.shape_body = body = pm.Body(self.mass, inertia) body.position = self.init_pos body.angle = self.init_angle self.add_to_space(body) shape = pm.Circle(body, self.shape_size, (0, 0)) shapes = [shape] del shape elif self.shape_type == ShapeType.STAR: star_npoints = 5 star_out_rad = 1.3 * self.shape_size star_in_rad = 0.5 * star_out_rad star_verts = gtools.compute_star_verts(star_npoints, star_out_rad, star_in_rad) # create an exact convex decpomosition convex_parts = autogeom.convex_decomposition( star_verts + star_verts[:1], 0) star_hull = autogeom.to_convex_hull(star_verts, 1e-5) star_inertia = pm.moment_for_poly(self.mass, star_hull, (0, 0), 0) self.shape_body = body = pm.Body(self.mass, star_inertia) body.position = self.init_pos body.angle = self.init_angle self.add_to_space(body) shapes = [] star_group = self.generate_group_id() for convex_part in convex_parts: shape = pm.Poly(body, convex_part) # avoid self-intersection with a shape filter shape.filter = pm.ShapeFilter(group=star_group) shapes.append(shape) del shape else: # these are free-form shapes b/c no helpers exist in Pymunk if self.shape_type == ShapeType.TRIANGLE: # shrink to make it look more sensible and easier to grasp factor = 0.8 num_sides = 3 elif self.shape_type == ShapeType.PENTAGON: factor = 1.0 num_sides = 5 elif self.shape_type == ShapeType.HEXAGON: factor = 1.0 num_sides = 6 elif self.shape_type == ShapeType.OCTAGON: factor = 1.0 num_sides = 8 else: raise NotImplementedError("haven't implemented", self.shape_type) side_len = factor * gtools.regular_poly_circ_rad_to_side_length( num_sides, self.shape_size) poly_verts = gtools.compute_regular_poly_verts(num_sides, side_len) inertia = pm.moment_for_poly(self.mass, poly_verts, (0, 0), 0) self.shape_body = body = pm.Body(self.mass, inertia) body.position = self.init_pos body.angle = self.init_angle self.add_to_space(body) shape = pm.Poly(body, poly_verts) shapes = [shape] del shape for shape in shapes: shape.friction = 0.5 self.add_to_space(shape) trans_joint = pm.PivotJoint(self.space.static_body, body, (0, 0), (0, 0)) trans_joint.max_bias = 0 trans_joint.max_force = self.phys_vars.shape_trans_joint_max_force self.add_to_space(trans_joint) rot_joint = pm.GearJoint(self.space.static_body, body, 0.0, 1.0) rot_joint.max_bias = 0 rot_joint.max_force = self.phys_vars.shape_rot_joint_max_force self.add_to_space(rot_joint) # Drawing if self.shape_type == ShapeType.SQUARE: geoms_inner = [r.make_square(side_len - 2 * SHAPE_LINE_THICKNESS)] geoms_outer = [r.make_square(side_len)] elif self.shape_type == ShapeType.CIRCLE: geoms_inner = [ r.make_circle(radius=self.shape_size - SHAPE_LINE_THICKNESS, res=100), ] geoms_outer = [r.make_circle(radius=self.shape_size, res=100)] elif self.shape_type == ShapeType.STAR: star_short_verts = gtools.compute_star_verts( star_npoints, star_out_rad - SHAPE_LINE_THICKNESS, star_in_rad - SHAPE_LINE_THICKNESS) short_convex_parts = autogeom.convex_decomposition( star_short_verts + star_short_verts[:1], 0) geoms_inner = [] for part in short_convex_parts: geoms_inner.append(r.make_polygon(part)) geoms_outer = [] for part in convex_parts: geoms_outer.append(r.make_polygon(part)) elif self.shape_type == ShapeType.OCTAGON \ or self.shape_type == ShapeType.HEXAGON \ or self.shape_type == ShapeType.PENTAGON \ or self.shape_type == ShapeType.TRIANGLE: apothem = gtools.regular_poly_side_length_to_apothem( num_sides, side_len) short_side_len = gtools.regular_poly_apothem_to_side_legnth( num_sides, apothem - SHAPE_LINE_THICKNESS) short_verts = gtools.compute_regular_poly_verts( num_sides, short_side_len) geoms_inner = [r.make_polygon(short_verts)] geoms_outer = [r.make_polygon(poly_verts)] else: raise NotImplementedError("haven't implemented", self.shape_type) for g in geoms_inner: g.set_color(*self.colour) for g in geoms_outer: g.set_color(*darken_rgb(self.colour)) self.shape_xform = r.Transform() shape_compound = r.Compound(geoms_outer + geoms_inner) shape_compound.add_attr(self.shape_xform) self.viewer.add_geom(shape_compound)
def setup(self, *args, **kwargs) -> None: super().setup(*args, **kwargs) # Physics. This joint setup was taken form tank.py in the pymunk # examples. if self.shape_type == ShapeType.SQUARE: side_len = math.sqrt(math.pi) * self.shape_size shapes = self._make_square(side_len) elif self.shape_type == ShapeType.CIRCLE: shapes = self._make_circle() elif self.shape_type == ShapeType.STAR: star_npoints = 5 star_out_rad = 1.3 * self.shape_size star_in_rad = 0.5 * star_out_rad shapes, convex_parts = self._make_star(star_npoints, star_out_rad, star_in_rad) else: # These are free-form shapes b/c no helpers exist in Pymunk. try: factor, num_sides = POLY_TO_FACTOR_SIDE_PARAMS[self.shape_type] except KeyError: raise NotImplementedError("haven't implemented", self.shape_type) side_len = factor * gtools.regular_poly_circ_rad_to_side_length( num_sides, self.shape_size) shapes, poly_verts = self._make_regular_polygon( num_sides, side_len) for shape in shapes: shape.friction = 0.5 self.add_to_space(shape) trans_joint = pm.PivotJoint(self.space.static_body, self.shape_body, (0, 0), (0, 0)) trans_joint.max_bias = 0 trans_joint.max_force = self.phys_vars.shape_trans_joint_max_force self.add_to_space(trans_joint) rot_joint = pm.GearJoint(self.space.static_body, self.shape_body, 0.0, 1.0) rot_joint.max_bias = 0 rot_joint.max_force = self.phys_vars.shape_rot_joint_max_force self.add_to_space(rot_joint) # Graphics. geoms_outer = [] if self.shape_type == ShapeType.SQUARE: geoms = [r.make_square(side_len, outline=True)] elif self.shape_type == ShapeType.CIRCLE: geoms = [r.make_circle(self.shape_size, 100, True)] elif self.shape_type == ShapeType.STAR: star_short_verts = gtools.compute_star_verts( star_npoints, star_out_rad - SHAPE_LINE_THICKNESS, star_in_rad - SHAPE_LINE_THICKNESS, ) short_convex_parts = autogeom.convex_decomposition( star_short_verts + star_short_verts[:1], 0) geoms = [] for part in short_convex_parts: geoms.append(r.Poly(part, outline=False)) geoms_outer = [] for part in convex_parts: geoms_outer.append(r.Poly(part, outline=False)) elif (self.shape_type == ShapeType.OCTAGON or self.shape_type == ShapeType.HEXAGON or self.shape_type == ShapeType.PENTAGON or self.shape_type == ShapeType.TRIANGLE): geoms = [r.Poly(poly_verts, outline=True)] else: raise NotImplementedError("haven't implemented", self.shape_type) if self.shape_type == ShapeType.STAR: for g in geoms_outer: g.color = darken_rgb(self.color) for g in geoms: g.color = self.color else: for g in geoms: g.color = self.color g.outline_color = darken_rgb(self.color) self.shape_xform = r.Transform() shape_compound = r.Compound(geoms_outer + geoms) shape_compound.add_transform(self.shape_xform) self.viewer.add_geom(shape_compound)