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 create_shapes(self, model, transform=None): if not transform: transform = model.transform #print('transform', transform) sprite = model.sprite body = model.body position = model.position shapes = [] sprite.position = position center = Vec2d(position) points = sprite.get_hit_box() #print(model.__class__) #print(points) points = to_convex_hull(points, SLOP) #print(points) shape = pymunk.Poly(body, points, transform) shape.friction = 10 shape.elasticity = 0.2 shape.collision_type = model.physics.type shapes.append(shape) return shapes
def create_collision_shape(cls, img, body, threshold=240): poly_points = [] px_arr = pygame.PixelArray(img) min_y = img.get_height() min_x = img.get_width() for x in range(px_arr.shape[1]): for y in range(px_arr.shape[0]): px = 0xFF & px_arr[y][x] if px < threshold and px != 0: if x < min_x: min_x = x if y < min_y: min_y = y poly_points.append((y, x)) hull = autogeometry.to_convex_hull(poly_points, 0.1) return pymunk.shapes.Poly(body, hull, transform=pymunk.Transform(d=-1)), (min_y, min_x)
def test_to_convex_hull(self) -> None: p1: List[Tuple[float, float]] = [(0, 0), (0, 10), (5, 5), (10, 10), (10, 0)] expected = [(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)] actual = a.to_convex_hull(p1, 1) self.assertEqual(actual, expected)
def test_to_convex_hull(self): p1 = [(0,0), (0,10), (5,5), (10, 10), (10,0)] expected = [(0,0), (10,0), (10,10), (0, 10), (0, 0)] actual = a.to_convex_hull(p1, 1) self.assertEqual(actual, expected)
def test_to_convex_hull(self): p1 = [(0, 0), (0, 10), (5, 5), (10, 10), (10, 0)] expected = [(0, 0), (10, 0), (10, 10), (0, 10), (0, 0)] actual = a.to_convex_hull(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)