Commit Graph

2 Commits

Author SHA1 Message Date
Christopher Wiebe bf0041605f M7.1-7.2: Play-loop hand-off — Wizard → WorldGen → PlayScreen
Lands the M7 plan's first two sub-milestones on port/godot.
theriapolis-rpg-implementation-plan-godot-port-m7.md is the design
doc (six screens collapse to four scenes + a camera mode, with
per-screen behavioural contracts and a six-step sub-milestone
breakdown).

M7.1 — WorldGenProgressScreen + GameSession autoload + wizard
hand-off rewrite. GameSession holds the cross-scene state that
outlives any single screen: seed, post-worldgen Ctx, pending
character (from the M6 wizard) and pending save snapshot (for
M7.3's load path). Wizard forwards StepReview.CharacterConfirmed
upward, and TitleScreen swaps to the progress screen instead of
just printing the build summary. The progress screen runs the
23-stage pipeline on a background thread, drives a ProgressBar
from ctx.ProgressCallback, and writes the full exception trace to
user://worldgen_error.log on failure. Escape cancels at the next
stage boundary and returns to title.

M7.2 — PlayScreen with a walking character. Extracted
WorldRenderNode from the M2+M4 WorldView demo so PlayScreen and
WorldView mount the same renderer (biome image + polylines +
bridges + settlement dots + tactical chunk lifecycle + PanZoomCamera
+ per-frame layer visibility + line-width counter-scaling).
PlayScreen owns the streamer (M7.3 save needs it), composes
ContentResolver + ActorManager + WorldClock + AnchorRegistry +
PlayerController, spawns the player at the Tier-1 anchor, and
wires resident + non-resident NPC spawning from chunk-load events
with allegiance-tinted markers.

PlayerController ported engine-agnostic to Theriapolis.Godot/Input/.
Takes pre-resolved dx/dy/dt/isTactical/isFocused instead of poking
MonoGame InputManager + Camera2D, so the arithmetic that advances
PlayerActor.Position and WorldClock.InGameSeconds is bit-identical
to the MonoGame version — saves round-trip cleanly.

Click-to-travel in world-map mode (camera zoom <
TacticalRenderZoomMin), WASD step in tactical mode with axis-
separated motion + encumbrance + sub-second clock carry. HUD
overlay top-left shows HP/AC/seed/tile/biome/view-mode/time. Esc
returns to title (M7.4 replaces this with a pause menu).

Namespace gotcha: Theriapolis.GodotHost.Input shadows the engine's
Godot.Input static class for any file under the GodotHost
namespace tree. Files needing keyboard polls (WorldView,
PlayScreen) fully qualify as Godot.Input.IsKeyPressed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 18:07:28 -07:00
Christopher Wiebe 42d66c00c3 M4: Tactical render + unified seamless-zoom WorldView
Implements the seamless-zoom contract from CLAUDE.md: one Camera2D
covers both world-map and tactical scales; layers fade in/out at zoom
thresholds; polyline widths and the player marker counter-scale with
zoom so on-screen sizing stays consistent across the full range.

Layers (bottom-up in WorldView):
  Biome sprite     — 256x256 ImageTexture scaled by WORLD_TILE_PIXELS;
                     always visible (acts as backdrop past the tactical
                     streaming radius).
  TacticalChunks   — TacticalChunkNode children added on chunk-loaded
                     event; visible only when zoom ≥ 4.
  Polylines/Bridge — Line2D children; always visible. Width recomputed
                     each frame as baseScreenPx / camera.Zoom so the
                     on-screen stroke is constant (4 px highway, 3 px
                     post road, 2 px dirt road, 4.5/3/2 for major-river/
                     river/stream, 4/2 for rail tie/line, 6 for bridge).
  Settlements      — SettlementDot children; hidden when zoom ≥ 2 (you
                     are visually "inside" them at tactical scale).
  PlayerMarker     — Always visible; Scale = 1/zoom keeps it at
                     PLAYER_MARKER_SCREEN_PX on-screen across all zooms.

TacticalAtlas:
  Loads PNGs from Content/Gfx/tactical/{surface,deco}/ via ContentLoader
  with name_0.png/name_1.png/... variant probing (silent miss). Falls
  back to procedurally-generated solid placeholders matching MonoGame's
  TacticalAtlas colour table so missing art doesn't break rendering.

TacticalChunkNode:
  One Node2D per cached chunk, positioned at (OriginX, OriginY) in
  world-pixel space. _Draw iterates the 64x64 tile grid once and Godot
  caches the rasterised CanvasItem; subsequent frames blit instead of
  re-issuing 4096 DrawTextureRect calls.

ChunkStreamer integration:
  WorldView listens to OnChunkLoaded / OnChunkEvicting and adds /
  removes TacticalChunkNode children. Streaming radius is computed
  dynamically from the viewport size and camera zoom plus a 2-tile
  buffer, so chunk loads always cover the visible viewport with margin.
  Chunks only stream when zoom ≥ 4 (tactical is visible).

Main.cs:
  --world-map [seed]            → WorldView, fit-to-viewport zoom
  --tactical  [seed] [tx] [ty]  → WorldView, zoom 32 at given tile
  Both flags converge on the same scene; mouse wheel transitions
  seamlessly between modes.

ContentLoader silent miss:
  Removed the "Missing texture" PrintErr — atlas variant probing
  legitimately tries name_3.png that doesn't exist, and the noise
  drowned the console. Genuine asset failures still surface via
  AssetTest's count summary.

Deleted (replaced by WorldView):
  Theriapolis.Godot/Rendering/WorldMapView.cs
  Theriapolis.Godot/Rendering/TacticalView.cs (created earlier in M4,
  never committed — superseded before commit).

Closes M4 of theriapolis-rpg-implementation-plan-godot-port.md.
Next: M5 (codex design system).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-01 20:08:14 -07:00