3.9 KiB
icon | label |
---|---|
package | box2d |
Box2D by Erin Catto, the world's best 2D physics engine now becomes a built-in module in pkpy v1.1.3
and later.
Setup
box2d
module will be enabled by default for CMake users.
All platforms are supported, including desktop, mobile and web.
You can set option PK_USE_BOX2D
to OFF
in CMakeLists.txt
if you don't want to use it.
Overview
The box2d
module in pkpy provides a high-level, also simplified, interface to Box2D engine, which is suitable for most use cases.
There are two classes in box2d
module: World
and Body
.
World
is the world of Box2D, it is the container of all Body
s.
In most cases, you only need one World
instance.
World
class provides methods to create, destroy and query Body
s
and also methods to step the simulation.
A Body
instance is a physical entity in the world.
A Body
can only have one shape at a time.
For example, a circle, a rectangle, a polygon, etc.
You are allowed to change the shape of a Body
at runtime.
Body
s can be static, dynamic or kinematic.
A static Body
is not affected by forces or collisions.
A dynamic Body
is fully simulated.
A kinematic Body
moves according to its velocity.
Body
class provides methods to set its properties, such as position, velocity, etc.
It also provides methods to apply forces and impulses to it.
!!!
A box2d.Body
in pkpy is an unified wrapper of Box2D's b2Body
,
b2Shape
and b2Fixture
.
It hides the details of Box2D's API and provides a high-level interface.
!!!
API list
from linalg import *
from typing import Iterable
class _Node:
def on_contact_begin(self, other: 'Body'): ...
def on_contact_end(self, other: 'Body'): ...
class World:
gravity: vec2 # gravity of the world, by default vec2(0, 0)
def create_body(self, node: _Node = None) -> 'Body':
"""create a body in the world"""
def get_bodies(self) -> Iterable['Body']:
"""return all bodies in the world."""
def raycast(self, start: vec2, end: vec2) -> list['Body']:
"""raycast from start to end, return all bodies that intersect with the ray."""
def query_aabb(self, p0: vec2, p1: vec2) -> list['Body']:
"""query bodies in the AABB region."""
def step(self, dt: float, velocity_iterations: int, position_iterations: int) -> None:
"""step the simulation, e.g. world.step(1/60, 8, 3)"""
class Body:
type: int # 0-static, 1-kinematic, 2-dynamic, by default 2
mass: float
inertia: float
gravity_scale: float
fixed_rotation: bool
enabled: bool
bullet: bool # whether to use continuous collision detection
position: vec2
rotation: float # in radians (counter-clockwise)
velocity: vec2 # linear velocity
angular_velocity: float
damping: float # linear damping
angular_damping: float
# fixture settings
density: float
friction: float
restitution: float
restitution_threshold: float
is_trigger: bool
def set_box_shape(self, hx: float, hy: float): ...
def set_circle_shape(self, radius: float): ...
def set_polygon_shape(self, points: list[vec2]): ...
def set_chain_shape(self, points: list[vec2]): ...
def apply_force(self, force: vec2, point: vec2): ...
def apply_force_to_center(self, force: vec2): ...
def apply_torque(self, torque: float): ...
def apply_linear_impulse(self, impulse: vec2, point: vec2): ...
def apply_linear_impulse_to_center(self, impulse: vec2): ...
def apply_angular_impulse(self, impulse: float): ...
def get_node(self) -> _Node:
"""return the node that is attached to this body."""
def get_contacts(self) -> list['Body']:
"""return all bodies that are in contact with this body."""
def destroy(self):
"""destroy this body."""
Example
import box2d
world = box2d.World()
body = world.create_body()