def run_gravity(body_1: pymunk.Body, body_2: pymunk.Body, g): """Function that can be called to apply gravitational impulses between two bodies. g is the gravitational constant""" distance = 2 * math.sqrt((body_1.position[0] - body_2.position[0])**2 + (body_1.position[1] - body_2.position[0])**2) force = body_1.mass * body_2.mass / (distance**2) * g impulse = Vec2d(force, 0) impulse = impulse.rotated((body_1.position - body_2.position).angle) if distance >= 5: body_1.apply_impulse_at_world_point(impulse.rotated(math.pi), body_2.position) body_2.apply_impulse_at_world_point(impulse, body_2.position)
class Object: def __init__( self, space: Space, shape_type: str, pos: Tuple[float, float], scale: float = 1., mass: float = 1, static: bool = False, friction: float = 1., color: Tuple[float, float, float] = (1., 1., 1.), ): self.space = space self.shape_type = shape_type self.static = static self._scale = scale self.color = color padding = 0.03 if not static: if self.shape_type == "box": moment = pymunk.moment_for_box(mass, (self.scale, self.scale)) elif self.shape_type == "circle": moment = pymunk.moment_for_circle(mass, 0, self.scale / 2.) else: raise ValueError(f"Invalid shape_type '{self.shape_type}'") self.mass = mass self.body = Body(mass, moment) self.body.position = pos self._static_position = None if self.shape_type == "box": self.shape = Poly.create_box(self.body, (1, 1)) elif self.shape_type == "circle": self.shape = Circle(self.body, self.scale / 2. - padding) # static else: self.mass = 0 self.body = self.space.static_body self._static_position = Vec2d(*pos) if self.shape_type == "box": self.shape = Poly( self.space.static_body, [(pos[0] + p[0] * scale, pos[1] + p[1] * scale) for p in SHAPE_TYPES[self.shape_type]["polygon"]]) self.shape.get_vertices() elif self.shape_type == "circle": self.shape = Circle(self.space.static_body, self.scale / 2. - padding, offset=pos) self.shape.friction = friction @property def position(self) -> Vec2d: if self._static_position: return self._static_position return self.body.position @property def rotation(self) -> float: return self.body.angle @property def scale(self) -> float: return self._scale @property def texture_idx(self) -> int: return 13 if self.shape_type == "circle" else 10 def __repr__(self): return f"Object({self.mass}, {self.position})" def apply_impulse(self, impulse: Tuple[float, float], point: Optional[Tuple[float, float]] = (0, 0)): if not self.static: point = self.position + point self.body.apply_impulse_at_world_point(impulse, point) def add_to_mesh(self, mesh: TriangleMesh): offset = self.body.position rotation = self.body.angle if isinstance(self.shape, Poly): vertices = [ glm.vec3(v.rotated(rotation) + offset, 0) for v in self.shape.get_vertices() ] for i in range(len(vertices) - 1): mesh.add_triangle( vertices[0], vertices[i + 1], vertices[i], ) elif self.shape_type == "circle": num_seg = 4 center = glm.vec3(offset, 0) vertices = [ glm.vec3( Vec2d(math.sin(s / num_seg * math.pi), math.cos(s / num_seg * math.pi)).rotated(rotation) * self.scale / 2. + offset, 0) for s in range(num_seg * 2 + 1) ] for i in range(len(vertices) - 1): mesh.add_triangle( center, vertices[i + 1], vertices[i], ) def update(self, time: float, dt: float): pass