Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
<script type="text/javascript">
//Modify these items.
const DOMAIN_KEY = "<youdomainKey>";
const GAME_KEY = "<gameKey>";
const GAME_VERSION = "<gameVersion>";
const DEV_MODE = true;
<!DOCTYPE html>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" type="text/css" href="css/gse-style.css" />
<link rel="stylesheet" type="text/css" href="css/gse-style-loading.css" />
<style type="text/css">
body {
background-color: black;
margin: 0;
padding: 0;
<div id="gse-player" class="gse-frame">
<!-- The engine will create and insert drawing elements here. -->
<div class="gse-overlay">
<div id="gse-text" class="gse-dialog">
<button id="gse-text-cancel">Cancel</button>
<button id="gse-text-done">Done</button>
<p id="gse-text-prompt"></p>
<textarea id="gse-text-input"></textarea>
<div id="gse-loading" style="visibility: visible;">
<img src="images/gse-loading.png" />
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script type="text/javascript">
var playerId = "";
var playerIdKey = "";
var sessionToken = "";
function postScore(_score, _leaderboard) {
var url = 'https://' + DOMAIN_KEY + '' + _leaderboard + '/submit';
var player_identifer;
var body = {
'score': _score,
'member_id': playerId
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-session-token': sessionToken
body: JSON.stringify(body)
.then(res => console.log(res.json));
function getPlayerIdPropertyId(_engine, gameObject) {
(k) => {
const attrib = gameObject.attributes[k].name;
if (attrib === 'playerId') {
playerIdKey = k;
playerId = gameObject.attributes[k].$;
function processPlayerId(_engine, _object) {
playerId = _object.player_identifier;
sessionToken = _object.session_token;
_engine.postEvent('externalWriteGameAttribute', null, `game.attributes.${playerIdKey}`, playerId)
function lootLockerLogin(_engine) {
var body = {
'game_key': GAME_KEY,
'game_version': GAME_VERSION,
'development_mode': DEV_MODE
if (playerId != null && playerId != "") {
body["player_identifier"] = playerId
var url = 'https://' + DOMAIN_KEY + '';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
body: JSON.stringify(body)
.then(res => res.json())
.then(json => processPlayerId(_engine, json));
(function(global) {
// This function is called after the engine script file has loaded.
// At that point, the gse.ready function has be defined and we can call it.
global.onEngineLoad = function() {
// gse.ready() is a global function defined by the engine JavaScript
// file. It is the only global function of the API and the only way to
// initially interact with the game. The remainder of the API is object-
// oriented.
// We define a ready callback function and pass it to gse.ready().
// Later, that callback will be invoked when the engine is ready.
// Via the callback's arguments, the GameSalad code passes us back an
// object called "engine" which implements several useful API functions.
gse.ready(function(engine) {
// These bits of code are optional. This demonstration shows how to
// use a delegate to control a loading animation that spins in
// between scene loads.
// A delegate is a JavaScript object that receives callback from the
// engine on particular events.
// To customize this animation, you can replace the gse-loading.png
// image with another, and you can tailor the CSS styling and
// animation to match (say, make it bounce instead of spin).
// Or, you can replace this entirely with your own JavaScript code.
var loadingElement = document.getElementById('gse-loading');
var playerDelegate = {
onGameReady: function() {
engine.project.getObjectJSON(function(gameObj) {
getPlayerIdPropertyId(engine, gameObj)
onLoadingBegin: function() {
engine.showOverlay(); = 'visible';
onLoadingEnd: function() { = 'hidden';
onWindowResize: function() {
onTweetSheet: function (msg, edit, img) {
print("msg:", msg)
switch (msg) {
case 'login':
onGameCenterPostScore: function (_score, _leaderboard) {
postScore(_score, _leaderboard);
window.addEventListener('resize', playerDelegate.onWindowResize, false);
// Pause and resume on page becoming visible/invisible
var MUTE_ON_HIDDEN = false;
document.addEventListener("visibilitychange", onVisibilityChanged, false);
document.addEventListener("mozvisibilitychange", onVisibilityChanged, false);
document.addEventListener("webkitvisibilitychange", onVisibilityChanged, false);
document.addEventListener("msvisibilitychange", onVisibilityChanged, false);
function onVisibilityChanged() {
if (document.hidden || document.mozHidden || document.webkitHidden || document.msHidden)
gse.setGameVolume(engine, 0);
gse.setGameVolume(engine, 1);
// These lines initialize and configure the engine.
// The choices for engine.setOptions are:
// viewport-reference = game | frame | window
// viewport-fit = none | center | fill | letterbox | overscan
'viewport-reference': 'window',
'viewport-fit': 'letterbox'
// While the engine is ready, the game assets have not been loaded
// yet. The final step is to begin loading the game.
// We have a few options:
// 1. Begin loading game assets immediately, from the default game
// location, and then start the first scene soon as it is complete.
// This is the simplest option with just one line.;
// 2. Load a game from a location other than the default. Use this
// if you have renamed the game directory, or have organized the
// files on the webserver different from the default.
// 3. Begin loading the game in the background, but do not
// immediately start the first scene.
// Instead, we will delay starting the game until some user event,
// such as waiting for them to click a button. This is an open ended
// choice, so implementations will vary.
// A very simple example might look like this below.
// Notice we pass a path to the load() function and then later call
// the play() function without any arguments. You just need a
// reference to the engine object, either in this closure scope or
// with a global variable.
// If you choose this route, you might want to tinker with the
// loading animation code so that you get the right visual experience.
// begin loading...
// register a click listener to start the game
//document.getElementById('gse-player').addEventListener('click', function() {
// 4. Neither load nor play the game immediately. Like the previous
// option, this can be very open ended. For example, maybe you want
// to play a video clip first, and then load the game.
// You can defer calling engine.load() and in response
// to whatever JavaScript events suits your design.
There are three ways to declare the engine script tag.
Declare the script for gse.ready() first, but wrapped in an onload function.
Then declare the script tag for the engine with the "async" attribute and an
"onload" handler.
This allows for a smoother page load while ensuring that things are loaded in
the right order.
This is the preferred method and the one use by this sample.
Declare the engine script tag first, with neither "async" nor "onload".
Then declare the loading script with gse.ready() after it. In this case, the
call to gse.ready() is global instead of wrapped in an onload function.
This is more straightforward, but depending on the overall layout of your page,
it could interrupt page loading.
You can generate the script tags dynamically with the DOM API or with help from
a library like jQuery. This is open ended and could get complicated. Generally
though, the GameSalad engine can play nice with other code and libraries as long
as these things happen in order:
1. Load the engine file.
2. Invoke gse.ready() with your ready callback as the argument.
3. Some time later, the engine will automatically invoke your ready callback.
4. You may invoke any of the engine.* functions within your read callback or at
any time afterward (provided you keep a reference to the engine object), but
not before.
Note that the "gse" namespace is global but the "engine" object is not.
<script type="text/javascript" src="js/gse/gse-export.js" async onload="onEngineLoad()"></script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment