simvx.core.physics_nodes¶

Physics/collision nodes: CharacterBody, CollisionShape, Area, ShapeCast (2D and 3D).

Module Contents¶

Classes¶

CharacterBody2D

2D node with velocity, movement, and collision response.

CollisionShape2D

2D collision shape: circle (default) or axis-aligned rectangle.

Area2D

2D trigger zone that detects overlapping bodies and areas.

CharacterBody3D

3D node with velocity, movement, and collision response.

CollisionShape3D

Sphere collision shape. Attach as child of a CharacterBody3D.

Area3D

3D trigger zone that detects overlapping bodies and areas.

Data¶

log

API¶

simvx.core.physics_nodes.log[source]¶

‘getLogger(…)’

class simvx.core.physics_nodes.CharacterBody2D(collision=None, **kwargs)[source]¶

Bases: simvx.core.physics_nodes._CharacterBodyBase, simvx.core.nodes_2d.node2d.Node2D

2D node with velocity, movement, and collision response.

Uses CollisionShape2D children for circle or rectangle collision. Screen coordinates: Y-down, so floor normal defaults to (0, -1).

Initialization

collision_layer¶

‘Property(…)’

collision_mask¶

‘Property(…)’

max_slides¶

‘Property(…)’

move_and_slide(dt: float = 1.0)[source]¶

Apply velocity with collision response. Resolves overlaps and slides along surfaces.

get_overlapping(group: str = None, body_type: type = None) list[simvx.core.physics_nodes.CharacterBody2D][source]¶

Find all CharacterBody2D nodes whose collision overlaps ours.

is_on_floor() bool¶
is_on_wall() bool¶
is_on_ceiling() bool¶
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 position: simvx.core.math.types.Vec2¶
property rotation: float¶
property rotation_degrees: float¶
property scale: simvx.core.math.types.Vec2¶
property world_position: simvx.core.math.types.Vec2¶
property world_rotation: float¶
property world_scale: simvx.core.math.types.Vec2¶
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)¶
strict_errors: ClassVar[bool]¶

True

script_error_raised¶

‘Signal(…)’

classmethod __init_subclass__(**kwargs)¶
property name: str¶
property process_mode: simvx.core.descriptors.ProcessMode¶
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¶
find_child(name: str, recursive: bool = False) simvx.core.node.Node | None¶
find(node_type: type, recursive: bool = True) simvx.core.node.Node | None¶
find_all(node_type: type, recursive: bool = True) list¶
property path: str¶
add_to_group(group: str)¶
remove_from_group(group: str)¶
is_in_group(group: str) bool¶
ready() None¶
enter_tree() None¶
exit_tree() None¶
process(dt: float) None¶
physics_process(dt: float) None¶
draw(renderer) None¶
input_event(event: simvx.core.events.InputEvent) None¶
input(event: simvx.core.events.TreeInputEvent) None¶
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()¶
property app¶
property tree: simvx.core.scene_tree.SceneTree¶
get_tree() simvx.core.scene_tree.SceneTree¶
__getitem__(key: str)¶
classmethod get_properties() dict[str, simvx.core.descriptors.Property]¶
__repr__()¶
class simvx.core.physics_nodes.CollisionShape2D(position=None, rotation: float = 0.0, scale=None, **kwargs)[source]¶

Bases: simvx.core.physics_nodes._CollisionShapeBase, simvx.core.nodes_2d.node2d.Node2D

2D collision shape: circle (default) or axis-aligned rectangle.

Circle mode (default): set radius. Rectangle mode: set extents to a Vec2(half_width, half_height). When extents is non-zero the shape is treated as an AABB and radius is ignored for overlap tests.

Initialization

radius¶

‘Property(…)’

extents¶

‘Property(…)’

gizmo_colour¶

‘Property(…)’

property is_rect: bool¶

True when extents are non-zero (rectangle mode).

overlaps(other: simvx.core.physics_nodes.CollisionShape2D) bool[source]¶

Test overlap with another CollisionShape2D (circle or rect).

overlaps_point(point: tuple[float, float] | numpy.ndarray) bool[source]¶

Test if a point is inside this shape.

get_penetration(other: simvx.core.physics_nodes.CollisionShape2D) tuple[simvx.core.math.types.Vec2, float] | None[source]¶

Return (normal, depth) to push self out of other, or None.

get_gizmo_lines() list[tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2]][source]¶

