Jump to content

How to correctly show load progress in Facebook instant games?


pingu
 Share

Recommended Posts

This is particularly related to fitting FB APIs into Phaser's lifecycle.

The way I start a Facebook game is like this:

  var config = {
     // Phaser config stuff
  };
   FBInstant.initializeAsync().then(function() {
        var windowWidth = window.innerWidth;
        var windowHeight = window.innerHeight;
        config.width = windowWidth;
        config.height = windowHeight;
        game = new Phaser.Game(config); // control will now go to preload method
    });

  function preload() {
        // load assets and at each step:
        // FBInstant.setLoadingProgress(i / n * 100);

        // when all assets are loaded
        FBInstant.setLoadingProgress(100);
        FBInstant.startGameAsync().then(function() {
              // nothing to do here. Phaser lifecycle would have already started
        });

  }

The starts fine, but I see that the progress doesn't quite update like it should. It stays at 0 for some time and the game suddenly starts.

I am unsure if I am doing it right. Should we instantiate Phaser.Game after FBInstant's `startGameAsync` resolves? If so, how then would we be able to load assets and set the progress correctly without Phaser having loaded all the assets?

Thank you

Link to comment
Share on other sites

You have to send loading progress to FB from your game - create & use loadUpdate(). Do not set it to 100 in preload(). In preload() you only prepare list of assets for loading - it is not actual loading.  Actual loading is started by Phaser when preload() exits.

        loadUpdate() {
            if (App.Global.FBINSTANT) {
                console.log("FB setLoadingProgress called " + this.load.progress);
                FBInstant.setLoadingProgress(this.load.progress);
            }
        }

 

Link to comment
Share on other sites

Hi @Tom Atom,

Should we do (create Phaser game after startGameAsync)

    FBInstant.initializeAsync().then(function() {   
        FBInstant.startGameAsync().then(function() {
            game = new Phaser.Game(config);
        })
    })

OR

    FBInstant.initializeAsync().then(function() {   
        game = new Phaser.Game(config);
        FBInstant.startGameAsync().then(function() {
            
        })
    })

Also does "loadUpdate" exist in Phaser 3? I couldn't find any reference of it. It also didn't work for me.

 

Thank you

Link to comment
Share on other sites

@pingu
- for load progress, see this Phaser 3 example: http://labs.phaser.io/edit.html?src=src/loader/loader%20events/load%20progress.js it is now about events,

- regarding FB IG: I am using first this:

// -------------------------------------------------------------------------
window.onload = () => {

     if (App.Global.FBINSTANT) {
        // check if FB Instant is present
        if (FBInstant == null) {
            App.Global.FBINSTANT = false;
            startGame();
            return;
        }

        // FB Instant
        console.log("FB initializeAsync called");

        FBInstant.initializeAsync().then(function () {
            console.log("FB initializeAsync completed");
            startGame();
        }).catch(function (e) {
            // FBInstant failed to initialize - switch off FBINSTANT setting and start standard game
            console.log("FB initializeAsync failed - fallback to standard game. Error: " + e.code + ": " + e.message);
            App.Global.FBINSTANT = false;
            startGame();
        });

    } else {
        // Standard game
        startGame();
    }
};

// -------------------------------------------------------------------------
function startGame(): Phaser.Game {
    let game = new Ninja2.Game();
    App.Global.game = game;

    return game;
}

it initializes FB API and creates Phaser game. Game runs through states until it gets into Preloader. When preloader finishes its job, I do this in preloader update:

        // -------------------------------------------------------------------------
        update() {
            // run only once - once the music is decoded do some tween animation
            if (!this._ready && this.cache.isSoundDecoded("Music")) {
                this._ready = true;

                let fbUtils = FBInstantUtils.FBInstantUtils.instance;
                let self = this;
                if (App.Global.FBINSTANT) {
                    console.log("FB startGameAsync called");

                    FBInstant.startGameAsync().then(function () {
                        console.log("FB startGameAsync completed");
                        fbUtils.onGameStart();
                        fbUtils.getPlayers(function () {

                            // load saved data
                            console.log("FB getDataAsync called");
                            FBInstant.player.getDataAsync(["saveData"]).then(function (data: any) {
                                // stats
                                if (data["saveData"] != null) {
                                    console.log("FB data loaded: " + JSON.stringify(data["saveData"]));
                                    App.Global.saveData = data["saveData"];

                                } else {
                                    console.log("No FB save data");
                                }

                                App.Global.adsSupported = fbUtils.isAPISupported("getRewardedVideoAsync");
                                if (App.Global.adsSupported) {
                                    console.log("Ads supported");
                                } else {
                                    console.log("Ads not supported");
                                }

                                // start game
                                self.setPlayState();
                            });
                            
                        }, self);

                    }).catch(function (e) {
                        console.log("FB startGameAsync failed. Error: " + e.code + ": " + e.message);
                    });
                } else {
                    this.setPlayState();
                }
            }
        }

        // -------------------------------------------------------------------------
        private setPlayState(): void {
            this.game.state.start("Play");
        }

Just remove / skip calls to fbUtils. They are my utils to build DB of profile photos, so it is not necessary to download it every time and to get players in context.

So, in the end of preloader I start FB game (this is needed only once) and then I load saved data from FB and check some features, like whether rewarded video ads are available. After all these check I move to game - this game is small, so there is immediatelly Play state. But for larger game I would move to Menu.

 

Link to comment
Share on other sites

@pingu it is ok in this case, because that part of update is called only once. Why not call it in the end of create()? Because there still may be music/sound decoding process ongoing. During update you are regularly checking if audio is ready and then, before you change state to Manu/Play or whatever "real" game state, you start FB too. So, when real game is entered, everything is ready.

(Of course, there is possibility to do it in create and set some flag. Then in update check if sounds are ready and FB game started too - this will run in parallel instead one after each other as in my case).

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...