In this article we will discuss and explain how to set up additional features that publishing your game as a Facebook Instant Game gives you. If you have not already done so, you should read through the article Facebook Instant Games - Getting Started before continuing, as this article assumes that you are already familiar with the Instant Games concept and have already set up a project.
General Advice
Before we go on to look at FB Instant Games specific features, we should discuss a few more general things related to the Instant Game concept. The following is a general list of what is considered "best practices" for your games when published:
- Initial loading shouldn't take more than 5 seconds: Instant Games need to be "instant", and players will tend to turn away if the initial loading takes too long. The total size of your bundle can be up to 200MB, but Facebook recommends that you try to keep this as small as possible and aim for a 1MB initial download.
- Avoid secondary loading screens: Instant Games have their own loading bar that is shown to the user while the game is being downloaded. The GameMaker Instant Games extension will update this for you as the game loads, and normally at the start of the game you would call FBInstantGames_SetLoadProgress(100) to set it to 100%. However, if you have further loading to do (because you are receiving external files or creating dynamic sprites, etc...) then instead of having an additional loading bar, simply set the FBInstantGames_SetLoadProgress function to a lower value and increment it up to 100 again when finished.
- Optimize for mobile: Although Instant Games works on desktop browsers, the majority of sessions are from Mobile devices. It's a good idea to optimize rendering and aspect ratio for popular iOS and Android devices (see the section on Scaling, below).
- Include a short, non-intrusive tutorial for first-time players: In general, you should try to include a short tutorial with all Instant Games. This tutorial can be text, but Facebook would prefer it be interactive in some way, or even included more subtly as part of the gameplay. You should also allow players to come back to the tutorial if they choose to. It can be that they haven't played the game in a while, or that they want to show the tutorial to a friend. Take note not to force the tutorial in every session, but give experienced players the opportunity to skip it.
- Make sure to handle interruptions: The function FBInstantGames_StartGame() has an argument for an "onPause" script callback, which is for specifying a script that will be called when the game is interrupted. Ideally the script will allow your game to gracefully handle situations in which the player was interrupted (by a notification, phone call, app switch, etc.) by pausing the game and stopping any sounds or music until the user interacts with the game again in some way.
Scaling The Game Canvas
An Instant Game may be played on a variety of of different devices, using a any one of a number of different resolutions and aspect ratios, making it difficult to know what your initial canvas size should be for the game. In general you may want to base the game around an aspect ratio of 16:9 (since that is by far the most common aspect ratio), and then dynamically scale the canvas to fit whatever size the actual display is when the game is run.
A basic overview of the possible solutions are as follows:
- If the game has no cameras and viewports, then simply scale the game canvas by setting the window size and the app surface size to an appropriate width/height based on the aspect ratio
- Use a view port and camera and then scale them (along with the window and app surface) to an appropriate width/height based on the aspect ratio, scaling the game pixel resolution while maintaining the aspect ratio of the game and doing a "best fit" approach to the browser size. This will scale the visible playing area up or down depending on the size of the browser window so that the same area is always shown to the user (bars may be added around the game to "pad" the browser area).
- Use a view port and camera and then scale them (along with the window and app surface) to an appropriate width/height based on the aspect ratio, but maintain the game pixel resolution while changing the visible aspect ratio. This method will not scale the game itself, but rather change the visible area of the game to always fit the current size of the browser.
Now, what you do will very much depend on the game you are making, but we recommend that you try to always have the game fit the browser window (the third option, above) as it gives the best overall user experience. The code below is a very basic method for doing this (note that it requires a view camera and port to be enabled and visible in the game rooms), and it would be placed in the Begin Step Event of a controller object:
if (browser_width != view_wport[0] || browser_height != view_hport[0])
{
view_wport[0] = browser_width;
view_hport[0] = browser_height;
display_set_gui_size(browser_width, browser_height);
window_set_size(browser_width, browser_height);
window_center();
camera_set_view_size(view_camera[0], view_wport[0] / 2, view_hport[0] / 2);
surface_resize(application_surface, browser_width, browser_height);
}
This will have the game always fit the exact dimensions of the browser, without changing the pixel scale for drawing. Note that this is not a one-size-fits-all solution, and will need to be adapted to suit your game (for example, maybe you want to have a minimum width and height at which point you will scale the game down to fit, etc...)
Instant Game Functions
The Facebook Instant Games Extension (see here) has a number of functions that tap into the Instant Games API and permit you to do various things like add leaderboards or get player information. These functions are split into two general groups: those that will asynchronously trigger a callback script, and those that do not. Note that you can download a test project that shows how these functions work from the following link:
The non-asynchronous functions are as follows:
- FBInstantGames_GetContextID(): Returns the Context ID, which can then be used in leaderboard calls.
- FBInstantGames_GetContextType(): Returns the context type for the instant game. The return vale will be one of the following strings:
- "POST" - The game was launched from a wall post
- "THREAD" - The game was launched from a comment thread
- "GROUP" - The game was launched from a messenger group
- "SOLO" - The game was launched from the games browser
- FBInstantGames_GetPlatform(): Returns what platform the game is running on, as a string. Note that there is no documentation on these returned strings provided by Facebook, so you will need to test in scenarios to get the actual strings. Known examples are:
- "IOS" - iOS device
- "ANDROID" - Android device
- "WEB" - Web browser
- FBInstantGames_GetLocale(): Returns the locale that the game is running in, return ing a string with the format "ll_CC", where "ll" is a two-letter language code, and "CC" is a two-letter country code. For example, "en_US" represents U.S. English. Supported language codes can be found here, and supported country codes can be found here.
- FBInstantGames_GetPlayerName(): Returns the player’s name, as a string.
- FBInstantGames_GetPlayerPic(): Returns the URL of the player’s profile picture. this can then be used along with sprite_add() to be displayed in the game.
- FBInstantGames_GetPlayerID(): Returns the player’s unique Facebook ID number.
- FBInstantGames_Quit(): Exit out of the game.
The next set of functions all take a gmcallback_ script. The scripts provided to these functions will be called asynchronously whenever the Instant Games API generates a relevant callback. All scripts to be used in this way must start with "gmcallback_". In this way, the compiler will know not to obfuscate them and permit the extension to call them when required.
IMPORTANT! You cannot use the GML Code keywords "other" and "self" as they have no context when checked as part of a callback from the Instant Games functions. Using these keywords in any callback will cause an error, so they must not be used.
The available asynchronous functions are:
- FBInstantGames_StartGame(onstartgamecompletecallback, onpausecallback): Calling this function indicates to Facebook that the game is ready to play and that it should hide the loading overlay. You supply a script name (as a string) for onstartgamecompletecallback and it will be called when Facebook returns that the game can start. Note that until this callback script has run, the game context or user data may not be correct, so you should not do anything else until after this callback. The next script name string to supply is onpausecallback which is the script to call when Instant Games has been interrupted and pauses execution. Note that you can pass in empty "" strings if you do not wish to be notified of these events.
- FBInstantGames_SetScore(score,leaderboardname,extradata,callbackfunction): Record the player's score on the given leaderboard. You supply the score and the leaderboard name (a string) as well as any extra data (as a string) and the name of the callback script (as a string). Your leaderboard must be setup on the Facebook Developer dashboard under Instant Games > Leaderboards. If you wish to have a global leaderboard you will need to switch off the "Make Leaderboard Contextual" option (this option allows you to have a separate leaderboards for a group or a post etc...). Note that if you update your leaderboards (using the query function, below) before the callback script has been called then the score data will not have been updated with the new score, so it's a good idea to only call the query to update score values in the callback script for this function.
- FBInstantGames_QueryLeaderboard(leaderboard,numentries,offset,callbackfunction): Returns a specified number of entries from the leaderboard. You supply the leaderboard name (a string), then the number of entries to retrieve (an int), as well as an offset value (an int, use 0 for no offset) and the name of the callback script (as a string). The callback script will receive a string as argument0 which can then be parsed to extract the leaderboard data. The string will have the format: Rank:!Name:!PictureURL:!Score:!Rank:!Name:!etc... where each individual item is separated from the next by ":!". Note that the maximum number of returned entries you can request is 100.
- FBInstantGames_QueryLeaderboardPlayerPosition(leaderboard,callbackfunction): Queries the given leaderboard for the player’s Rank/Name/Score. You supply the leaderboard name (a string), and the name of the callback script (as a string), and the function will trigger the callback script where a string will be returned as argument0. This string will have the following format: Rank:!Name:!Score where each individual item is separated from the next by ":!".
Summary
Hopefully after having read through this you have a firm grasp of the concepts and requirements to make a go Facebook Instant Game. To see a "real world" context for much of what has been discussed in this article, you can download a YYZ of a small test project. This project can then be added as an app to your Facebook Developer dashboard, ready for testing.
-