Return wireframe line segments for the collision shape in world space.

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 position: simvx.core.math.types.Vec2¶
property rotation: float¶
property rotation_degrees: float¶
property scale: simvx.core.math.types.Vec2¶
property world_position: simvx.core.math.types.Vec2¶
property world_rotation: float¶
property world_scale: simvx.core.math.types.Vec2¶
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)¶
strict_errors: ClassVar[bool]¶

True

script_error_raised¶

‘Signal(…)’

classmethod __init_subclass__(**kwargs)¶
property name: str¶
property process_mode: simvx.core.descriptors.ProcessMode¶
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¶
find_child(name: str, recursive: bool = False) simvx.core.node.Node | None¶
find(node_type: type, recursive: bool = True) simvx.core.node.Node | None¶
find_all(node_type: type, recursive: bool = True) list¶
property path: str¶
add_to_group(group: str)¶
remove_from_group(group: str)¶
is_in_group(group: str) bool¶
ready() None¶
enter_tree() None¶
exit_tree() None¶
process(dt: float) None¶
physics_process(dt: float) None¶
draw(renderer) None¶
input_event(event: simvx.core.events.InputEvent) None¶
input(event: simvx.core.events.TreeInputEvent) None¶
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()¶
property app¶
property tree: simvx.core.scene_tree.SceneTree¶
get_tree() simvx.core.scene_tree.SceneTree¶
__getitem__(key: str)¶
classmethod get_properties() dict[str, simvx.core.descriptors.Property]¶
__repr__()¶
class simvx.core.physics_nodes.Area2D(**kwargs)[source]¶

Bases: simvx.core.physics_nodes._AreaBase, simvx.core.nodes_2d.node2d.Node2D

2D trigger zone that detects overlapping bodies and areas.

Add CollisionShape2D children to define the detection region. Emits body_entered/body_exited when CharacterBody2D nodes overlap, and area_entered/area_exited for other Area2D nodes.

Initialization

collision_layer¶

‘Property(…)’

collision_mask¶

‘Property(…)’

monitoring¶

‘Property(…)’

gizmo_colour¶

‘Property(…)’

get_gizmo_lines() list[tuple[simvx.core.math.types.Vec2, simvx.core.math.types.Vec2]][source]¶

Return gizmo lines from child collision shapes, or a default diamond if none.

physics_process(dt: float)[source]¶
get_overlapping_bodies() list¶
get_overlapping_areas() list¶
has_overlapping_bodies() bool¶
has_overlapping_areas() bool¶
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 position: simvx.core.math.types.Vec2¶
property rotation: float¶
property rotation_degrees: float¶
property scale: simvx.core.math.types.Vec2¶
property world_position: simvx.core.math.types.Vec2¶
property world_rotation: float¶
property world_scale: simvx.core.math.types.Vec2¶
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)¶
strict_errors: ClassVar[bool]¶

True

script_error_raised¶

‘Signal(…)’

classmethod __init_subclass__(**kwargs)¶
property name: str¶
property process_mode: simvx.core.descriptors.ProcessMode¶
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¶
find_child(name: str, recursive: bool = False) simvx.core.node.Node | None¶
find(node_type: type, recursive: bool = True) simvx.core.node.Node | None¶
find_all(node_type: type, recursive: bool = True) list¶
property path: str¶
add_to_group(group: str)¶
remove_from_group(group: str)¶
is_in_group(group: str) bool¶
ready() None¶
enter_tree() None¶
exit_tree() None¶
process(dt: float) None¶
draw(renderer) None¶
input_event(event: simvx.core.events.InputEvent) None¶
input(event: simvx.core.events.TreeInputEvent) None¶
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()¶
property app¶
property tree: simvx.core.scene_tree.SceneTree¶
get_tree() simvx.core.scene_tree.SceneTree¶
__getitem__(key: str)¶
classmethod get_properties() dict[str, simvx.core.descriptors.Property]¶
__repr__()¶
class simvx.core.physics_nodes.CharacterBody3D(collision=None, **kwargs)[source]¶

Bases: simvx.core.physics_nodes._CharacterBodyBase, simvx.core.nodes_3d.node3d.Node3D

3D node with velocity, movement, and collision response.

Uses sphere-sphere collision via CollisionShape3D children. Y-up convention: floor normal defaults to (0, 1, 0).

Initialization

collision_layer¶

‘Property(…)’

collision_mask¶

‘Property(…)’

max_slides¶

‘Property(…)’

move_and_slide(dt: float = 1.0)[source]¶

Apply velocity with collision response. Resolves overlaps and slides along surfaces.

