diff --git a/src/game/engine/scenes/tests/standin_world_proof.gd b/src/game/engine/scenes/tests/standin_world_proof.gd new file mode 100644 index 00000000..75796fa0 --- /dev/null +++ b/src/game/engine/scenes/tests/standin_world_proof.gd @@ -0,0 +1,148 @@ +extends Node2D +## Live world-map proof for the OSS stand-in sprites. Models p2-66's +## full_game_demo_proof, but leaves authored sprites ENABLED (no +## MC_USE_PROCEDURAL_SPRITES) and spawns units whose type_id matches the +## stand-in roster, so the real UnitRenderer / CityRenderer draw the stand-in +## PNGs on actual generated terrain. Capital-zoom for sprite legibility. +## Self-capturing under a render target (run via weston, not plain --headless). + +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 CityScript: GDScript = preload("res://engine/src/entities/city.gd") +const HexUtilsScript: GDScript = preload("res://engine/src/map/hex_utils.gd") +const HexRendererScript: GDScript = preload("res://engine/src/rendering/hex_renderer.gd") +const UnitRendererScript: GDScript = preload("res://engine/src/rendering/unit_renderer.gd") +const CityRendererScript: GDScript = preload("res://engine/src/rendering/city_renderer.gd") + +const OUTPUT_DIR: String = "user://screenshots" +const VIEWPORT_SIZE: Vector2i = Vector2i(1920, 1080) + +# Dwarf units placed around player-1's capital (type_id -> matches roster). +const P1_UNITS: Array[String] = ["warrior", "archer", "cavalry", "worker", "runesmith", "spearmen"] +# Wild creatures placed as neutral (owner -1) on nearby tiles. +const WILD_UNITS: Array[String] = ["ancient_hydra", "dire_wolf", "feral_spider", "wild_wyvern"] + +var _captured: bool = false + + +func _ready() -> void: + # Explicitly DO NOT force procedural — we want authored stand-in PNGs. + OS.set_environment("MC_USE_PROCEDURAL_SPRITES", "") + OS.set_environment("FORCE_DISABLE_FOGOFWAR", "true") + DisplayServer.window_set_size(VIEWPORT_SIZE) + get_viewport().size = VIEWPORT_SIZE + RenderingServer.set_default_clear_color(Color(0.05, 0.07, 0.10)) + + DataLoader.load_theme("age-of-dwarves") + DataLoader.load_world("earth") + ThemeAssets.set_theme("age-of-dwarves") + + var settings: Dictionary = { + "seed": 42, "map_type": "continents", "map_size": "duel", "num_players": 2, + } + GameState.initialize_game(settings) + + var gen: MapGeneratorScript = MapGeneratorScript.new() + var game_map: RefCounted = gen.generate(settings) + if game_map == null: + push_error("standin_world: MapGenerator returned null") + get_tree().quit(1) + return + + var primary: Dictionary = GameState.get_primary_layer() + primary["map"] = game_map + + var player: PlayerScript = PlayerScript.new() + player.index = 0 + player.is_human = true + player.player_name = "Dwarf Clan" + player.race_id = "dwarf" + player.gender_preset = "male" + player.color = Color(0.85, 0.65, 0.2) + GameState.players.append(player) + + var start: Vector2i = Vector2i.ZERO + if game_map.start_positions.size() > 0: + start = game_map.start_positions[0] + var ring: Array[Vector2i] = HexUtilsScript.get_neighbors(start) + + # Capital city at start. + var city: CityScript = CityScript.new("city_capital") + city.owner_index = 0 + city.position = start + if "city_name" in city: + city.city_name = "Karak Stand-in" + if "population" in city: + city.population = 18 # high tier -> city_q5 silhouette + player.cities.append(city) + + # Dwarf units on the ring around the capital. + var all_units: Array = [] + for i: int in P1_UNITS.size(): + var pos: Vector2i = ring[i % ring.size()] + var u: UnitScript = UnitScript.new(P1_UNITS[i], 0, pos) + u.id = "p1_%s" % P1_UNITS[i] + all_units.append(u) + + # Wild creatures on a second ring (owner -1 -> generic sprite, grey disc). + for j: int in WILD_UNITS.size(): + var base: Vector2i = ring[j % ring.size()] + var wpos: Vector2i = base + (base - start) # one hex further out + var w: UnitScript = UnitScript.new(WILD_UNITS[j], -1, wpos) + w.id = "wild_%s" % WILD_UNITS[j] + all_units.append(w) + + var hex: Node2D = HexRendererScript.new() + hex.name = "HexRenderer" + add_child(hex) + hex.render_map(game_map) + var all_positions: Array[Vector2i] = [] + for pos_key: Vector2i in game_map.tiles: + all_positions.append(pos_key) + hex.update_fog(all_positions, [] as Array[Vector2i]) + + var units: Node2D = UnitRendererScript.new() + units.name = "UnitRenderer" + add_child(units) + units.call("setup_visibility", -1, game_map) # -1: render all (no fog gate) + units.call("sync_units", all_units) + + var cities: Node2D = CityRendererScript.new() + cities.name = "CityRenderer" + add_child(cities) + cities.call("sync_cities", player.cities) + + # Capital-zoom camera: ~7 hexes wide around the start hex. + var cam: Camera2D = Camera2D.new() + cam.position = HexUtilsScript.axial_to_pixel(start) + var zoom_factor: float = float(VIEWPORT_SIZE.x) / (7.0 * 384.0) + cam.zoom = Vector2(zoom_factor, zoom_factor) + cam.make_current() + add_child(cam) + + for _i: int in range(20): + await get_tree().process_frame + await get_tree().create_timer(1.5).timeout + _capture_and_quit() + + +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("standin_world: viewport image null") + get_tree().quit(1) + return + var abs_path: String = ProjectSettings.globalize_path( + "%s/standin_world_proof.png" % OUTPUT_DIR + ) + var err: Error = image.save_png(abs_path) + if err == OK: + print("SCREENSHOT_PATH:%s" % abs_path) + else: + push_error("standin_world: save failed: %s" % error_string(err)) + get_tree().quit() diff --git a/src/game/engine/scenes/tests/standin_world_proof.tscn b/src/game/engine/scenes/tests/standin_world_proof.tscn new file mode 100644 index 00000000..e1c2e230 --- /dev/null +++ b/src/game/engine/scenes/tests/standin_world_proof.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://c5tand1nw0rld"] + +[ext_resource type="Script" path="res://engine/scenes/tests/standin_world_proof.gd" id="1_standinw"] + +[node name="StandinWorldProof" type="Node2D"] +script = ExtResource("1_standinw")