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(scalarworld_rotationin 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, scalarspin). 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¶
Node-level 2D collision-event payload for |
|
A |
|
A 2D physics body on the 2D seam; its motion mode is a Property. |
|
A 2D character controller (collide-and-slide), distinct from a rigid body. |
|
A 2D pure sensor zone (trigger): broadphase-driven overlap detection. |
|
A 2D force-field zone: an ADDITIVE gravity effector over the bodies it overlaps. |
|
Base class for the 2D constraint nodes (node-agnostic carriers). |
|
Weld two 2D bodies: lock their full relative transform (position + rotation). |
|
Pin two 2D bodies at a single world-space point, rotation free. |
|
Hinge two 2D bodies at :attr: |
|
Soft distance-spring between the two 2D body centres (compliant, not rigid). |
|
Slide |
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-agnosticContactEvent2D. The tree fillsotherwith the peer node and reorientsnormal/velocityso 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)) onseparated. impulse: Normal impulse magnitude applied this step.0onseparatedand on anenterthe solver did not push apart. velocity: Relative velocity ofotherw.r.t. the receiver at the contact, pre-solve (Vec2). Degenerate (Vec2(0)) onseparated.- 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.Node2DA
Node2Dthat carries a :class:Shape2Dcollision-geometry resource.Geometry lives in a single :class:
Shape2Dresource (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.Node2DA 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:BodyModemodeknob (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-onlyone_way/one_way_normalProperties.velocityis aVec2accessor;spinis 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
Noneif no body was created.
- property world: simvx.core.physics.world2d.Physics2DWorld | None[source]¶
The :class:
Physics2DWorldthis body was created in, orNone.
- 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. ReturnsVec2()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. Returns0.0when 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).
atis a world-space point; its offsetr = at - centreadds 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_massstand-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_updateto sustain). DYNAMIC-only, inert otherwise.atadds a scalar torquecross(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.
- 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. ReturnsNoneon no contact or when inert.
- 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.Node2DA 2D character controller (collide-and-slide), distinct from a rigid body.
The 2D sibling of :class:
~simvx.core.physics.nodes.CharacterBody3D: it holds aCharacterHandle(not aBodyHandle), manages its own seam lifecycle, and is deliberately NOT registered for the dynamic auto bulk-sync;- Meth:
move_and_slidesyncs the node transform synchronously.velocityis aVec2set 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
Noneif inert.
- property world: simvx.core.physics.world2d.Physics2DWorld | None[source]¶
The :class:
Physics2DWorldthis character was created in, orNone.
- 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).
- 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.Node2DA 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 iffarea.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 (
shapeProperty if set, else firstCollisionShape2Dchild, 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
Noneif inert.
- property world: simvx.core.physics.world2d.Physics2DWorld | None[source]¶
The :class:
Physics2DWorldthis area’s sensor was created in, orNone.
- 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:PhysicsBody2Dsubclass (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).
- 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.Area2DA 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_updatehandler 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_strengthtoward 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_forceis auto-cleared each step, so the field is freshly re-applied every fixed step and consumed once by the followingworld.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 nodeon_fixed_updatefirst, then steps the worlds), accumulating a fresh force consumed by that step.dtis accepted to match the hook signature but not used to scale (add_forceis 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.Node2DBase class for the 2D constraint nodes (node-agnostic carriers).
The 2D sibling of :class:
~simvx.core.physics.nodes.Joint3D. Constrains two- Class:
PhysicsBody2Dinstances 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
Noneif inert / not created.
- property world: simvx.core.physics.world2d.Physics2DWorld | None[source]¶
The :class:
Physics2DWorldthis joint was created in, orNone.
- 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.Joint2DWeld 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.Joint2DPin two 2D bodies at a single world-space point, rotation free.
The two bodies cannot separate at :attr:
anchorbut 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.Joint2DHinge two 2D bodies at :attr:
anchor(no axis: 2D rotation is 1-DOF).2D rotation is 1-DOF, so a 2D hinge has no
axisargument: this tier it is a pin atanchor(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.Joint2DSoft distance-spring between the two 2D body centres (compliant, not rigid).
Pulls the two body centres toward :attr:
rest_lengthapart 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.Joint2DSlide
body_b’s anchor along a groove (line segment) fixed onbody_a.The 2D-only pymunk-native slider-on-a-line constraint (no 3D equivalent).
- Attr:
groove_a/ :attr:groove_bare body-local points inbody_a’s frame defining the groove segment; :attr:anchor_bis a body-local point inbody_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__()¶