get_overlapping(group: str = None, body_type: type = None) list[simvx.core.physics_nodes.CharacterBody3D][source]¶
is_on_floor() bool¶
is_on_wall() bool¶
is_on_ceiling() bool¶
render_layer¶

‘Property(…)’

property position¶
property rotation: simvx.core.math.types.Quat¶
property scale¶
property rotation_degrees: simvx.core.math.types.Vec3¶
property world_position: simvx.core.math.types.Vec3¶
property world_rotation: simvx.core.math.types.Quat¶
property world_scale: simvx.core.math.types.Vec3¶
property forward: simvx.core.math.types.Vec3¶
property right: simvx.core.math.types.Vec3¶
property up: simvx.core.math.types.Vec3¶
translate(offset: tuple[float, float, float] | numpy.ndarray)¶
translate_global(offset: tuple[float, float, float] | numpy.ndarray)¶
rotate(axis: tuple[float, float, float] | numpy.ndarray, angle: float)¶
rotate_x(angle: float)¶
rotate_y(angle: float)¶
rotate_z(angle: float)¶
look_at(target: tuple[float, float, float] | numpy.ndarray, up=None)¶
set_render_layer(index: int, enabled: bool = True) None¶
is_on_render_layer(index: int) bool¶
wrap_bounds(bounds: tuple[float, float, float] | numpy.ndarray, margin: float = 1.0)¶
strict_errors: ClassVar[bool]¶

True

script_error_raised¶

‘Signal(…)’

classmethod __init_subclass__(**kwargs)¶
property name: str¶
property process_mode: simvx.core.descriptors.ProcessMode¶
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¶
find_child(name: str, recursive: bool = False) simvx.core.node.Node | None¶
find(node_type: type, recursive: bool = True) simvx.core.node.Node | None¶
find_all(node_type: type, recursive: bool = True) list¶
property path: str¶
add_to_group(group: str)¶
remove_from_group(group: str)¶
is_in_group(group: str) bool¶
ready() None¶
enter_tree() None¶
exit_tree() None¶
process(dt: float) None¶
physics_process(dt: float) None¶
draw(renderer) None¶
input_event(event: simvx.core.events.InputEvent) None¶
input(event: simvx.core.events.TreeInputEvent) None¶
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()¶
property app¶
property tree: simvx.core.scene_tree.SceneTree¶
get_tree() simvx.core.scene_tree.SceneTree¶
__getitem__(key: str)¶
classmethod get_properties() dict[str, simvx.core.descriptors.Property]¶
__repr__()¶
class simvx.core.physics_nodes.CollisionShape3D(position=None, rotation=None, scale=None, **kwargs)[source]¶

Bases: simvx.core.physics_nodes._CollisionShapeBase, simvx.core.nodes_3d.node3d.Node3D

Sphere collision shape. Attach as child of a CharacterBody3D.

Initialization

radius¶

‘Property(…)’

pickable¶

‘Property(…)’

gizmo_colour¶

‘Property(…)’

overlaps(other: simvx.core.physics_nodes.CollisionShape3D) bool[source]¶
overlaps_point(point: tuple[float, float, float] | numpy.ndarray) bool[source]¶
get_gizmo_lines() list[tuple[simvx.core.math.types.Vec3, simvx.core.math.types.Vec3]][source]¶

Return wireframe line segments for the collision sphere (3 circles: XY, XZ, YZ).

render_layer¶

‘Property(…)’

property position¶
property rotation: simvx.core.math.types.Quat¶
property scale¶
property rotation_degrees: simvx.core.math.types.Vec3¶
property world_position: simvx.core.math.types.Vec3¶
property world_rotation: simvx.core.math.types.Quat¶
property world_scale: simvx.core.math.types.Vec3¶
property forward: simvx.core.math.types.Vec3¶
property right: simvx.core.math.types.Vec3¶
property up: simvx.core.math.types.Vec3¶
translate(offset: tuple[float, float, float] | numpy.ndarray)¶
translate_global(offset: tuple[float, float, float] | numpy.ndarray)¶
rotate(axis: tuple[float, float, float] | numpy.ndarray, angle: float)¶
rotate_x(angle: float)¶
rotate_y(angle: float)¶
rotate_z(angle: float)¶
look_at(target: tuple[float, float, float] | numpy.ndarray, up=None)¶
set_render_layer(index: int, enabled: bool = True) None¶
is_on_render_layer(index: int) bool¶
wrap_bounds(bounds: tuple[float, float, float] | numpy.ndarray, margin: float = 1.0)¶
strict_errors: ClassVar[bool]¶

