simvx.core.physics.nodes2d

Role

The 2D sibling of :mod:~simvx.core.physics.nodes: the user-facing 2D body/shape/area/joint node taxonomy on the 2D transport seam (:class:~simvx.core.physics.world2d.Physics2DWorld). Every node extends

class:

~simvx.core.nodes_2d.node2d.Node2D (scalar world_rotation in radians), resolves its 2D world via :func:resolve_world_2d, and rides the same SceneTree fixed-step plumbing as the 3D nodes (width-aware _BodySync).

These nodes reuse the dimension-agnostic pieces by import (:class:BodyMode,

class:

PhysicsMaterial, :class:Bitmask, :class:Property, :class:Signal) and carry 2D-only state (one_way / one_way_normal, scalar spin). They are NOT wired into any facade this stage; tests import them via this module path. The facade flip + removal of the old 2D nodes is a later stage.

Body + shape-carrier nodes for the 2D physics seam (Stage T2f).

Module Contents

Classes

Contact2D

Node-level 2D collision-event payload for collided / separated.

CollisionShape2D

A Node2D that carries a :class:Shape2D collision-geometry resource.

PhysicsBody2D

A 2D physics body on the 2D seam; its motion mode is a Property.

CharacterBody2D

A 2D character controller (collide-and-slide), distinct from a rigid body.

Area2D

A 2D pure sensor zone (trigger): broadphase-driven overlap detection.

GravityArea2D

A 2D force-field zone: an ADDITIVE gravity effector over the bodies it overlaps.

Joint2D

Base class for the 2D constraint nodes (node-agnostic carriers).

FixedJoint2D

Weld two 2D bodies: lock their full relative transform (position + rotation).

PinJoint2D

Pin two 2D bodies at a single world-space point, rotation free.

HingeJoint2D

Hinge two 2D bodies at :attr:anchor (no axis: 2D rotation is 1-DOF).

SpringJoint2D

Soft distance-spring between the two 2D body centres (compliant, not rigid).

GrooveJoint2D

Slide body_b’s anchor along a groove (line segment) fixed on body_a.

Data

API

simvx.core.physics.nodes2d.log

‘getLogger(…)’

simvx.core.physics.nodes2d.__all__

