How to structures my scenes/code? And switching betweeen scenes?

12p4$5@+22

Hi there,

Apologies if a question like this has already been asked, (could not find a suitable answer)

I’m trying to restrusture my single file app.js to a more structured approach, and with the ability to separate all my different screens & functionalities, in this case:

  • Start Screen
  • Lobby Screen
  • Game Screen

After alot of research, I could not really find many examples of how to achieve that so I came up with my own solution: https://github.com/oriongunning/orbiter-colyseus/tree/main/src

StartScene.js

export class StartScene {
    
    public _scene: Scene;
    public _button: Button;

    constructor(engine) {
        this.create(engine);
    }

    public async create(engine) {

        // create scene
        let scene = new Scene(engine);

        // setup events
        this._button.onPointerDownObservable.add(() => { 
            scene.detachControl(); //observables disabled
            this._newState = State.LOBBY;
        });

        this._scene = scene;
    }

}

App.js

    this._engine.runRenderLoop(() => {

            switch (this._state) {

                ///////////////////////////////////////
                case State.START:
                    this.clearScene();
                    scene = new StartScene(this._engine);
                    this._scene = scene._scene;
                    this._state = State.NULL;
                    break;
    
                ///////////////////////////////////////
                case State.LOBBY:
                    this.clearScene();
                    scene = new LobbyScene(this._engine, this._client);
                    this._scene = scene._scene;
                    this._state = State.NULL;
                    break;
    
                default: break;
            }

            // monitor state
            this._state = scene._newState;

            // render when scene is ready
            this._process();

        });
        
    }

    private async _process(): Promise<void> {
        if(this._scene){
            await this._scene.whenReadyAsync();
            this._engine.hideLoadingUI(); //when the scene is ready, hide loading
            this._scene.render();
        }
    }
private clearScene() {
        if(this._scene){
            this._scene.dispose();
            this._scene.detachControl();
            this._engine.displayLoadingUI();
        }
    }

What I’m wondering if am I doing any obvious mistakes? or improvements?

Before I dive deeper, I’d like to know I have a good base,

Cheers,
Orion

1 Like

There is no single solution for scene organization, and each project has their own requirements. I don’t see anything very bad with your scene, through you could stop the render loop while the scene wasn’t ready. If you want to get more examples of organizing scenes, I highly recommend @jelster 's book and accompanying repository :slight_smile: :bookmark: Available now to pre-order - new book on how-to BabylonJS! :bookmark: - Announcements - Babylon.js

2 Likes

Thanks for the shout-out, @carolhmj and welcome to the community @oriongu!

I think you’re off to a good start with the code you posted. Two things I can think of for you to keep in mind or that might help would be these:

  1. don’t invoke create from your scene class constructor. Instead, your scene management logic in app should call that. Internally, the create call can await scene.whenReady

  2. your render loop appears to reset the scene every frame - as was mentioned, that’s an area that can be tightened up

1 Like

What can I say. Now we know why You wrote this book :wink:. Though, from a marketing perspective, you should have pushed for the purchase of a hardcopy :money_mouth_face:. Not as if @carolhmj didn’t offer it to you :grin: Here you’re just giving the answer for free :rofl:
@oriongu Please note the joke only in this post. It’s actually part of BJS culture to help the best we can, fast and for free. Among the things I appreciate (and use :wink:) a lot here. And then, so do I (for whatever the little my advise is worth :wink:)

1 Like

not sure it should be here but if it is a password @oriongu it is probably time to change it :slight_smile:

I would just need the IBAN for this bank account, please :grin: :rofl:

haha, love the vibes/banter here guys :slight_smile:

many thanks for all the advice & links @jelster & @carolhmj

ps: hehe, that password was never used

4 Likes

When in doubt, I copy the way the SpacePirates do it (in the BabylonJS repo).

The way your doing it looks good and similar to mine. I have the main render loop in my index.ts and switching scenes is basically just switching which scene is the current one similar to yours.

I also have d.ts for any global needed game logic, maybe this isn’t smart however…

4 Likes

Hi guys,

I’ve restructured slight the game loop and scene classes following you guys advice, scene is only rendered once now until we change state.

I’m still getting some “No camera defined” until the player is actually initialized, but it looks like it’s working as I want. I guess I must create the camera in the gamescene and then pass the reference to the player class, so that there is always a camera. even during “loading”.

Additionally, if I try to draw the game gui (this._setupGUI()), the whole things crashes, but I think if I solve the above, I should be fine,

On the fun side, i’ve added nameplate to the players, it looks great :slight_smile: . I now have a basic functionning lobby and game movement inplace :slight_smile:

the core architecture is always harder to make than anything else

3 Likes

That’s very true, but it’s very rewarding when things start to take shape! :smiley:

2 Likes