simvx.core.light2d

2D lighting nodes — Light2D, PointLight2D, DirectionalLight2D, LightOccluder2D.

Backend-agnostic light description nodes. The Vulkan backend renders these via Light2DPass (additive light accumulation with optional shadow casting).

Module Contents

Classes

Light2D

Base class for 2D lights.

PointLight2D

Radial point light with configurable falloff curve.

DirectionalLight2D

Global directional light that illuminates the entire scene.

LightOccluder2D

Shadow-casting obstacle defined by a convex polygon.

Functions

collect_lights

Walk the subtree and return all enabled Light2D nodes.

collect_occluders

Walk the subtree and return all LightOccluder2D nodes with non-empty polygons.

Data

API

simvx.core.light2d.__all__

[‘Light2D’, ‘PointLight2D’, ‘DirectionalLight2D’, ‘LightOccluder2D’]

class simvx.core.light2d.Light2D(**kwargs)

Bases: simvx.core.engine.Node2D

Base class for 2D lights.

Lights contribute additive (or mixed) color to a light accumulation buffer that modulates the final 2D scene output. Attach as children of any Node2D to have their position follow the parent.

Attributes: color: RGB light color, each component in [0, 1]. energy: Intensity multiplier applied to the light color. range: Radius of the light in pixels. blend_mode: "add" for additive blending, "mix" for alpha-based mix with ambient. enabled: Toggle the light on/off without removing it. shadow_enabled: When True, occluders in the scene cast shadows for this light. shadow_color: RGBA color used to tint shadow regions. texture_scale: Scale multiplier for the light texture/gradient.

Initialization

color

‘Property(…)’

energy

‘Property(…)’

range

‘Property(…)’

blend_mode

‘Property(…)’

enabled

‘Property(…)’

shadow_enabled

‘Property(…)’

shadow_color

‘Property(…)’

texture_scale

‘Property(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

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 global_position: simvx.core.math.types.Vec2
property global_rotation: float
property global_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, color=None)
wrap_screen(margin: float = 20)
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) 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)
destroy()
queue_free

None

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]
get_settings

None

__repr__()
class simvx.core.light2d.PointLight2D(**kwargs)

Bases: simvx.core.light2d.Light2D

Radial point light with configurable falloff curve.

The falloff exponent controls the attenuation shape:

  • 1.0 = linear falloff (default)

  • 2.0 = quadratic (more concentrated center)

  • 0.5 = square-root (softer, wider spread)

Example::

light = PointLight2D(
    color=(1.0, 0.8, 0.3),
    energy=1.5,
    range=300.0,
    falloff=2.0,
    position=Vec2(400, 300),
)

Initialization

falloff

‘Property(…)’

color

‘Property(…)’

energy

‘Property(…)’

range

‘Property(…)’

blend_mode

‘Property(…)’

enabled

‘Property(…)’

shadow_enabled

‘Property(…)’

shadow_color

‘Property(…)’

texture_scale

‘Property(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

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 global_position: simvx.core.math.types.Vec2
property global_rotation: float
property global_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, color=None)
wrap_screen(margin: float = 20)
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) 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)
destroy()
queue_free

None

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]
get_settings

None

__repr__()
class simvx.core.light2d.DirectionalLight2D(**kwargs)

Bases: simvx.core.light2d.Light2D

Global directional light that illuminates the entire scene.

Unlike point lights, directional lights have no position-based attenuation. The direction vector determines the light angle for shadow casting (if enabled). The range setting is ignored for illumination but still used to size the shadow map.

Example::

sun = DirectionalLight2D(
    direction=(0.5, -1.0),
    color=(1.0, 1.0, 0.9),
    energy=0.8,
)

Initialization

direction

‘Property(…)’

color

‘Property(…)’

energy

‘Property(…)’

range

‘Property(…)’

blend_mode

‘Property(…)’

enabled

‘Property(…)’

shadow_enabled

‘Property(…)’

shadow_color

‘Property(…)’

texture_scale

‘Property(…)’

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

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 global_position: simvx.core.math.types.Vec2
property global_rotation: float
property global_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, color=None)
wrap_screen(margin: float = 20)
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) 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)
destroy()
queue_free

None

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]
get_settings

None

__repr__()
class simvx.core.light2d.LightOccluder2D(position=None, rotation: float = 0.0, scale=None, **kwargs)

Bases: simvx.core.engine.Node2D

Shadow-casting obstacle defined by a convex polygon.

The polygon attribute is a sequence of (x, y) tuples defining the occluder shape in local coordinates. The occluder follows its parent’s transform (position, rotation, scale).

When one_way is True, shadows are only cast in the direction of the polygon’s winding normal.

Example::

wall = LightOccluder2D(
    polygon=[(-50, -10), (50, -10), (50, 10), (-50, 10)],
    position=Vec2(400, 400),
)

Initialization

polygon

‘Property(…)’

one_way

‘Property(…)’

get_global_polygon() list[tuple[float, float]]

Return polygon vertices transformed to global coordinates.

Applies the node’s global position, rotation, and scale to each vertex in the polygon.

get_edge_segments() list[tuple[tuple[float, float], tuple[float, float]]]

Return a list of edge segments ((x0, y0), (x1, y1)) in global space.

z_index

‘Property(…)’

z_as_relative

‘Property(…)’

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 global_position: simvx.core.math.types.Vec2
property global_rotation: float
property global_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, color=None)
wrap_screen(margin: float = 20)
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) 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)
destroy()
queue_free

None

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]
get_settings

None

__repr__()
simvx.core.light2d.collect_lights(root: simvx.core.engine.Node2D) list[simvx.core.light2d.Light2D]

Walk the subtree and return all enabled Light2D nodes.

simvx.core.light2d.collect_occluders(root: simvx.core.engine.Node2D) list[simvx.core.light2d.LightOccluder2D]

Walk the subtree and return all LightOccluder2D nodes with non-empty polygons.