extends SceneTree ## WEGWERF-Renderprobe (Karte t_1cdc1a72, Lauf-Modus im Map Builder selbst) — ## (a) Spieleraugen-Startansicht am Team-0-Spawnpunkt (Kisten voraus, HUD an) ## (b) Nach 8 m Gehen (60 × step 1/30 s) — Spieler bewegt, bleibt auf Terrain ## (c) Nach ESC: Editor-Panels wieder da, Spiel-Kamera weg, Status meldet ## Ausführen: ## xvfb-run -a godot4 --path . --rendering-driver opengl3 -s res://tests/probe_playtest_render.gd ## Wegwerf-Probe (nicht im Repo-Commit — Datei-Grenzen der Karte), Beweise nach ## /opt/data/scopedvr/work/t1cdc_beweise/. var main: Control var subvp: SubViewport func _initialize() -> void: _run.call_deferred() func _png(name: String) -> String: return "/opt/data/scopedvr/work/t1cdc_beweise/" + name func _shot(name: String) -> void: await process_frame await process_frame var img := subvp.get_texture().get_image() img.save_png(_png(name)) print("PROBE_PNG=%s (%dx%d)" % [_png(name), img.get_width(), img.get_height()]) func _find_subvp(node: Node) -> SubViewport: if node is SubViewport: return node as SubViewport for c in node.get_children(): var f := _find_subvp(c) if f != null: return f return null func _press_key(code: Key) -> InputEventKey: var key := InputEventKey.new() key.keycode = code key.physical_keycode = code key.pressed = true return key func _run() -> void: DirAccess.make_dir_recursive_absolute("/opt/data/scopedvr/work/t1cdc_beweise") var scene: PackedScene = load("res://scenes/main.tscn") main = scene.instantiate() root.add_child(main) await process_frame await process_frame subvp = _find_subvp(main) var container: SubViewportContainer = subvp.get_parent() container.stretch = false subvp.size = Vector2i(1600, 900) await process_frame # Test-Szene: 1024er Map, 3 Kisten vor dem Spieler (Richtung -Z), # Team-0-Spawn am Ursprung — der Spieler spawnt dort mit Blick auf die Kisten. var doc: Dictionary = SvmapDocument.create_new("T1-Probe", 1024.0, "mittag") doc["objects"] = [ {"id": "crate_wood", "pos": [0.0, 0.0, -150.0], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "crate_wood", "pos": [-120.0, 0.0, -280.0], "scale": 1.0, "rot_y_deg": 0.0}, {"id": "crate_wood", "pos": [150.0, 0.0, -320.0], "scale": 1.0, "rot_y_deg": 0.0}, ] doc["spawn_zones"] = {"0": {"points": [{"id": "spawn0", "pos": [0.0, 0.0, 0.0]}]}} main.set("doc", doc) main.call("_refresh_all") await process_frame await process_frame # --- (a) Lauf-Modus starten (F5-Route: _on_test_run) ---------------------- main.call("_on_test_run") await process_frame await process_frame var pt: Node = main.get("playtest") print("ZAHLEN (a) playtest aktiv: ", pt != null, " | mode.active=", pt.get("active")) var body: Node3D = pt.get("body") print("ZAHLEN (a) Spawn: body.position=", body.position, " | Terrainhöhe dort=", body.terrain_height(0.0, 0.0)) print("ZAHLEN (a) yaw=", body.get("yaw_deg"), " pitch=", body.get("pitch_deg"), " Kapsel-Mitte y=", body.position.y, " feet=", body.fuss_hoehe()) var look_cam: Camera3D = body.get("look_cam") var editor_cam: Camera3D = main.get("camera") print("ZAHLEN (a) Spiel-Kamera current=", look_cam.current, " | Editor-Kamera current=", editor_cam.current) print("ZAHLEN (a) Kiste (0,0.6,-150) im Frustum=", look_cam.is_position_in_frustum(Vector3(0.0, 0.6, -150.0)), " | Kiste (−120,0.6,−280) im Frustum=", look_cam.is_position_in_frustum(Vector3(-120.0, 0.6, -280.0))) var hp: Label = pt.get("hud_pos") print("ZAHLEN (a) HUD: hud=", pt.get("hud") != null, " pos-text='", hp.text, "'") print("ZAHLEN (a) Top-Bar sichtbar=", main.get("ui_top_bar").visible, " links=", main.get("ui_left_panel").visible, " rechts=", main.get("ui_right_panel").visible) await _shot("t1_a_spieler_startansicht.png") # --- (b) 1 s Gehen (60 Physik-Frames, Autopilot) — Bewegung + Terrain ---- var pos_vor: Vector3 = body.position body.set("auto_move_dir", Vector3(0, 0, -1)) for i in 60: await physics_frame body.set("auto_move_dir", Vector3.ZERO) var pos_nach: Vector3 = body.position print("ZAHLEN (b) Position vor/nach 60 Physik-Frames: ", pos_vor, " → ", pos_nach, " (Δ=", pos_vor.distance_to(pos_nach), " m)") print("ZAHLEN (b) on_floor=", body.is_on_floor(), " feet=", body.fuss_hoehe(), " Terrainhöhe dort=", body.terrain_height(pos_nach.x, pos_nach.z)) await _shot("t1_b_spieler_gelaufen.png") # --- (c) ESC: zurück in den Editor ----------------------------------------- main._unhandled_key_input(_press_key(KEY_ESCAPE)) await process_frame await process_frame print("ZAHLEN (c) playtest nach ESC null=", main.get("playtest") == null) print("ZAHLEN (c) Top-Bar sichtbar=", main.get("ui_top_bar").visible, " links=", main.get("ui_left_panel").visible, " rechts=", main.get("ui_right_panel").visible, " Statusleiste=", main.get("ui_status_bar").visible) print("ZAHLEN (c) Editor-Kamera current=", editor_cam.current) print("ZAHLEN (c) Status: ", main.status_label.text) await _shot("t1_c_editor_zurueck.png") print("PROBE_FERTIG") quit(0)