How to start() after stop()?

113 views
Skip to first unread message

Thomer Gil

unread,
Apr 23, 2020, 7:02:02 PM4/23/20
to excaliburjs


If I want to make 'p' (un)pause a game, how do I unpause after calling game.stop()? I'm (obviously) no longer receiving events to call game.start().

Erik Onarheim

unread,
Apr 23, 2020, 11:39:43 PM4/23/20
to Thomer Gil, excaliburjs
Hi Thomer,

Currently this has to be handled outside of the game as you say, we've been directing people to use HTML dialogues/buttons and similar techniques to gather user input to call game.start()

There is definitely opportunity for improvement, perhaps a more robust pause/unpause feature is warranted? Let us know what you think would be best for your use case.

Cheers,
Erik

On Thu, Apr 23, 2020 at 6:02 PM Thomer Gil <thome...@gmail.com> wrote:


If I want to make 'p' (un)pause a game, how do I unpause after calling game.stop()? I'm (obviously) no longer receiving events to call game.start().

--
You received this message because you are subscribed to the Google Groups "excaliburjs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to excaliburjs...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/excaliburjs/92c5f9ef-7d1b-4485-82bb-2a03004b99a6%40googlegroups.com.

Thomer Gil

unread,
Apr 24, 2020, 5:59:40 AM4/24/20
to excaliburjs
Erik, thank you. An external button is possibly inconvenient because it suggests the focus is outside of the canvas when the game gets unpaused, meaning that you're likely going to "miss" out a little bit on whatever action is resuming. (I guess one could build in a short delay before actually unpausing the game...?)

I've only had experience with Excalibur for a few days, so I don't imagine I'm familiar enough with the paradigm to suggest a good way of handling this. But I think the one and only things you'd ever want ever do when calling game.stop() is either quit entirely, or a way back to game.start()? Maybe allow an optional unpause event handler when invoking stop() and a way to invoke that event? Looking at Excalibur code, however, the actual event loop seems to stop, so I imagine it'll likely be tricky to get that working.

I suspect I now have to implement my own version of pause, where I set all velocities to 0 and disable key handlers except the unpause button. It's a hack, but it'll likely achieve what I want.

Thank you for your quick response and for thinking about this.


On Friday, April 24, 2020 at 5:39:43 AM UTC+2, Erik Onarheim wrote:
Hi Thomer,

Currently this has to be handled outside of the game as you say, we've been directing people to use HTML dialogues/buttons and similar techniques to gather user input to call game.start()

There is definitely opportunity for improvement, perhaps a more robust pause/unpause feature is warranted? Let us know what you think would be best for your use case.

Cheers,
Erik

On Thu, Apr 23, 2020 at 6:02 PM Thomer Gil <thom...@gmail.com> wrote:


If I want to make 'p' (un)pause a game, how do I unpause after calling game.stop()? I'm (obviously) no longer receiving events to call game.start().

--
You received this message because you are subscribed to the Google Groups "excaliburjs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to excal...@googlegroups.com.

DaVince

unread,
Apr 24, 2020, 10:20:45 AM4/24/20
to excaliburjs
Could you explain what your aim is? If you're trying to implement some sort of game pause mechanic, you don't need to use stop() and start(). You could instead switch to a different scene that implements a "game paused" screen. You can then add logic in this new scene to switch back to your in-game scene, which should simply continue where it left off.

- DaVince

Op vrijdag 24 april 2020 11:59:40 UTC+2 schreef Thomer Gil:

Thomer Gil

unread,
Apr 24, 2020, 12:37:43 PM4/24/20
to excaliburjs
Hi DaVince,

That's an excellent idea. My hope, however, was to freeze the game and still be able to see where you've left off. I guess the alternate scene you suggest could "rebuild" the state of the frozen game. But at that point, I could also implement my silly idea by setting all velocities to 0 and disable keys. Or maybe I misunderstood what you meant?

Thank you.

DaVince

unread,
Apr 24, 2020, 3:19:09 PM4/24/20
to excaliburjs
You understood me perfectly. :)

You can take a screen grab of the scene right before switching it out by using Engine.screenshot(). It creates an HTMLImageElement which you can store directly into a Texture, then assign it to an actor or screen element in the pause scene.

Alternatively, with the solution you've suggested, instead of setting all velocities etc. to zero, you can also disable the physics globally. Just set Physics.enabled = false. That will preserve the state of the velocities, if I'm not mistaken, because it effectively just stops updating the physics updates. As a bonus, you could keep having the world animate by doing this. But even then, you're going to have to make sure to disable all of your custom logic in the actors' update methods as well.

A third possible solution could be to overload your scene's update() method, make it run super.update() in the normal case and your own custom logic in the paused case. But that one only really makes sense if you're using a custom Scene class. I also have no clue if it breaks anything, though it shouldn't.

Mind that I haven't actually tested any of these yet. But there are plenty of methods to try. :)


Op vrijdag 24 april 2020 18:37:43 UTC+2 schreef Thomer Gil:

