From 66fb634d585d74a8729bbb5481fcefe1132e9c09 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Fri, 10 Apr 2026 08:13:02 -0700 Subject: [PATCH] =?UTF-8?q?test(scenes):=20=E2=9C=85=20Add=20visual=20proo?= =?UTF-8?q?f=20test=20scene=20for=20worldmap=20rendering=20validation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../tests/iter_7q_worldmap_visual_proof.gd | 121 ++++++++++++++++++ .../tests/iter_7q_worldmap_visual_proof.tscn | 6 + 2 files changed, 127 insertions(+) create mode 100644 src/game/engine/scenes/tests/iter_7q_worldmap_visual_proof.gd create mode 100644 src/game/engine/scenes/tests/iter_7q_worldmap_visual_proof.tscn diff --git a/src/game/engine/scenes/tests/iter_7q_worldmap_visual_proof.gd b/src/game/engine/scenes/tests/iter_7q_worldmap_visual_proof.gd new file mode 100644 index 00000000..2e50e4e7 --- /dev/null +++ b/src/game/engine/scenes/tests/iter_7q_worldmap_visual_proof.gd @@ -0,0 +1,121 @@ +extends Node2D +## Iter 7q — Real world_map visual Phase Gate. +## +## Programmatically runs the full New Game flow: +## 1. Load theme + world +## 2. Initialize game state +## 3. Generate map via MapGenerator +## 4. Create players + spawn starting units +## 5. Instantiate world_map.tscn scene and add it as child +## 6. Wait for rendering, capture screenshot, quit +## +## This proves the entire presentation stack: hex_renderer, unit_renderer, +## city_renderer, fog_renderer, lair_overlay_renderer, HUD, camera — all +## running against real game state from real mapgen. + +const MapGeneratorScript: GDScript = preload("res://engine/src/generation/map_generator.gd") +const PlayerScript: GDScript = preload("res://engine/src/entities/player.gd") +const UnitScript: GDScript = preload("res://engine/src/entities/unit.gd") +const WorldMapScene: PackedScene = preload("res://engine/scenes/world_map/world_map.tscn") + +const OUTPUT_DIR: String = "user://screenshots" + +var _captured: bool = false + + +func _ready() -> void: + DisplayServer.window_set_size(Vector2i(1920, 1080)) + get_viewport().size = Vector2i(1920, 1080) + + _setup_game() + + await get_tree().create_timer(0.5).timeout + + # Instantiate the real world_map scene + var world_map: Node = WorldMapScene.instantiate() + add_child(world_map) + + # Wait for rendering to settle + for _i: int in range(30): + await get_tree().process_frame + + await get_tree().create_timer(2.0).timeout + _capture_and_quit() + + +func _setup_game() -> void: + print("iter_7q: Loading theme...") + DataLoader.load_theme("age-of-dwarves") + DataLoader.load_world("earth") + + var settings: Dictionary = { + "seed": 42, + "map_type": "continents", + "map_size": "duel", + "num_players": 2, + } + GameState.initialize_game(settings) + print("iter_7q: GameState initialized") + + var gen: MapGeneratorScript = MapGeneratorScript.new() + var game_map: RefCounted = gen.generate(settings) + if game_map == null: + push_error("iter_7q: MapGenerator returned null") + return + print("iter_7q: Map %dx%d (%d tiles)" % [ + game_map.width, game_map.height, game_map.tiles.size() + ]) + + var primary: Dictionary = GameState.get_primary_layer() + primary["map"] = game_map + + # Create 2 players + for i: int in range(2): + var player: PlayerScript = PlayerScript.new() + player.index = i + player.is_human = (i == 0) + player.player_name = "Player %d" % (i + 1) + player.race_id = "dwarf" + player.color = Color(0.85, 0.65, 0.2) if i == 0 else Color(0.8, 0.2, 0.2) + GameState.players.append(player) + + # Spawn a founder at start position + var start_pos: Vector2i = Vector2i.ZERO + if i < game_map.start_positions.size(): + start_pos = game_map.start_positions[i] + var unit: UnitScript = UnitScript.new("founder", i, start_pos) + unit.instance_id = "founder_%d" % i + player.units.append(unit) + + print("iter_7q: %d players, %d units" % [ + GameState.players.size(), + GameState.players[0].units.size() + GameState.players[1].units.size() + ]) + + +func _capture_and_quit() -> void: + if _captured: + return + _captured = true + DirAccess.make_dir_recursive_absolute( + ProjectSettings.globalize_path(OUTPUT_DIR) + ) + var image: Image = get_viewport().get_texture().get_image() + if image == null: + push_error("iter_7q: viewport image null") + get_tree().quit(1) + return + var timestamp: String = Time.get_datetime_string_from_system().replace( + ":", "-" + ).replace("T", "_") + var rel_path: String = "%s/%s_%s.png" % [ + OUTPUT_DIR, "iter_7q_worldmap_visual", timestamp + ] + var abs_path: String = ProjectSettings.globalize_path(rel_path) + var err: Error = image.save_png(abs_path) + if err == OK: + print("SCREENSHOT_PATH:%s" % abs_path) + print("iter_7q: %dx%d saved" % [image.get_width(), image.get_height()]) + else: + push_error("iter_7q: save failed: %s" % error_string(err)) + get_tree().quit() diff --git a/src/game/engine/scenes/tests/iter_7q_worldmap_visual_proof.tscn b/src/game/engine/scenes/tests/iter_7q_worldmap_visual_proof.tscn new file mode 100644 index 00000000..60ad04ca --- /dev/null +++ b/src/game/engine/scenes/tests/iter_7q_worldmap_visual_proof.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://engine/scenes/tests/iter_7q_worldmap_visual_proof.gd" id="1"] + +[node name="Iter7qVisualProof" type="Node2D"] +script = ExtResource("1")