Visual pass 2: tree + rock + stone wall sprite swaps

Replaces three procedural _draw() entities with bundle sprites:

- Tree: was draw_rect trunk + draw_circle canopy. Now Sprite2D using
  FG_Tree_Spring.png (64x80, 4 variants picked deterministically from
  tile coord). Bottom-anchored so trunk base sits at tile bottom, canopy
  rises into the cell above; y_sort_enabled so canopies tuck behind
  pawns south of the trunk. Chop-progress notch overlay retained.
- Rock: was draw_colored_polygon hex. Now Sprite2D reading from the
  existing FG_Grasslands_Spring.png decoration atlas at three eyeballed
  coords (2 gray boulders, 1 brown rock pile). Variant deterministic
  per tile. Mine-progress crack overlay retained.
- Stone wall: was procedural top-band + front-band + mortar lines. Now
  Sprite2D from FG_Fortress.png at (1,1) — clean tan-stone brick fill.
  Bottom-anchored (offset.y=-8) so the 16x16 sprite spans y=-16..0,
  matching the procedural draw box exactly. Ghost state via modulate.a.
  Wood walls still use procedural _draw_wood_wall — no clean 16x16 wood
  tile found in the bundle yet (Pixel Crawler Walls.png is 32x32, would
  need crop+rescale).

Asset additions:
- art/sprites/FG_Tree_Spring.png (Tier 1, Grasslands pack)
- FG_Fortress.png and FG_Grasslands_Spring.png were already in art/tiles
  from earlier passes; this commit just consumes them from new sites.

Headless boots clean, runtime verified: trees look like chunky pixel-art
trees with root flare, rocks read as real boulders, cabin walls show
proper brick texture.

License: all ElvGames Humble bundle — commercial OK with credit.
Credit-string compilation still open.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-12 14:19:06 +01:00
parent 314c7a70b4
commit 2de5130ae0
5 changed files with 145 additions and 51 deletions

View file

@ -31,14 +31,47 @@ var chop_progress: int = 0
# Preloaded scene for spawned wood items.
const ITEM_SCENE: PackedScene = preload("res://scenes/entities/item.tscn")
## ElvGames Grasslands tree pack — 4 variants laid out left-to-right.
## Each variant is 64×80 px; trunk base sits in the bottom ~10 rows. We anchor
## the sprite center 32 px above tile origin so the trunk bottom lands at the
## tile's bottom edge and the canopy rises into the cells above.
const _TREE_TEX: Texture2D = preload("res://art/sprites/FG_Tree_Spring.png")
const _TREE_VARIANT_W: int = 64
const _TREE_VARIANT_H: int = 80
const _TREE_VARIANT_COUNT: int = 4
# ── lifecycle ─────────────────────────────────────────────────────────────────
func _ready() -> void:
position = _tile_to_world(tile)
_build_sprite()
# Y-sort so the canopy draws behind walls/pawns that are visually south of
# the trunk base. Position.y is the trunk-base row.
y_sort_enabled = true
World.register_tree(self)
## Adds a Sprite2D child painted with one of the 4 ElvGames tree variants.
## Variant chosen deterministically from the tile coord so the same tile always
## gets the same tree silhouette across boots and load/save.
func _build_sprite() -> void:
var sprite := Sprite2D.new()
sprite.name = "Sprite"
sprite.texture = _TREE_TEX
sprite.region_enabled = true
var variant: int = (tile.x * 31 + tile.y * 17) % _TREE_VARIANT_COUNT
sprite.region_rect = Rect2(variant * _TREE_VARIANT_W, 0, _TREE_VARIANT_W, _TREE_VARIANT_H)
sprite.centered = true
# Lift the sprite up so its bottom edge sits at the tile's bottom row.
# Sprite center is at offset.y; sprite half-height is _TREE_VARIANT_H/2 = 40.
# We want bottom edge at +8 (tile bottom) → center at 8 - 40 = -32.
sprite.offset = Vector2(0, -32)
# Render behind pawns/items that are at higher z_index; trees live at z=0.
sprite.z_index = 0
add_child(sprite)
func _exit_tree() -> void:
World.unregister_tree(self)
@ -106,18 +139,8 @@ static func from_dict(d: Dictionary) -> Dictionary:
# ── render ────────────────────────────────────────────────────────────────────
func _draw() -> void:
# Brown trunk: small filled rect at centre-bottom (~4 wide × 6 tall).
var trunk_color := Color(0.45, 0.28, 0.12)
draw_rect(Rect2(Vector2(-2.0, 1.0), Vector2(4.0, 6.0)), trunk_color)
# Green canopy: large filled circle centered near the top.
var canopy_color := Color(0.22, 0.60, 0.18)
draw_circle(Vector2(0.0, -3.0), 7.0, canopy_color)
# Canopy outline.
draw_arc(Vector2(0.0, -3.0), 7.0, 0.0, TAU, 24, Color(0.0, 0.0, 0.0, 0.4), 1.0)
# Chop-progress wedge: a dark angled line on the trunk when partially chopped.
# Canopy + trunk now come from the Sprite2D child (see _build_sprite).
# This _draw renders only the chop-progress notch overlaid on the trunk.
if chop_progress > 0:
var ratio := float(chop_progress) / float(CHOP_TICKS)
var notch_depth := ratio * 3.0