[‘BodyMode’, ‘Contact2D’, ‘CollisionShape2D’, ‘PhysicsBody2D’, ‘CharacterBody2D’, ‘Area2D’, ‘Gravity…

class simvx.core.physics.nodes2d.Contact2D[source]

Node-level 2D collision-event payload for collided / separated.

The 2D sibling of :class:~simvx.core.physics.nodes.Contact. Node-typed and built by the tree’s dispatch from a node-agnostic ContactEvent2D. The tree fills other with the peer node and reorients normal / velocity so they always point toward the RECEIVING body.

Distinct from the seam-level :class:~simvx.core.physics.world2d.Contact2D (a query/sweep TOI result keyed by handle): this carries the resolved peer node.

Attributes: other: The OTHER body involved in the collision. point: World-space contact point (Vec2). normal: Unit normal oriented TOWARD the receiving body (the separating direction). Degenerate (Vec2(0)) on separated. impulse: Normal impulse magnitude applied this step. 0 on separated and on an enter the solver did not push apart. velocity: Relative velocity of other w.r.t. the receiver at the contact, pre-solve (Vec2). Degenerate (Vec2(0)) on separated.

other: PhysicsBody2D

None

point: simvx.core.math.Vec2

None

normal: simvx.core.math.Vec2

None

impulse: float

None

velocity: simvx.core.math.Vec2

None

class simvx.core.physics.nodes2d.CollisionShape2D(**kwargs)[source]

Bases: simvx.core.nodes_2d.node2d.Node2D

A Node2D that carries a :class:Shape2D collision-geometry resource.

Geometry lives in a single :class:Shape2D resource (CircleShape2D / RectangleShape2D / …), so the node stays open for new shape kinds. A pure data carrier this stage (the seam does narrowphase); it exists so a body can discover its geometry as a child node.

Initialization

shape: simvx.core.physics.shapes2d.Shape2D

‘Property(…)’

build_shape(world: simvx.core.physics.world2d.Physics2DWorld) simvx.core.physics.world2d.ShapeHandle[source]

Build this node’s shape into an opaque seam shape handle.

position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_enter_tree() None
on_exit_tree() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.PhysicsBody2D(**kwargs: object)[source]

Bases: simvx.core.nodes_2d.node2d.Node2D

A 2D physics body on the 2D seam; its motion mode is a Property.

The 2D sibling of :class:~simvx.core.physics.nodes.PhysicsBody3D: one concrete body node with a runtime-mutable :class:BodyMode mode knob (STATIC | KINEMATIC | DYNAMIC). It owns the seam lifecycle (resolve 2D world, build shape, create body on enter; unregister + destroy on exit) and carries the 2D-only one_way / one_way_normal Properties. velocity is a Vec2 accessor; spin is a scalar (2D angular is 1-DOF).

Initialization

mode: simvx.core.physics.world2d.BodyMode

‘Property(…)’

mass: float

‘Property(…)’

collision_layer: int

‘Bitmask(…)’

collision_mask: int

‘Bitmask(…)’

shape: simvx.core.physics.shapes2d.Shape2D | None

‘Property(…)’

material: simvx.core.physics.material.PhysicsMaterial

‘Property(…)’

continuous: bool

‘Property(…)’

one_way: bool

‘Property(…)’

one_way_normal: simvx.core.math.Vec2

‘Property(…)’

collided

‘Signal(…)’

separated

‘Signal(…)’

property handle: simvx.core.physics.world2d.BodyHandle | None[source]

This body’s opaque seam handle, or None if no body was created.

property world: simvx.core.physics.world2d.Physics2DWorld | None[source]

The :class:Physics2DWorld this body was created in, or None.

property is_sleeping: bool[source]

True if the seam body is asleep (basic-tier sleeping). False when inert.

property velocity: simvx.core.math.Vec2[source]

Live linear velocity (Vec2), read/written straight to the seam.

Runtime sim state, NOT a serialized :class:Property. Returns Vec2() when inert (not in tree / no seam body). The setter preserves the current angular velocity (:attr:spin).

property spin: float[source]

Live scalar angular velocity (radians/s, CCW positive), read/written to the seam.

Companion to :attr:velocity; same live-state, never-serialized rules. Returns 0.0 when inert. The setter preserves linear velocity.

push(impulse: simvx.core.math.Vec2 | collections.abc.Sequence[float], *, at: simvx.core.math.Vec2 | collections.abc.Sequence[float] | None = None) None[source]

Apply an instantaneous linear impulse NOW (DYNAMIC-only, inert otherwise).

at is a world-space point; its offset r = at - centre adds a scalar angular impulse via the 2D cross product.

spin_up(angular_impulse: float) None[source]

Apply an instantaneous SCALAR angular impulse (DYNAMIC-only, inert otherwise).

Applied via the body’s real inverse moment of inertia (the 2D backend has a per-shape scalar moment, unlike the 3D inverse_mass stand-in).

add_force(force: simvx.core.math.Vec2 | collections.abc.Sequence[float], *, at: simvx.core.math.Vec2 | collections.abc.Sequence[float] | None = None) None[source]

Accumulate a continuous force, applied during the NEXT fixed step.

Auto-cleared each step (re-call per on_fixed_update to sustain). DYNAMIC-only, inert otherwise. at adds a scalar torque cross(r, force).

add_torque(torque: float) None[source]

Accumulate a continuous SCALAR torque for the NEXT fixed step.

Auto-cleared each step like :meth:add_force. DYNAMIC-only, inert otherwise. Applied via the real inverse moment of inertia.

on_enter_tree() None[source]
move_and_collide(velocity: simvx.core.math.Vec2 | collections.abc.Sequence[float], dt: float = 1.0) simvx.core.physics.nodes2d.Contact2D | None[source]

Move by velocity * dt, stop at the first contact, sync, return it.

Meaningful for mode == KINEMATIC. Sweeps the seam body’s shape and reports the first blocker as a node-level :class:Contact2D. After the sweep the node’s transform is synced SYNCHRONOUSLY from the seam. Returns None on no contact or when inert.

on_exit_tree() None[source]
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.CharacterBody2D(**kwargs: object)[source]

Bases: simvx.core.nodes_2d.node2d.Node2D

A 2D character controller (collide-and-slide), distinct from a rigid body.

The 2D sibling of :class:~simvx.core.physics.nodes.CharacterBody3D: it holds a CharacterHandle (not a BodyHandle), manages its own seam lifecycle, and is deliberately NOT registered for the dynamic auto bulk-sync;

Meth:

move_and_slide syncs the node transform synchronously. velocity is a Vec2 set by game logic each frame and written back (deflected) after each move.

Initialization

slope_limit: float

‘Property(…)’

step_height: float

‘Property(…)’

max_slides: int

‘Property(…)’

skin_width: float

‘Property(…)’

collision_layer: int

‘Bitmask(…)’

collision_mask: int

‘Bitmask(…)’

shape: simvx.core.physics.shapes2d.Shape2D | None

‘Property(…)’

property character: simvx.core.physics.world2d.CharacterHandle | None[source]

This node’s opaque character handle, or None if inert.

property world: simvx.core.physics.world2d.Physics2DWorld | None[source]

The :class:Physics2DWorld this character was created in, or None.

is_on_floor() bool[source]

True if the last :meth:move_and_slide ended on a walkable floor.

is_on_wall() bool[source]

True if the last :meth:move_and_slide hit a wall.

is_on_ceiling() bool[source]

True if the last :meth:move_and_slide hit a ceiling.

move_and_slide(dt: float) None[source]

Collide-and-slide by self.velocity * dt, then sync the transform.

Writes the deflected post-slide velocity back to :attr:velocity, caches floor/wall/ceiling state + :attr:floor_normal, and syncs the node’s transform SYNCHRONOUSLY from the seam. No-op if inert (no collider).

on_enter_tree() None[source]
on_exit_tree() None[source]
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.Area2D(**kwargs: object)[source]

Bases: simvx.core.nodes_2d.node2d.Node2D

A 2D pure sensor zone (trigger): broadphase-driven overlap detection.

The 2D sibling of :class:~simvx.core.physics.nodes.Area3D. Owns a SENSOR body (a flag, not a separate class): it participates in the broadphase but is excluded from collision resolution. Detection is ONE-DIRECTIONAL (the area sees another body iff area.collision_mask & other.collision_layer). Overlap edges arrive as a buffered, deferred event stream drained by the tree; the live overlap sets are maintained from those edges (never a per-frame tree scan).

Geometry follows the standard order (shape Property if set, else first CollisionShape2D child, else inert). The sensor body is STATIC.

Initialization

collision_layer: int

‘Bitmask(…)’

collision_mask: int

‘Bitmask(…)’

monitoring: bool

‘Property(…)’

shape: simvx.core.physics.shapes2d.Shape2D | None

‘Property(…)’

body_entered

‘Signal(…)’

body_exited

‘Signal(…)’

area_entered

‘Signal(…)’

area_exited

‘Signal(…)’

property handle: simvx.core.physics.world2d.BodyHandle | None[source]

This area’s opaque sensor-body handle, or None if inert.

property world: simvx.core.physics.world2d.Physics2DWorld | None[source]

The :class:Physics2DWorld this area’s sensor was created in, or None.

get_overlapping_bodies(*, group: str | None = None, type: simvx.core.physics.nodes2d.Area2D.get_overlapping_bodies.type[simvx.core.physics.nodes2d.PhysicsBody2D] | None = None) list[simvx.core.physics.nodes2d.PhysicsBody2D][source]

Bodies currently overlapping this area (live, as of the last step).

Off-seam peers (handle is None: destroyed / removed mid-overlap) are filtered here so polling never reports a body that has left the simulation.

The optional filters narrow the result without a tree scan (they test the already-maintained overlap set): this is the durable, broadphase-backed replacement for the old arcade CharacterBody.get_overlapping(group=, body_type=) poll. Both are ANDed when given:

Args: group: When set, keep only bodies that belong to this SceneTree group (body.is_in_group(group)). The canonical “what of kind X am I touching?” query (e.g. area.get_overlapping_bodies(group="mobs")). type: When set, keep only bodies that are instances of this :class:PhysicsBody2D subclass (isinstance(body, type)).

Returns: The overlapping bodies (live, off-seam peers filtered) matching every supplied filter, in arbitrary order.

get_overlapping_areas() list[simvx.core.physics.nodes2d.Area2D][source]

Other areas currently overlapping this area (live, as of the last step).

on_enter_tree() None[source]
on_exit_tree() None[source]
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.GravityArea2D(**kwargs: object)[source]

Bases: simvx.core.physics.nodes2d.Area2D

A 2D force-field zone: an ADDITIVE gravity effector over the bodies it overlaps.

The 2D sibling of :class:~simvx.core.physics.nodes.GravityArea3D. Inherits the entire sensor mechanism unchanged and adds an :meth:on_fixed_update handler that, each fixed step, applies a field (additive on top of world gravity) to every DYNAMIC overlapping body. Two independent SUMMING components:

  • Directional (:attr:gravity): a uniform acceleration (Vec2) applied regardless of body mass, exactly like world gravity.

  • Point (:attr:point_gravity / :attr:point_strength): a CONSTANT acceleration of magnitude :attr:point_strength toward the area centre (:attr:world_position).

The acceleration becomes a force via add_force(mass * accel) (the integrator divides by mass, so the net effect is mass-INDEPENDENT, like gravity). add_force is auto-cleared each step, so the field is freshly re-applied every fixed step and consumed once by the following world.step.

Initialization

gravity: simvx.core.math.Vec2

‘Property(…)’

point_gravity: bool

‘Property(…)’

point_strength: float

‘Property(…)’

on_fixed_update(dt: float) None[source]

Apply the additive gravity field to every DYNAMIC overlapping body.

Runs BEFORE world.step (the tree drives node on_fixed_update first, then steps the worlds), accumulating a fresh force consumed by that step. dt is accepted to match the hook signature but not used to scale (add_force is a continuous force, not an impulse).

collision_layer: int

‘Bitmask(…)’

collision_mask: int

‘Bitmask(…)’

monitoring: bool

‘Property(…)’

shape: simvx.core.physics.shapes2d.Shape2D | None

‘Property(…)’

body_entered

‘Signal(…)’

body_exited

‘Signal(…)’

area_entered

‘Signal(…)’

area_exited

‘Signal(…)’

property handle: simvx.core.physics.world2d.BodyHandle | None
property world: simvx.core.physics.world2d.Physics2DWorld | None
get_overlapping_bodies(*, group: str | None = None, type: simvx.core.physics.nodes2d.Area2D.get_overlapping_bodies.type[simvx.core.physics.nodes2d.PhysicsBody2D] | None = None) list[simvx.core.physics.nodes2d.PhysicsBody2D]
get_overlapping_areas() list[simvx.core.physics.nodes2d.Area2D]
on_enter_tree() None
on_exit_tree() None
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.Joint2D(*, body_a: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, body_b: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, **kwargs: object)[source]

Bases: simvx.core.nodes_2d.node2d.Node2D

Base class for the 2D constraint nodes (node-agnostic carriers).

The 2D sibling of :class:~simvx.core.physics.nodes.Joint3D. Constrains two

Class:

PhysicsBody2D instances via the 2D seam; a thin carrier that owns the seam-constraint lifecycle (create on enter-tree, remove on exit-tree). Body references (:attr:body_a / :attr:body_b) are PLAIN instance attributes, set programmatically or via the constructor.

Same resolution rules as the 3D base: a missing body is a soft-inert no-op; a cross-world (or missing-world) pair after handles resolve is a ValueError. ALWAYS add a joint AFTER both of its bodies (or re-enter it).

Initialization

property joint: simvx.core.physics.world2d.JointHandle | None[source]

This joint’s opaque seam handle, or None if inert / not created.

property world: simvx.core.physics.world2d.Physics2DWorld | None[source]

The :class:Physics2DWorld this joint was created in, or None.

on_enter_tree() None[source]
on_exit_tree() None[source]
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.FixedJoint2D(*, body_a: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, body_b: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, **kwargs: object)[source]

Bases: simvx.core.physics.nodes2d.Joint2D

Weld two 2D bodies: lock their full relative transform (position + rotation).

Captures the current relative pose at enter-tree and holds it, so the two bodies move as one rigid assembly. No anchor Properties.

Initialization

property joint: simvx.core.physics.world2d.JointHandle | None
property world: simvx.core.physics.world2d.Physics2DWorld | None
on_enter_tree() None
on_exit_tree() None
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.PinJoint2D(*, body_a: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, body_b: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, **kwargs: object)[source]

Bases: simvx.core.physics.nodes2d.Joint2D

Pin two 2D bodies at a single world-space point, rotation free.

The two bodies cannot separate at :attr:anchor but rotate freely about it.

Initialization

anchor: simvx.core.math.Vec2

‘Property(…)’

property joint: simvx.core.physics.world2d.JointHandle | None
property world: simvx.core.physics.world2d.Physics2DWorld | None
on_enter_tree() None
on_exit_tree() None
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.HingeJoint2D(*, body_a: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, body_b: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, **kwargs: object)[source]

Bases: simvx.core.physics.nodes2d.Joint2D

Hinge two 2D bodies at :attr:anchor (no axis: 2D rotation is 1-DOF).

2D rotation is 1-DOF, so a 2D hinge has no axis argument: this tier it is a pin at anchor (motors / angular limits are a follow-on).

Initialization

anchor: simvx.core.math.Vec2

‘Property(…)’

property joint: simvx.core.physics.world2d.JointHandle | None
property world: simvx.core.physics.world2d.Physics2DWorld | None
on_enter_tree() None
on_exit_tree() None
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.SpringJoint2D(*, body_a: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, body_b: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, **kwargs: object)[source]

Bases: simvx.core.physics.nodes2d.Joint2D

Soft distance-spring between the two 2D body centres (compliant, not rigid).

Pulls the two body centres toward :attr:rest_length apart with

Attr:

stiffness (N/m) and :attr:damping (N*s/m). Intentionally compliant.

Initialization

rest_length: float

‘Property(…)’

stiffness: float

‘Property(…)’

damping: float

‘Property(…)’

property joint: simvx.core.physics.world2d.JointHandle | None
property world: simvx.core.physics.world2d.Physics2DWorld | None
on_enter_tree() None
on_exit_tree() None
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()
class simvx.core.physics.nodes2d.GrooveJoint2D(*, body_a: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, body_b: simvx.core.physics.nodes2d.PhysicsBody2D | None = None, **kwargs: object)[source]

Bases: simvx.core.physics.nodes2d.Joint2D

Slide body_b’s anchor along a groove (line segment) fixed on body_a.

The 2D-only pymunk-native slider-on-a-line constraint (no 3D equivalent).

Attr:

groove_a / :attr:groove_b are body-local points in body_a’s frame defining the groove segment; :attr:anchor_b is a body-local point in body_b’s frame. body_b’s anchor is held on that segment: it slides freely ALONG the groove and is pinned PERPENDICULAR to it, clamped between the endpoints.

Basic-tier honesty: a hard 1-DOF lock with no endpoint-clamp softness or slide motor, and the groove direction is fixed in world axes at create time rather than rotating with body_a (anchors are not rotated; parity with the other 2D joints). The exact rotating-groove and motor live in the pymunk backend.

Initialization

groove_a: simvx.core.math.Vec2

‘Property(…)’

groove_b: simvx.core.math.Vec2

‘Property(…)’

anchor_b: simvx.core.math.Vec2

‘Property(…)’

property joint: simvx.core.physics.world2d.JointHandle | None
property world: simvx.core.physics.world2d.Physics2DWorld | None
on_enter_tree() None
on_exit_tree() None
position

‘_SpatialVecProperty(…)’

rotation

‘Property(…)’

scale

‘_SpatialVecProperty(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

render_layer

‘Property(…)’

set_render_layer(index: int, enabled: bool = True) None
is_on_render_layer(index: int) bool
property absolute_z_index: int
property rotation_degrees: float
property world_position: simvx.core.math.types.Vec2
property world_rotation: float
property world_scale: simvx.core.math.types.Vec2
property world_transform: tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2, float]
property forward: simvx.core.math.types.Vec2
property right: simvx.core.math.types.Vec2
translate(offset: tuple[float, float] | numpy.ndarray)
rotate(radians: float)
rotate_deg(degrees: float)
look_at(target: tuple[float, float] | numpy.ndarray)
transform_points(points: list[simvx.core.math.types.Vec2]) list[simvx.core.math.types.Vec2]
draw_polygon(renderer, points: list[simvx.core.math.types.Vec2], closed=True, colour=None)
wrap_screen(margin: float = 20)
hdr

‘Property(…)’

queue_redraw() None
property render_dirty: bool
property transform_render_dirty: bool
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property update_mode: simvx.core.descriptors.UpdateMode
property visible: bool
reset_error() None
add_child(node: simvx.core.node.Node) simvx.core.node.Node
remove_child(node: simvx.core.node.Node)
reparent(new_parent: simvx.core.node.Node)
get_node(path: str) simvx.core.node.Node
get_node_or_none(path: str) simvx.core.node.Node | None
find(target, *, direct: bool = False)
find_all(target, *, direct: bool = False)
walk(*, include_self: bool = True) collections.abc.Iterator[simvx.core.node.Node]
property path: str
add_to_group(group: str)
remove_from_group(group: str)
is_in_group(group: str) bool
on_ready() None
on_update(dt: float) None
on_fixed_update(dt: float) None
on_draw(renderer) None
on_picked(event: simvx.core.events.InputEvent) None
on_unhandled_input(event: simvx.core.events.TreeInputEvent) None
start_coroutine(gen: simvx.core.descriptors.Coroutine) simvx.core.descriptors.CoroutineHandle
stop_coroutine(gen_or_handle)
clear_children()
destroy()
call_deferred(method: collections.abc.Callable[..., Any], *args: Any) None
property app
property tree: simvx.core.scene_tree.SceneTree
property physics
property physics_2d
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()