simvx.core.tilemap

TileMap and TileSet for grid-based 2D level design.

Module Contents

Classes

TileData

Per-tile metadata within a TileSet.

TileSet

Collection of tiles from one or more texture atlases.

TileMapLayer

A single layer within a TileMap. Stores tiles in chunks for large maps.

TileMap

Grid-based 2D map with multiple layers. Uses chunk-based storage.

Data

API

simvx.core.tilemap.log

‘getLogger(…)’

simvx.core.tilemap.__all__

[‘TileData’, ‘TileSet’, ‘TileMapLayer’, ‘TileMap’]

class simvx.core.tilemap.TileData[source]

Per-tile metadata within a TileSet.

texture_region: tuple[int, int, int, int]

(0, 0, 0, 0)

collision_shapes: list

‘field(…)’

navigation_polygon: list | None

None

custom_data: dict

‘field(…)’

animation_frames: list[int] | None

None

animation_speed: float

5.0

terrain_type: str = <Multiline-String>
terrain_set: int

0

terrain_bits: int

0

class simvx.core.tilemap.TileSet(tile_size: tuple[int, int] = (16, 16))[source]

Collection of tiles from one or more texture atlases.

Initialization

classmethod from_atlas_array(pixels: numpy.ndarray, width: int, height: int, tile_size: tuple[int, int] = (16, 16)) simvx.core.tilemap.TileSet[source]

Create a TileSet from an RGBA atlas array and auto-generate tiles.

pixels is an RGBA uint8 ndarray of shape (height, width, 4) that the scene adapter uploads to the GPU. Tiles are created in a grid using create_from_grid.

add_tile(tile_data: simvx.core.tilemap.TileData | None = None) int[source]

Add a tile, return its ID.

set_tile(tile_id: int, tile_data: simvx.core.tilemap.TileData) None[source]

Insert or replace a tile at a specific ID.

Used by loaders (e.g. :meth:TileMap.from_tmx) that need to place tiles at predetermined IDs: Tiled’s global tile IDs include a firstgid offset per tileset so the local index doesn’t start at zero, and the TileSet must mirror that addressing.

get_tile(tile_id: int) simvx.core.tilemap.TileData | None[source]
remove_tile(tile_id: int)[source]
property tile_count: int[source]
create_from_grid(atlas_width: int, atlas_height: int) list[int][source]

Auto-create tiles from a grid atlas. Returns list of tile IDs.

add_terrain_set(set_id: int = 0)[source]

Create a terrain set for auto-tiling.

set_terrain_tile(set_id: int, bitmask: int, tile_id: int)[source]

Map a neighbor bitmask to a tile ID for auto-tiling.

get_terrain_tile(set_id: int, bitmask: int) int | None[source]

Look up tile ID for a given neighbor bitmask.

simvx.core.tilemap.CHUNK_SIZE

32

class simvx.core.tilemap.TileMapLayer(name: str = 'Layer 0')[source]

A single layer within a TileMap. Stores tiles in chunks for large maps.

Initialization

set_cell(x: int, y: int, tile_id: int)[source]

Set a tile at grid position (x, y).

get_cell(x: int, y: int) int[source]

Get tile ID at grid position. Returns -1 if empty.

erase_cell(x: int, y: int)[source]
get_used_cells() list[tuple[int, int]][source]

Return all non-empty cell positions.

get_used_rect() tuple[int, int, int, int][source]

Return bounding rect (x, y, w, h) of used cells.

class simvx.core.tilemap.TileMap(name='TileMap', **kwargs)[source]

Bases: simvx.core.nodes_2d.node2d.Node2D

Grid-based 2D map with multiple layers. Uses chunk-based storage.

The default :attr:mode is "orthogonal": tile (col, row) projects to world (col * cell_w, row * cell_h). Switching mode to "isometric" rotates that lattice 45° and halves the row spacing so tiles tile diamond-style (canonical for 2D strategy games like Tanks of Freedom). Conversions in either direction go through :meth:map_to_world / :meth:world_to_map, so call those rather than rolling your own cell arithmetic: projection details belong to the TileMap.

Initialization

tile_set

‘Property(…)’

cell_size

‘Property(…)’

mode

‘Property(…)’

classmethod from_tmx(path, *, project_root: pathlib.Path | None = None, image_loader: collections.abc.Callable[[pathlib.Path], tuple[numpy.ndarray, int, int]] | None = None) simvx.core.tilemap.TileMap[source]

Load a TileMap from a Tiled Map Editor .tmx XML file.

