Door sprite — swap castle gate for 1-tile FG_Village cabin door

The previous 32×32 FG_Fortress arched gate at (4,19) was rejected as 'a
door for a entrance to a castle' — too imposing for a cabin's front door.

Pivot: FG_Village atlas (3, 24) — a single 16×16 olive-wood plank door
with a white U-handle, extracted from the red-roofed cottage template.
Sprite occupies one tile (no overhang, no rising lintel), bottom-anchored
the same as Wall so Y-sort layers pawns correctly.

Verified in MCP play_scene: the door slots cleanly into the demo cabin's
south-wall gap at (47, 28), matching the surrounding stone-brick wall
height. Ghost-alpha pipeline (0.4 in-build → 1.0 on _complete) intact.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-12 16:11:05 +01:00
parent ac21443037
commit 745ab29c51
3 changed files with 66 additions and 27 deletions

BIN
art/tiles/FG_Village.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View file

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cbqcq5n5iy737"
path="res://.godot/imported/FG_Village.png-cc0ade50cce054d39cffc82cfd873349.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://art/tiles/FG_Village.png"
dest_files=["res://.godot/imported/FG_Village.png-cc0ade50cce054d39cffc82cfd873349.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View file

@ -13,12 +13,14 @@ 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).
## Render: a 16×16 olive-wood cabin door sprite from FG_Village (atlas (3, 24))
## is bottom-anchored on the door tile. The sprite occupies exactly one tile —
## same footprint as the surrounding wall, no overhang into neighbours — so
## a 1-tile gap in a wall reads cleanly as "door here".
##
## The previous pick was the 32×32 FG_Fortress stone-arch gate at (4, 19): a
## proper castle entrance, far too imposing for a cabin's front door. Swapped
## 2026-05-12 after the user flagged it as "a door for a entrance to a castle".
##
## World registration: World.register_build_site / World.unregister_build_site
## are called from _ready / _exit_tree. Methods land in the Opus integration pass.
@ -28,12 +30,11 @@ 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
## ElvGames Village atlas. Single-tile olive-wood cabin door with a white
## U-shaped handle at (3, 24) — extracted from the red-roofed cottage template
## on FG_Village. See /tmp/village_just_3_24.png for the standalone preview.
const _DOOR_TEX: Texture2D = preload("res://art/tiles/FG_Village.png")
const _DOOR_COORD: Vector2i = Vector2i(3, 24)
# ── state ──────────────────────────────────────────────────────────────────────
@ -72,10 +73,10 @@ func setup(p_tile: Vector2i) -> void:
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.
## Builds the 16×16 FG_Village cabin-door Sprite2D child. Bottom-anchored so the
## door sits flush with the tile's bottom edge, matching Wall's convention so
## Y-sort layers pawns correctly relative to it. Idempotent: re-running drops
## the previous sprite first.
func _build_sprite() -> void:
var prev := get_node_or_null("Sprite")
if prev != null:
@ -84,19 +85,17 @@ func _build_sprite() -> void:
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,
TILE_SIZE_PX,
TILE_SIZE_PX,
)
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 center at y=-8 so the 16×16 region spans y=-16..0 — flush against
# the bottom edge of the door tile (matches Wall._build_stone_sprite). No
# horizontal overhang into neighbouring tiles.
sprite.offset = Vector2(0.0, -8.0)
sprite.z_index = 0
# Ghost state — translucent until built. Solidified in _complete().
sprite.modulate.a = 1.0 if _completed else 0.4
@ -155,9 +154,9 @@ static func from_dict(d: Dictionary) -> Dictionary:
func _draw() -> void:
# 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.
# No procedural overlay needed — the FG_Village cabin-door sprite already
# shows the wood planks and U-handle. Ghost alpha is handled via
# sprite.modulate.a in _build_sprite / _complete.
pass