diff --git a/src/game/engine/scenes/world_map/world_map_arena.gd b/src/game/engine/scenes/world_map/world_map_arena.gd index 1a9b683a..3195bae9 100644 --- a/src/game/engine/scenes/world_map/world_map_arena.gd +++ b/src/game/engine/scenes/world_map/world_map_arena.gd @@ -172,7 +172,7 @@ func _on_turn_ended(_turn_number: int, _player_index: int) -> void: var shot_turn: int = EnvConfig.get_int("AI_ARENA_SCREENSHOT_TURN", -1) if shot_turn > 0 and GameState.turn_number == shot_turn and not _screenshot_taken: _screenshot_taken = true - _capture_viewport_screenshot.call_deferred() + _capture_viewport_screenshot_async() if Time.get_ticks_msec() - _start_ticks_msec > WALL_CLOCK_LIMIT_MSEC: var winner_clock: int = _pick_winner_by_score() @@ -184,9 +184,22 @@ func _on_turn_ended(_turn_number: int, _player_index: int) -> void: _finish(winner_score, "score") -func _capture_viewport_screenshot() -> void: +func _capture_viewport_screenshot_async() -> void: + ## Godot on Wayland skips rendering occluded/unfocused windows, so a + ## raw `get_viewport().get_texture().get_image()` here grabs whatever + ## stale frame was last drawn — which for windows stacked behind + ## other arena instances is the loading-screen splash. Wait a few + ## idle frames AND force an explicit draw pass before grabbing, so + ## every window renders at least one real gameplay frame to its + ## texture before we read it back. if _result_dir.is_empty(): return + var tree: SceneTree = _world_map.get_tree() + for _i: int in range(3): + await tree.process_frame + RenderingServer.force_draw() + await tree.process_frame + var viewport: Viewport = _world_map.get_viewport() if viewport == null: return