Thomer Gil

unread,
Apr 24, 2020, 4:12:27 PM4/24/20
to excaliburjs
Fantastic. Thank you, DaVince. I'll try (some of) these and report back. Thank you for taking the time to walk me through this.

DaVince

unread,
Apr 25, 2020, 3:42:59 AM4/25/20
to excaliburjs
Well, this inspired me to implement a pause menu next as well.

I experimented with the Engine.screenshot() method today, which seemed the most sensible option to me, but... it's not reliable and a little flimsy.

It takes a screenshot of the canvas at its current size, so if you scale the canvas, you're not going to get a screengrab back that will fit into the screen if you try to display it. I think having a high DPI screen might also affect this.

Furthermore, to use Texture, you first have to create a texture by loading in some other image that has the size of your game. You can't directly generate a texture from any HTMLImageElement. Processing the image and displaying it takes long enough for the game to display nothing for a split second, too, though that could be covered up with a fade transition effect of some sort.

I'm going to attempt the third method I mentioned next, though I'd really have liked to keep the pause menu code separated into its own scene.

Op vrijdag 24 april 2020 22:12:27 UTC+2 schreef Thomer Gil:

DaVince

unread,
Apr 25, 2020, 7:57:02 AM4/25/20
to excaliburjs
Found a better solution.

You can give the Pause scene a property where you store what the previously displayed scene was. Then you can directly call that scene's draw() method in the Pause scene's onPreDraw method. It works perfectly.

Op zaterdag 25 april 2020 09:42:59 UTC+2 schreef DaVince:

DaVince

unread,
Apr 25, 2020, 8:06:53 AM4/25/20
to excaliburjs
Some pseudo-code:


export class GameScene extends Scene {
  // ...

  public update(engine: Game, delta: number) {
    super.update(engine, delta);
    if (game.keyboard.wasPressed(Input.Keys.P)) {
      this.engine.pauseScreen.bgSceneToRender = this;
      this.engine.goToScene('pause');
    }
}

export class PauseScreen extends Scene {
  public bgSceneToRender: Scene;

  // ...
  
  public onPreDraw() {
    this.bgSceneToRender.draw(this.engine.ctx, 0);
  }
}


Op zaterdag 25 april 2020 13:57:02 UTC+2 schreef DaVince:

Thomer Gil

unread,
Apr 25, 2020, 9:01:01 AM4/25/20
to excaliburjs
Hi DaVince,


Excellent, that worked. For the benefit of future generations, here's a slightly extended version. Please let me know if you think I got (parts of) it wrong.

class Game extends ex.Engine {
    // ...
    public gameScene: GameScene;
    public pauseScene: PauseScene;

    constructor(...) {
        // ...
        this.gameScene = new GameScene(this);
        this.pauseScene = new PauseScene(this);
        this.add('play', this.gameScene);
        this.add('pause', this.pauseScene);
        this.goToScene('play');
    }
}

class GameScene extends ex.Scene {
    constructor(engine: ex.Engine) {
        super(engine);

    }

    public update(engine: Game, delta: number) {
        super.update(engine, delta);
        if (engine.input.keyboard.wasPressed(ex.Input.Keys.P)) {
            engine.pauseScene.bgSceneToRender = this;
            engine.goToScene('pause');
        }
    }
}

class PauseScene extends ex.Scene {
    public bgSceneToRender: ex.Scene;
    private engine: ex.Engine;

    constructor(engine: ex.Engine) {
        super(engine);
        this.engine = engine;

    }

    public update(engine: Game, delta: number) {
        super.update(engine, delta);
        if (engine.input.keyboard.wasPressed(ex.Input.Keys.P)) {
            engine.goToScene('play');
        }
    }

    public onPreDraw() {
        this.bgSceneToRender.draw(this.engine.ctx, 0);
    }
}


Thomer Gil

unread,
Apr 25, 2020, 11:10:03 AM4/25/20
to excaliburjs
I know that on the scale of human accomplishments, it isn't a big deal, but here's the first game I ever made: https://thomer.com/games/brickbreaker-js/

The 'p' key provides the pause/unpause functionality that you helped me with.

Thanks for the help so far!


On Saturday, April 25, 2020 at 2:06:53 PM UTC+2, DaVince wrote:

Erik Onarheim

unread,
Apr 25, 2020, 11:17:32 AM4/25/20
to Thomer Gil, excaliburjs
This is fantastic Thomer! 

I'll add this to our documentation/perhaps make this a first class feature in excalibur?

To unsubscribe from this group and stop receiving emails from it, send an email to excaliburjs...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/excaliburjs/fec25070-e4a3-4d7e-b83e-9182fe5f456e%40googlegroups.com.
Message has been deleted

DaVince

unread,
Apr 26, 2020, 4:50:49 AM4/26/20
to excaliburjs
This is nice! I like all the configurable settings you've added.

Op zaterdag 25 april 2020 17:10:03 UTC+2 schreef Thomer Gil:
Reply all
Reply to author
Forward
0 new messages