Door sprite — swap procedural draw for FG_Fortress arched door
Closed wooden door with stone arch from FG_Fortress (4..5, 19..20) — a 32×32 sprite bottom-anchored on the door tile. The 2-tile-wide sprite extends 8 px into each flanking tile so the stone arch merges into adjacent wall sprites, and the lintel rises one tile above the door tile (Y-sorted, occludes pawns). Ghost state stays at 40% alpha until build completes, matching the Wall/Bed/ Workbench convention. _draw() is now a no-op; the sprite handles everything. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7274ada5d1
commit
ac21443037
1 changed files with 56 additions and 23 deletions
|
|
@ -13,6 +13,13 @@ class_name Door extends Node2D
|
|||
## complete: it registers with World for future open/close logic, does NOT
|
||||
## call set_cell_walkable(false), and transitions from ghost to solid.
|
||||
##
|
||||
## Render: a 32×32 closed-wood-door sprite from FG_Fortress (atlas (4..5, 19..20))
|
||||
## is bottom-anchored on the door tile. The sprite is 2 tiles wide so the stone
|
||||
## arch extends 8 px into each flanking tile — which is correct, since walls
|
||||
## typically sit on those tiles and the arch is supposed to merge into them.
|
||||
## The sprite is 2 tiles tall so the lintel rises one tile above the door tile
|
||||
## (matching Wall's bottom-anchored sprite convention).
|
||||
##
|
||||
## World registration: World.register_build_site / World.unregister_build_site
|
||||
## are called from _ready / _exit_tree. Methods land in the Opus integration pass.
|
||||
|
||||
|
|
@ -21,6 +28,13 @@ const TILE_SIZE_PX: int = 16
|
|||
## Sim ticks to build a door at 1× speed (80 ticks = 4 sim seconds).
|
||||
const BUILD_TICKS: int = 80
|
||||
|
||||
## ElvGames Fortress atlas. Stone-arched closed wooden door — top-left of the
|
||||
## 32×32 region at (4, 19); covers tiles (4..5, 19..20).
|
||||
const _DOOR_TEX: Texture2D = preload("res://art/tiles/FG_Fortress.png")
|
||||
const _DOOR_COORD: Vector2i = Vector2i(4, 19)
|
||||
const _DOOR_W_TILES: int = 2
|
||||
const _DOOR_H_TILES: int = 2
|
||||
|
||||
# ── state ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
@export var tile: Vector2i = Vector2i.ZERO
|
||||
|
|
@ -52,10 +66,43 @@ func setup(p_tile: Vector2i) -> void:
|
|||
tile.x * TILE_SIZE_PX + TILE_SIZE_PX / 2.0,
|
||||
tile.y * TILE_SIZE_PX + TILE_SIZE_PX
|
||||
)
|
||||
y_sort_enabled = true
|
||||
_build_sprite()
|
||||
queue_redraw()
|
||||
Audit.log("door", "door ghost placed at %s" % tile)
|
||||
|
||||
|
||||
## Builds the 32×32 FG_Fortress closed-door Sprite2D child. Bottom-anchored
|
||||
## so it sits flush with the door tile's bottom edge — the lintel rises into
|
||||
## the tile above and the stone arch extends one half-tile into each adjacent
|
||||
## tile. Idempotent: re-running drops the previous sprite first.
|
||||
func _build_sprite() -> void:
|
||||
var prev := get_node_or_null("Sprite")
|
||||
if prev != null:
|
||||
prev.queue_free()
|
||||
var sprite := Sprite2D.new()
|
||||
sprite.name = "Sprite"
|
||||
sprite.texture = _DOOR_TEX
|
||||
sprite.region_enabled = true
|
||||
var pixels_w: int = TILE_SIZE_PX * _DOOR_W_TILES
|
||||
var pixels_h: int = TILE_SIZE_PX * _DOOR_H_TILES
|
||||
sprite.region_rect = Rect2(
|
||||
_DOOR_COORD.x * TILE_SIZE_PX,
|
||||
_DOOR_COORD.y * TILE_SIZE_PX,
|
||||
pixels_w,
|
||||
pixels_h,
|
||||
)
|
||||
sprite.centered = true
|
||||
# Centred at (0, -16): bottom edge of sprite at y=0 (= tile bottom), top at
|
||||
# y=-32. Horizontally centred so the 32-wide sprite extends ±16 px around
|
||||
# the door tile's centre, overlapping the two neighbouring wall tiles.
|
||||
sprite.offset = Vector2(0.0, -float(pixels_h) / 2.0)
|
||||
sprite.z_index = 0
|
||||
# Ghost state — translucent until built. Solidified in _complete().
|
||||
sprite.modulate.a = 1.0 if _completed else 0.4
|
||||
add_child(sprite)
|
||||
|
||||
|
||||
## True while the door still needs construction work.
|
||||
func is_buildable() -> bool:
|
||||
return not _completed
|
||||
|
|
@ -107,29 +154,11 @@ static func from_dict(d: Dictionary) -> Dictionary:
|
|||
# ── render ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
func _draw() -> void:
|
||||
# 3/4-perspective door — fits strictly within the tile (16×16) so it
|
||||
# slots cleanly between adjacent walls. Origin (0,0) is at the tile's
|
||||
# bottom-centre. Tile spans local Y: -16 to 0.
|
||||
var alpha: float = 1.0 if _completed else 0.4
|
||||
|
||||
# Matches Wall's 3/4-band layout so doors and walls share a top horizon.
|
||||
var lintel_color := Color(0.55, 0.40, 0.22, alpha) # stone-warmed top lintel
|
||||
var frame_color := Color(0.32, 0.22, 0.10, alpha)
|
||||
var panel_color := Color(0.52, 0.36, 0.18, alpha)
|
||||
var hinge_color := Color(0.20, 0.18, 0.16, alpha)
|
||||
var outline := Color(0.16, 0.10, 0.04, 0.7 * alpha)
|
||||
|
||||
# Top lintel band (matches wall top-face height of 5 px so it lines up).
|
||||
draw_rect(Rect2(Vector2(-8.0, -16.0), Vector2(16.0, 5.0)), lintel_color)
|
||||
# Door frame — fills the front-face band (matches wall front 11 px).
|
||||
draw_rect(Rect2(Vector2(-8.0, -11.0), Vector2(16.0, 11.0)), frame_color)
|
||||
# Door panel (inset 1 px each side, leaves 2 px frame visible left/right).
|
||||
draw_rect(Rect2(Vector2(-6.0, -10.0), Vector2(12.0, 10.0)), panel_color)
|
||||
# Hinge dot.
|
||||
draw_circle(Vector2(-5.0, -5.0), 1.0, hinge_color)
|
||||
# Top/bottom borders + tile outline.
|
||||
draw_line(Vector2(-8.0, -11.0), Vector2(8.0, -11.0), Color(0.20, 0.14, 0.06, alpha), 1.0)
|
||||
draw_rect(Rect2(Vector2(-8.0, -16.0), Vector2(16.0, 16.0)), outline, false, 1.0)
|
||||
# Door body is rendered by the Sprite2D child (see _build_sprite()).
|
||||
# No procedural overlay needed — the FG_Fortress closed-door sprite already
|
||||
# shows the wood panels, stone arch, and lintel. Ghost alpha is handled
|
||||
# via sprite.modulate.a in _build_sprite / _complete.
|
||||
pass
|
||||
|
||||
|
||||
# ── internal ───────────────────────────────────────────────────────────────────
|
||||
|
|
@ -148,5 +177,9 @@ func _complete() -> void:
|
|||
# Phase 13 — notify RoomDetector so the door tile is eligible as an
|
||||
# interior boundary tile for room BFS.
|
||||
World.mark_door_tile(tile)
|
||||
# Solidify the ghost sprite from 40% to full opacity.
|
||||
var sprite: Sprite2D = get_node_or_null("Sprite")
|
||||
if sprite != null:
|
||||
sprite.modulate.a = 1.0
|
||||
queue_redraw()
|
||||
Audit.log("door", "door completed at %s" % tile)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue