port/godot
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6f47700820 |
M7.4a: PlayScreen polish — facing tick, road overlap, WASD pan
Facing tick stuck at the initial angle. PlayerMarker._Draw was computing the tick direction from a FacingAngleRad auto-property, but Godot caches CanvasItem draw commands and only re-runs _Draw on QueueRedraw. Setter never called QueueRedraw → tick never rotated. Fixed by leaning on the Node2D transform instead: tick is drawn along the local +X axis, PlayScreen sets marker.Rotation = facing each frame. The transform rotation applies to the cached commands without re-invoking _Draw — efficient and correct. FacingAngleRad property removed; ShowFacingTick became a property with QueueRedraw on change (visibility toggle still needs to invalidate the cache). Tactical view double-drew roads. TacticalChunkGen.Pass2_Polylines already bakes roads + rivers + bridges into the surface tiles of each chunk. WorldRenderNode's Line2D overlay was still visible at tactical zoom, stroking the same path on top of the rasterised version — showed as a brown line over every road. Ported the MonoGame "suppress polyline overlay in tactical" rule into UpdateLayerVisibility: _polylineLayer and _bridgeLayer hide when zoom >= TacticalRenderZoomMin. WASD now pans the world map. Previously WASD did nothing in world-map mode — only right-drag / middle-drag / mouse-wheel worked. WASD is now context-sensitive: tactical mode steps the player (unchanged), world-map mode pans the camera at 400 screen px/sec (world-pixel speed scales as 1/zoom so the perceived rate stays constant). Diagonal motion is √2-normalised to match tactical step. Suppressed during click-to-travel since the camera-follow would clobber any pan input anyway. HUD hint updated. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
a23cf8bd97 |
M3: Asset pipeline — ContentPaths + ContentLoader + asset-test
Formalises Content/ access from the Godot host. Content lives at the repo root (sibling of Theriapolis.Godot/), not duplicated under res://, so the MonoGame branch and headless Tools keep reading from the same single source of truth. ContentPaths.cs: Static ContentRoot/DataDir/GfxDir resolved once via res:// walk-up and cached. Replaces two inline ResolveDataDir copies in SmokeTest and WorldMapView. ContentLoader.cs: LoadGfx(relativePath) -> ImageTexture, cached by relative path. Bypasses the res:// import pipeline because Content/ lives outside the project — fine for static pixel-art assets at native size, and the project default texture filter is already Nearest. Cache is per-process, never evicted (full atlas <1 MB). AssetTest.cs + Main.cs --asset-test flag: Smoke-tests the pipeline. Walks Content/Data and Content/Gfx, reports counts, attempts to load every PNG, prints per-subdir breakdown. Quits with non-zero on any failure. Verified post-refactor (--asset-test): 53 JSON files in Data, 50 PNG files in Gfx (8 tactical/deco + 42 tactical/surface), 50/50 loaded, 0 failures. Verified no regressions: --smoke-test (M1) still produces canonical FNV hashes. --world-map 12345 (M2) still produces 3 rivers / 91 roads / 226 settlements / 0 rails / 0 bridges. Scope note: plan mentioned "tile/NPC/CodexUI atlases — three separate themes". Only tactical/ exists in Content/Gfx today; NPC and CodexUI atlases never landed during MonoGame development. M3 ships what's actually present. ContentLoader.LoadGfx works for any future sub-directories without changes. Closes M3 of theriapolis-rpg-implementation-plan-godot-port.md. Next: M4 (tactical render). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
59784048cd |
M2: World map render in Godot
Renders the full worldgen output as a Godot scene at visual parity with
worldgen-dump's PNG output: biome tiles, rivers/roads/rails as Line2D
polylines, settlements as filled circles. Pan + zoom via Camera2D.
WorldMapView.cs:
- Loads Content/Data via res:// walk-up, runs WorldGenerator.RunAll
- Tile palette built from BiomeDef.ParsedColor() — same source as the
PNG dump, so colours are identical
- Tiles rendered as a 256x256 Image scaled by WORLD_TILE_PIXELS to
cover world-pixel space (matches polyline coord system)
- Polyline draw order mirrors LineFeatureRenderer.cs: roads (smaller
first) -> rivers -> rail tie underlay -> rail line. Bridges as
short Line2Ds; settlements as SettlementDot (Node2D + _Draw circle)
- Line widths in world-pixel space, tuned for visibility at world-map
zoom; M4 will add zoom-aware width scaling for tactical view
- Camera fits the whole world (95% of viewport) on first frame
PanZoomCamera.cs:
- Mouse-wheel zoom centered on cursor (cursor world-point stays fixed)
- Middle/right click + drag to pan
- MinZoom/MaxZoom configurable per-instance
Main.cs:
- --world-map [seed] flag launches the view (default seed 12345)
- Arg parser now reads both GetCmdlineArgs and GetCmdlineUserArgs so
callers don't need to remember the "--" separator
- --smoke-test path and M0 hello-world fallback unchanged
Visual diff against world_seed12345.png (generated by
worldgen-dump --seed 12345) confirmed manually: same biome palette, same
rivers/roads topology, same settlement placement and tier colours.
3 rivers, 91 roads, 226 settlements (138 PoIs), 0 rails (ENABLE_RAIL=false),
0 bridges (this seed has no road/river crossings). All match the PNG.
Settlement dot sizes iterated twice from user feedback — final values
in tile units, scaled to world-pixel space, so they shrink at world-map
zoom and grow toward tactical zoom (the right "scale with the map"
behaviour).
Closes M2 of theriapolis-rpg-implementation-plan-godot-port.md.
Next: M3 (asset pipeline).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|