class_name WallRenderer extends Node2D ## Renders wall textures by sampling segments from the aux_terrain texture atlas ## and compositing them onto tile edges. Each edge is made of two half-segments. const TILE_SIZE := 100.0 ## Source atlas rects (x, y, w, h) from aux_terrain.BMP ## Each edge has two half-segments that together span the full tile edge. # -- Left edge -- const LEFT_UPPER_RECT := Rect2(0, 103, 20, 50) const LEFT_LOWER_RECT := Rect2(0, 53, 20, 50) # -- Right edge -- const RIGHT_UPPER_RECT := Rect2(186, 103, 20, 50) const RIGHT_LOWER_RECT := Rect2(186, 53, 20, 50) # -- Top edge -- const TOP_LEFT_RECT := Rect2(103, 0, 50, 20) const TOP_RIGHT_RECT := Rect2(53, 0, 50, 20) # -- Bottom edge -- const BOTTOM_LEFT_RECT := Rect2(103, 186, 50, 20) const BOTTOM_RIGHT_RECT := Rect2(53, 186, 50, 20) # -- Inner corners (drawn where two perpendicular wall edges meet) -- const INNER_CORNER_UPPER_LEFT_RECT := Rect2(0, 0, 50, 50) const INNER_CORNER_UPPER_RIGHT_RECT := Rect2(156, 0, 50, 50) const INNER_CORNER_LOWER_LEFT_RECT := Rect2(0, 156, 50, 50) const INNER_CORNER_LOWER_RIGHT_RECT := Rect2(156, 156, 50, 50) ## Wall thickness in game pixels (how far the border extends into the tile) const WALL_THICKNESS := 20.0 ## Inner corner piece size in game pixels (quarter of a tile) const CORNER_SIZE := 50.0 ## Half the tile edge length const HALF_EDGE := TILE_SIZE / 2.0 @export var atlas_texture: Texture2D func draw_walls_for_layout(map_layout: MapLayout) -> void: _clear_walls() if not map_layout or not atlas_texture: return var tile_edges := _collect_tile_edges(map_layout) for tile in tile_edges: var edges: Array = tile_edges[tile] _draw_tile_walls(tile, edges) func _clear_walls() -> void: for child in get_children(): child.queue_free() func _collect_tile_edges(map_layout: MapLayout) -> Dictionary: ## Returns {Vector2i: Array[StringName]} mapping each tile to its wall edge directions. var tile_edges: Dictionary = {} var walls := map_layout.get_walls() for wall in walls: var tile_a: Vector2i = wall[0] var tile_b: Vector2i = wall[1] var diff: Vector2i = tile_b - tile_a # Determine which edge of tile_a faces the wall var edge_a := _direction_to_edge(diff) if edge_a != &"": if not tile_edges.has(tile_a): tile_edges[tile_a] = [] tile_edges[tile_a].append(edge_a) # Determine which edge of tile_b faces the wall (opposite direction) var edge_b := _direction_to_edge(-diff) if edge_b != &"" and map_layout.is_tile_valid(tile_b): if not tile_edges.has(tile_b): tile_edges[tile_b] = [] tile_edges[tile_b].append(edge_b) return tile_edges func _direction_to_edge(dir: Vector2i) -> StringName: match dir: Vector2i.RIGHT: return &"right" Vector2i.LEFT: return &"left" Vector2i.UP: return &"top" Vector2i.DOWN: return &"bottom" return &"" func _draw_tile_walls(tile: Vector2i, edges: Array) -> void: var tile_origin := Vector2(tile) * TILE_SIZE for edge in edges: match edge: &"left": _draw_edge_segments(tile_origin, edge) &"right": _draw_edge_segments(tile_origin, edge) &"top": _draw_edge_segments(tile_origin, edge) &"bottom": _draw_edge_segments(tile_origin, edge) # TODO: Outer corner segments _draw_outer_corners(tile, tile_origin, edges) # TODO: Inner corner segments (for non-rectangular room support) _draw_inner_corners(tile, tile_origin, edges) func _draw_edge_segments(tile_origin: Vector2, edge: StringName) -> void: var seg_a_rect: Rect2 var seg_b_rect: Rect2 var seg_a_offset: Vector2 var seg_b_offset: Vector2 var seg_a_size: Vector2 var seg_b_size: Vector2 match edge: &"left": seg_a_rect = LEFT_UPPER_RECT seg_b_rect = LEFT_LOWER_RECT seg_a_size = Vector2(WALL_THICKNESS, HALF_EDGE) seg_b_size = Vector2(WALL_THICKNESS, HALF_EDGE) seg_a_offset = Vector2(0, 0) seg_b_offset = Vector2(0, HALF_EDGE) &"right": seg_a_rect = RIGHT_UPPER_RECT seg_b_rect = RIGHT_LOWER_RECT seg_a_size = Vector2(WALL_THICKNESS, HALF_EDGE) seg_b_size = Vector2(WALL_THICKNESS, HALF_EDGE) seg_a_offset = Vector2(TILE_SIZE - WALL_THICKNESS, 0) seg_b_offset = Vector2(TILE_SIZE - WALL_THICKNESS, HALF_EDGE) &"top": seg_a_rect = TOP_LEFT_RECT seg_b_rect = TOP_RIGHT_RECT seg_a_size = Vector2(HALF_EDGE, WALL_THICKNESS) seg_b_size = Vector2(HALF_EDGE, WALL_THICKNESS) seg_a_offset = Vector2(0, 0) seg_b_offset = Vector2(HALF_EDGE, 0) &"bottom": seg_a_rect = BOTTOM_LEFT_RECT seg_b_rect = BOTTOM_RIGHT_RECT seg_a_size = Vector2(HALF_EDGE, WALL_THICKNESS) seg_b_size = Vector2(HALF_EDGE, WALL_THICKNESS) seg_a_offset = Vector2(0, TILE_SIZE - WALL_THICKNESS) seg_b_offset = Vector2(HALF_EDGE, TILE_SIZE - WALL_THICKNESS) _create_segment_sprite(tile_origin + seg_a_offset, seg_a_size, seg_a_rect) _create_segment_sprite(tile_origin + seg_b_offset, seg_b_size, seg_b_rect) func _create_segment_sprite(pos: Vector2, target_size: Vector2, source_rect: Rect2) -> void: var atlas := AtlasTexture.new() atlas.atlas = atlas_texture atlas.region = source_rect var sprite := Sprite2D.new() sprite.texture = atlas sprite.centered = false sprite.position = pos sprite.scale = Vector2( target_size.x / source_rect.size.x, target_size.y / source_rect.size.y ) add_child(sprite) func _draw_outer_corners(_tile: Vector2i, _tile_origin: Vector2, _edges: Array) -> void: # TODO: Implement outer corner segments # Check pairs of adjacent edges (e.g., "top" + "left" → top-left outer corner) # and draw the corner piece from the atlas. pass func _draw_inner_corners(_tile: Vector2i, tile_origin: Vector2, edges: Array) -> void: ## Draws decorative corner pieces wherever two perpendicular wall edges meet ## on the same tile (e.g., a top wall + left wall produces an upper-left corner). var has_top := edges.has(&"top") var has_bottom := edges.has(&"bottom") var has_left := edges.has(&"left") var has_right := edges.has(&"right") var corner_size := Vector2(CORNER_SIZE, CORNER_SIZE) if has_top and has_left: _create_segment_sprite( tile_origin + Vector2(0, 0), corner_size, INNER_CORNER_UPPER_LEFT_RECT ) if has_top and has_right: _create_segment_sprite( tile_origin + Vector2(TILE_SIZE - CORNER_SIZE, 0), corner_size, INNER_CORNER_UPPER_RIGHT_RECT ) if has_bottom and has_left: _create_segment_sprite( tile_origin + Vector2(0, TILE_SIZE - CORNER_SIZE), corner_size, INNER_CORNER_LOWER_LEFT_RECT ) if has_bottom and has_right: _create_segment_sprite( tile_origin + Vector2(TILE_SIZE - CORNER_SIZE, TILE_SIZE - CORNER_SIZE), corner_size, INNER_CORNER_LOWER_RIGHT_RECT )