Skip to content

Commit 3a16ee1

Browse files
committed
Run a single game frame when the frozen gameplay test game is resized
After a test finishes, the game is left paused, showing the last frame. Resizing the frame then runs one game frame (synchronously, at most once per animation frame), so anchored objects and cameras adapt the displayed frame to the new size. Test results are unaffected: they were already reported when the test finished.
1 parent f7dc064 commit 3a16ee1

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

GDJS/Runtime/gameplay-tests/gameplay-test-runner.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2905,6 +2905,47 @@ namespace gdjs {
29052905
export const isGameplayTestRunning = (): boolean =>
29062906
!!currentlyRunningHarness;
29072907

2908+
/**
2909+
* The game left paused (frozen) by the last finished test, if any.
2910+
* See `installFreezeResizeStepListener`.
2911+
*/
2912+
let frozenRuntimeGame: gdjs.RuntimeGame | null = null;
2913+
let freezeResizeStepListenerInstalled = false;
2914+
2915+
/**
2916+
* When a test finished with `freezeWhenFinished`, the game stays paused,
2917+
* showing the last frame. If the game window is then resized, run a
2918+
* single game frame so that everything adapting to the window size
2919+
* (anchored objects, cameras...) updates the displayed frame. This does
2920+
* not change the results of the test: they were already computed and
2921+
* reported when the test finished.
2922+
*/
2923+
const installFreezeResizeStepListener = () => {
2924+
if (freezeResizeStepListenerInstalled || typeof window === 'undefined') {
2925+
return;
2926+
}
2927+
freezeResizeStepListenerInstalled = true;
2928+
2929+
let stepScheduled = false;
2930+
window.addEventListener('resize', () => {
2931+
if (!frozenRuntimeGame || currentlyRunningHarness || stepScheduled) {
2932+
return;
2933+
}
2934+
// Coalesce to at most one game frame per animation frame, but run
2935+
// the frame synchronously so the adaptation is rendered in the same
2936+
// paint as the resize (no trailing while dragging a window border).
2937+
stepScheduled = true;
2938+
requestAnimationFrame(() => {
2939+
stepScheduled = false;
2940+
});
2941+
// The game renderer's own resize listener ran first (it was
2942+
// registered at game startup): the game resolution is already
2943+
// adapted. Adapt the cameras now, then run a single game frame.
2944+
frozenRuntimeGame.getSceneStack().onGameResolutionResized();
2945+
frozenRuntimeGame.getSceneStack().step(1000 / 60);
2946+
});
2947+
};
2948+
29082949
/**
29092950
* Run a gameplay test script against the game and return its result.
29102951
*
@@ -2930,6 +2971,8 @@ namespace gdjs {
29302971

29312972
const harness = new GameplayTestHarness(runtimeGame, payload);
29322973
currentlyRunningHarness = harness;
2974+
// The game is not frozen anymore: the test owns the game stepping.
2975+
frozenRuntimeGame = null;
29332976
harness._onProgress = onProgress || null;
29342977

29352978
// The source must be the BODY of `async (harness) => { ... }`, but
@@ -3162,6 +3205,9 @@ namespace gdjs {
31623205
} catch (error) {
31633206
// Ignore errors while muting the game.
31643207
}
3208+
// Still adapt the displayed last frame if the window is resized.
3209+
frozenRuntimeGame = runtimeGame;
3210+
installFreezeResizeStepListener();
31653211
} else {
31663212
runtimeGame.pause(wasPaused);
31673213
}

0 commit comments

Comments
 (0)