Facebook Instant Games progress bars with Cocos Creator
Introduction and getting help
You are welcome to post to the Cocos Creator category on the Cocos forums to talk about any issues you encounter during the development process. This tutorial does not teach how to code.
Please prepare your development environment before starting this tutorial. If you are having trouble with our tutorial, please take a look at the following documentation:
Preparing the development environment:
Let’s get started
After publishing a Facebook Instant Game with Cocos Creator, we found that the progress bar will wait, for some time, from 0, and then fly directly to 100. This user experience is not very good and may affect perceived performance and app store reviews.
FBInstant interface for setting a progress bar
FBInstant.setLoadingProgress
(a percentage) reports the initial loading progress of the game. This a number between 0 and 100 and can return a void. Example:
FBInstant.setLoadingProgress(50); // Assets are 50% loaded
When calling FBIstant.startGameAsync()
, the Facebook SDK will execute FBIstant.setLoadingProgress(100)
to directly set the progress bar to 100%.
Calling SetLoadingProgress()
will only have an effect after FBInstant.initializeAsync()
succeeds.
The process of ccc setting the progress bar by default
Cocos Creator sets the progress bar to use cc.loader.onProgress
by default, which is called by all global resource loads. The returned CompleteCount
and totalCount
are both 1, resulting in incorrect progress settings.
function setLoadingDisplay() {
// Loading splash scene
cc.loader.onProgress = function (completedCount, totalCount, item) {
var progress = 100 * completedCount / totalCount;
FBInstant.setLoadingProgress(progress);
};
}
Taking a look at the loading process, binding onProgresssetLoadingDisplay()
will only be called after loading multiple JavaScript files and running the game. The previous bulk of the waiting time will always display 0%. This time can also be optimized.
Optimization
After fbinstant.6.2.js loads, call FBInstant.initializeAsync
, and then call FBInstant.setLoadingProgress()
at each step above, so that the loading process can be seen.
First, find the published directory, modify the <body>
in index.html, call fbinstant.6.2.js to load and initialize FBInstant.initializeAsync()
, then set the progress calling FBInstant.setLoadingProgress(10);
, then load settings.js and set the progress calling FBInstant.setLoadingProgress(20);
. Finally, call main.js.
<body>
<canvas id="GameCanvas" oncontextmenu="event.preventDefault()" tabindex="0"></canvas>
<!-- Add -->
<script type="text/javascript">
// Load javascript
var loadSingleScript = function (src, callback) {
var s = document.createElement('script');
s.async = false;
s.src = src;
s.charset = 'utf-8';
s.addEventListener('load', function () {
s.parentNode.removeChild(s);
s.removeEventListener('load', arguments.callee, false);
callback();
}, false);
document.body.appendChild(s);
};
function setting_js_load() {
// load settings.js
FBInstant.setLoadingProgress(20);
loadSingleScript("main.js", function () { });
}
function fb_js_load() {
console.log('fb_js_load')
FBInstant.initializeAsync()
.then(function () {
// Set the progress bar after initialization
FBInstant.setLoadingProgress(10);
loadSingleScript("src/settings.js", setting_js_load);
})
}
</script>
<script src="https://connect.facebook.net/en_US/fbinstant.6.2.js" onload="fb_js_load()">
</script>
<!-- Add end-->
<!-- Remove -->
<!-- <script src="https://connect.facebook.net/en_US/fbinstant.6.2.js"></script> <script src="src/settings.js" charset="utf-8"></script> <script src="main.js" charset="utf-8"></script> -->
<!-- Remove end-->
</body>
Last, modify main.js to remove the original initialization and binding onProgress()
. Find the corresponding position and set the progress bar. Example:
(function () {
'use strict';
// Set the progress bar after loading main.js
FBInstant.setLoadingProgress(30);
function boot() {
// Progress bar after cocos2d-js.js is loaded
FBInstant.setLoadingProgress(40);
// omit this code
}
// omit this code
// Remove binding
// function setLoadingDisplay () {
// // Loading splash scene
// cc.loader.onProgress = function (completedCount, totalCount, item) {
// var progress = 100 * completedCount / totalCount;
// FBInstant.setLoadingProgress(progress);
// };
// }
var onStart = function () {
//cc.game.run post the progress bar
FBInstant.setLoadingProgress(50);
// remove the binging
if (cc.sys.isBrowser) {
// removing binding
// setLoadingDisplay();
}
// omit this code
cc.director.preloadScene(launchScene,
function () {
// progress bar after loading
FBInstant.setLoadingProgress(60);
// omit this code
}
);
};
// omit this code
}
if (window.document) {
// omit this code
var engineLoaded = function () {
// Remove the original initialization
// FBInstant.initializeAsync()
// .then(function () {
document.body.removeChild(cocos2d);
cocos2d.removeEventListener('load', engineLoaded, false);
if (typeof VConsole !== 'undefined') {
window.vConsole = new VConsole();
}
boot();
// });
};
// omit this code
}
})();
When the index.html and main.js are modified as above, they can be placed in the project’s build template directory. They will be automatically copied to the release directory after the next build release. This means they don’t need to be modified again.