True

script_error_raised¶

‘Signal(…)’

classmethod __init_subclass__(**kwargs)¶
property name: str¶
property process_mode: simvx.core.descriptors.ProcessMode¶
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¶
find_child(name: str, recursive: bool = False) simvx.core.node.Node | None¶
find(node_type: type, recursive: bool = True) simvx.core.node.Node | None¶
find_all(node_type: type, recursive: bool = True) list¶
property path: str¶
add_to_group(group: str)¶
remove_from_group(group: str)¶
is_in_group(group: str) bool¶
ready() None¶
enter_tree() None¶
exit_tree() None¶
process(dt: float) None¶
physics_process(dt: float) None¶
draw(renderer) None¶
input_event(event: simvx.core.events.InputEvent) None¶
input(event: simvx.core.events.TreeInputEvent) None¶
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()¶
property app¶
property tree: simvx.core.scene_tree.SceneTree¶
get_tree() simvx.core.scene_tree.SceneTree¶
__getitem__(key: str)¶
classmethod get_properties() dict[str, simvx.core.descriptors.Property]¶
__repr__()¶
class simvx.core.physics_nodes.Area3D(**kwargs)[source]¶

Bases: simvx.core.physics_nodes._AreaBase, simvx.core.nodes_3d.node3d.Node3D

3D trigger zone that detects overlapping bodies and areas.

Add CollisionShape3D children to define the detection region. Emits body_entered/body_exited when CharacterBody3D nodes overlap, and area_entered/area_exited for other Area3D nodes.

Initialization

collision_layer¶

‘Property(…)’

collision_mask¶

‘Property(…)’

monitoring¶

‘Property(…)’

gizmo_colour¶

‘Property(…)’

get_gizmo_lines() list[tuple[simvx.core.math.types.Vec3, simvx.core.math.types.Vec3]][source]¶

Return gizmo lines from child collision shapes, or a small axis cross if none.

physics_process(dt: float)[source]¶
get_overlapping_bodies() list¶
get_overlapping_areas() list¶
has_overlapping_bodies() bool¶
has_overlapping_areas() bool¶
render_layer¶

‘Property(…)’

property position¶
property rotation: simvx.core.math.types.Quat¶
property scale¶
property rotation_degrees: simvx.core.math.types.Vec3¶
property world_position: simvx.core.math.types.Vec3¶
property world_rotation: simvx.core.math.types.Quat¶
property world_scale: simvx.core.math.types.Vec3¶
property forward: simvx.core.math.types.Vec3¶
property right: simvx.core.math.types.Vec3¶
property up: simvx.core.math.types.Vec3¶
translate(offset: tuple[float, float, float] | numpy.ndarray)¶
translate_global(offset: tuple[float, float, float] | numpy.ndarray)¶
rotate(axis: tuple[float, float, float] | numpy.ndarray, angle: float)¶
rotate_x(angle: float)¶
rotate_y(angle: float)¶
rotate_z(angle: float)¶
look_at(target: tuple[float, float, float] | numpy.ndarray, up=None)¶
set_render_layer(index: int, enabled: bool = True) None¶
is_on_render_layer(index: int) bool¶
wrap_bounds(bounds: tuple[float, float, float] | numpy.ndarray, margin: float = 1.0)¶
strict_errors: ClassVar[bool]¶

True

script_error_raised¶

‘Signal(…)’

classmethod __init_subclass__(**kwargs)¶
property name: str¶
property process_mode: simvx.core.descriptors.ProcessMode¶
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¶
find_child(name: str, recursive: bool = False) simvx.core.node.Node | None¶
find(node_type: type, recursive: bool = True) simvx.core.node.Node | None¶
find_all(node_type: type, recursive: bool = True) list¶
property path: str¶
add_to_group(group: str)¶
remove_from_group(group: str)¶
is_in_group(group: str) bool¶
ready() None¶
enter_tree() None¶
exit_tree() None¶
process(dt: float) None¶
draw(renderer) None¶
input_event(event: simvx.core.events.InputEvent) None¶
input(event: simvx.core.events.TreeInputEvent) None¶
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()¶
property app¶
property tree: simvx.core.scene_tree.SceneTree¶
get_tree() simvx.core.scene_tree.SceneTree¶
__getitem__(key: str)¶
classmethod get_properties() dict[str, simvx.core.descriptors.Property]¶
__repr__()¶