How to pause the game correctly while in the game menu?

Hi everyone!

I am rendering the game itself and the main menu in the separate scenes. Like this:

_runRenderLoop() {
    this.engine.runRenderLoop(function () {
        this.currentScene.render();
        this.mainMenu.mainMenuScene.render();
    }.bind(this));
}

I want to pause the game when the user is in the main menu. How to do this?

In my understanding, the pausing includes:

  1. Stop rendering, freeze at the current frame.
  2. Stop physics.
  3. Stop other processes like animations, sounds etc.
  4. Stop keyboard/mouse listening. Here some clarifications needed, I expect that the engine will not put these events into the event queue when paused. I DO NOT want the following situation: pause, press several keys, unpause, engine handles all the keys which were pressed during the pause.

Is there any general way to do so?

I tried it something like this:

_runRenderLoop() {
    this.engine.runRenderLoop(function () {
        if (!this.paused) {
            this.currentScene.render();
        }
        this.mainMenu.mainMenuScene.render();
    }.bind(this));
}

But the screen behind the menu becames white and I don’t know how correct the pausing is.

1 Like

Hello!
Curious, do you have a full playground for this? I’d love to help you out and games are one of my passions.

On a high level summary, when the pause event is triggered, you will want to call off everything currently running (pause sound, stop animations). Next, you can still accept input when the game is “paused” but then filter it out for your pause and unpause functions. Then when you transition back to unpaused you can resume your animation and sounds in another function.

Hi,

It’s barely possible to make a playground for this. Even if I will create a simple menu and the simple scene, it may not contain all the mechanics.

Regarding mechanics. All my own proccesses in the game that depends on time (like fire rate of guns, grenade delays etc.) I attach to the gaming loop directly, using:

this.scene.onBeforeRenderObservable.add(function(e) {doSomething()});

I never use setTimeout or setInterval. All my processes are synchronized with the gaming loop. Internal BABYLON.Animation instances and physics could be also synchronized with the gaming loop (I want to believe). That means, that if I will stop rendering the scene (like I did in my previous post) this should stop all native BABYLON processes and my processes as well and if I will resume rendering the scene then everything will continue from the last point (I want to believe).

Actually it seems to work so far, but I am receiving the white screen instead of the last frame. I hope it might be easily fixed, by setting some parameter or putting the last frame in the some kind of buffer somehow (don’t know how exactly).

I didn’t check sounds yet. It will be really painful to go into every function that uses sounds and place paused flag there. Of course I could create a separate component to handle every sound in one place. But I want to believe that the Babylon already has it inside. And even if the sound is not paused on pausing rendering loop, it might be paused by some method like pauseAllSounds() (I want to believe).

Going inside every onBeforeRenderObservable event handler of mine and pausing it is barely possible either.

Hi again,

So for sound I would recommend storing them all in a common data structure so you can iterate over and pause them in a single function. I am trying to see if I can create a basic demo or pseudo code that can show this.

Please let me know if you have more questions! :slight_smile: Are you still stuck on a white screen when you pause?

No, I don’t know what to do with white screen. Probably before the pause we can dump image buffer into some kind of array and print it again, but this time in the Main Menu related scene. But I am not sure how BABYLON provides such opportunity.

Initially I expected that BABYLON will keep the last frame if I will stop rendering the scene, but it clears it instead.

You can do this by ensuring that when you initialize the engine you setup in the options preserveDrawingBuffers to true.

1 Like

OK. The last frame remains, but there another problem appears.

My mainMenuScene uses a partially transparent background for menu (alpha = 0.5). When the game is not paused and both scenes are rendering, then everything looks good, I can see the main scene through the menu background. But when the game is paused, then the background of main menu becomes not transparent.

Not paused:

Paused:

In this case it is totally different as if you need to render the menu, you still need to render everything behind it every frame for the blending to work.

So either you could use the createScreenshot apis and put the result in a layer or you would need to render the screen in a RenderTargetTexture and use this in a layer.

1 Like