Supports orthogonal + isometric maps, multiple tile layers, CSV / base64 (uncompressed, zlib, gzip) layer encodings, and external .tsx tilesets referenced via the source attribute. Tiled object groups and infinite-map chunks are recognised but skipped with a debug log entry: they’re a port-by-port concern, not a tilemap primitive.

Args: path: .tmx filesystem path (or any spec accepted by :func:resolve_asset_path). project_root: Root for resolving relative paths in path. Image / external-tileset references inside the TMX are resolved relative to the TMX file’s directory, not project_root. image_loader: Optional callable (Path) -> (pixels, width,         height) returning RGBA uint8 pixels for the first tileset image. When omitted, the source path is stored on tile_set._atlas_source for the renderer or a downstream preloader to resolve.

Returns: A fully populated TileMap with cell_size, mode, tile_set, and one layer per <layer> element in the TMX. Tile IDs in the layers are the TMX global tile IDs (firstgid offset preserved), matching the TileSet entries.

warn_on_nested_ysort

‘Property(…)’

add_child(node)[source]

Warn (once) when a direct child carries descendants of its own.

Y-sort only applies to direct children. Nesting a group like _floor or _units with per-cell sprites underneath causes the group to sort as a single unit, NOT per descendant: fine for flat ground, wrong for isometric / elevated scenes. See docs/core/tilemap.md “Y-sort caveats” for the full write-up.

add_layer(name: str = '') int[source]

Add a new layer. Returns its index.

get_layer(index: int) simvx.core.tilemap.TileMapLayer[source]
property layer_count: int[source]
set_cell(layer: int, x: int, y: int, tile_id: int)[source]
get_cell(layer: int, x: int, y: int) int[source]
erase_cell(layer: int, x: int, y: int)[source]
world_to_map(world_pos: tuple[float, float]) tuple[int, int][source]

Convert world position to grid coordinates.

Inverse of :meth:map_to_world; honours the active :attr:mode. The result is the cell that contains world_pos: for the isometric case that’s the diamond whose centre is closest, computed by inverting the standard (col-row) * w/2, (col+row) * h/2 mapping.

map_to_world(map_pos: tuple[int, int]) tuple[float, float][source]

Convert grid coordinates to world position (centre of the cell).

Orthogonal: (col * cell_w + cell_w/2, row * cell_h + cell_h/2). Isometric: rotates the lattice 45° so columns advance +x/+y and rows advance -x/+y: the canonical diamond layout used by Godot’s TileMap in isometric mode and adopted by most 2D isometric strategy ports.

get_neighbor_bitmask(layer: int, x: int, y: int) int[source]

Calculate 4-bit bitmask for auto-tiling.

Bits: up=1, right=2, down=4, left=8. A neighbor bit is set when the adjacent tile shares the same terrain_type as the center tile.

auto_tile(layer: int, x: int, y: int, terrain_set: int = 0)[source]

Update tile at (x, y) based on neighbors using auto-tile rules.

highlight_cells(cells: list[tuple[int, int]], colour: tuple = (0.3, 0.6, 1.0, 0.45)) None[source]

Overlay a translucent fill on each named cell.

Args: cells: List of (x, y) grid coordinates to fill. colour: RGBA tuple in 0.0-1.0 range (alpha defaults to ~0.45 for a readable translucent overlay). 3-tuples are accepted and receive a default alpha of 0.45.

Used by strategy/tactics games to show movement range, attack range, targeting reticles, and similar overlays. Multiple groups may be registered (e.g. blue for “move”, red for “attack”); each call adds a new group. Call :meth:clear_highlights to remove them.

clear_highlights() None[source]

Remove every highlight group registered via :meth:highlight_cells.

property highlight_groups: list[tuple[list[tuple[int, int]], tuple]][source]

Read-only view of the registered highlight groups (for inspection / tests).

on_draw(renderer) None[source]

Layer translucent fills over the rendered tiles for each highlight group.

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)
strict_errors: ClassVar[bool]

True

script_error_raised

‘Signal(…)’

classmethod __init_subclass__(**kwargs)
property name: str
property process_mode: simvx.core.descriptors.ProcessMode
property visible: bool
reset_error() None
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(target: type | str, recursive: bool = True) simvx.core.node.Node | None
find_all(node_type: type, recursive: bool = True) list
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_process(dt: float) None
on_physics_process(dt: float) 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()
property app
property tree: simvx.core.scene_tree.SceneTree
__getitem__(key: str)
classmethod get_properties() dict[str, simvx.core.descriptors.Property]
__repr__()