Sokoban Series: Part 5, Publishing your Game

After spending too many hours of your free time on creating a game you want people to play and enjoy it. Next to that, you also want to earn a bit of money from your game. CrazyGames has a Developer Portal that enables you to upload a game, and if there are no problems get it published within a couple of days.

You automatically get part of the revenue that is made from advertisements on your game page, even without having any kind of advertisement in your game. You can increase the revenue share by letting CrazyGames have exclusive rights for the first couple of weeks of your game, by incorporating the logo in your game etc.
The only minimum requirement for revenue share is that your game is not published anywhere else, and does not contain branding of a competing portal.

It is also interesting for larger games that aim to release on Steam: you can submit an early version of your game, see what parts users like and dislike, while already earning some money. You can update your game after it has been released. And, you can choose to take down your game at any time; you remain the owner of your game.

The upload process is fairly short. You fill in the basic information of your game, upload your game files, configure the revenue share options and you are done.

game files

revenue share

You can immediately preview your game using using the Preview tool. This shows you what your game will approximately look like on CrazyGames. It also helps you to catch some final mistakes. You can update your game files at any point in time.

preview

Integrating Advertisements

In case you want to increase the revenue from your game you can integrate advertisements into your game. CrazyGames provides an SDK that facilitates this process.

The SDK comes with detailed instructions on how to install and use it.

Installation

Installing the SDK is done by including <script src="https://sdk.crazygames.com/crazygames-sdk-v1.js"></script> in your index.html. This installs the SDK under window.CrazyGames. The SDK requires that you use the game loader of CrazyGames: this is the loader that wraps your game, adds a full screen button, adds links to the Play store if your game is on it etc. It also contains the logic of requesting and displaying advertisements. The SDK comes with an HTML file that wraps your index.html. Just test your game by going to localhost/sdk.html instead of localhost/index.html.

Setup of the SDK

We instantiate the SDK in our init() function. The SDK is implemented using a singleton pattern, and you get an instance by calling getInstance().
After this we make a call to sdk.init() which initializes the SDK. The SDK communicates through events to let you know the state of a requested advertisement.

There are three kinds of events:

  • adStarted: fired when the advertisement starts playing. You should mute any music, and ensure that the game is not continuing playing
  • adFinished: fired when the advertisement finished playing. Resume your game.
  • adError: fired whenever some error occured, or when no advertisement is available. Continue with your game.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class LevelScene extends Phaser.Scene {
// ads
private sdk: any;
private adRequested: boolean;

init() {
const { SDK } = (window as any).CrazyGames;
this.sdk = SDK.getInstance();
this.sdk.init();
this.installListeners();
}

private installListeners() {
this.sdk.addEventListener('adStarted', this.adStarted);
this.sdk.addEventListener('adError', this.adError);
this.sdk.addEventListener('adFinished', this.adFinished);
}

private adStarted = () => {
this.sound.mute = true;
}

private adError = () => {
this.sound.mute = false;
this.adRequested = false;
}

private adFinished = () => {
this.sound.mute = false;
this.adRequested = false;
}
}

Requesting an Advertisement

We have installed the necessary event listeners, but still need to request an advertisement. We want to do this at the time where it annoys the user the least. We do it whenever we start a level. The SDK will automatically limit the number of advertisements that are displayed, so even when a user quickly finishes a level he won’t see to many advertisements.

We place the call to requestAd() in the preload() function, so that the ad plays while other assets are loaded in the background. An advertisement is played
as an overlay, so your game still runs in the background. As long as an advertisement is requested or playing we disable user interaction, simply by returning early from the update loop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class LevelScene extends Phaser.Scene {
preload() {
this.requestAd();
// load other assets if needed
}

update() {
if (this.adRequested) {
return;
}
// normal update logic here
}

private requestAd() {
this.adRequested = true;
this.sdk.requestAd();
}
}

And that is all you need to do to get advertisements up and running.

Sitelocking your Game

Games can get copied and distributed to other platforms without your permission, and it is difficult to enforce to take down your game from a platform.
What we can do is obfuscate our code and install a sitelock into the game that freezes your game when it runs on a disallowed domain.

We will make use of obfuscator.io: they provide a specialized tool to obfuscate and sitelock your code, and there is no need to reinvent the wheel. They surely do a better job than we can do ourselves, and having an easy to remove sitelock check is almost useless. Don’t forget that people can always download your code, and just remove the sitelock code. We enable our game to run on the following domains: .crazygames.com, .gioca.re, .1001juegos.com, .onlinegame.co.id, .speelspelletjes.nl and localhost. These are all the domains affiliated with CrazyGames, and of course localhost so we can still test it locally.

We install java-obfuscator as a dev-dependency (npm install -D javascript-obfuscator), and create a new build task in our package.json:

1
2
3
"scripts": {
"obfuscate": "webpack --mode production && npx javascript-obfuscator build/bundle.js --output build/obfuscated.js --compact true --domain-lock '.crazygames.com, .gioca.re, .1001juegos.com, .onlinegame.co.id, .speelspelletjes.nl, localhost'"
}

This will build our game and then obfuscate our game bundle. One downside of obfuscating the code is that it can have an impact on performance. For sokoban this is not a problem as the game is not very resource intensive, but may be a problem for more complex games. We obfuscate everything: Phaser, React and our game. One solution would be to only obfuscate some of your game logic, and make a bundle using that code.

You can always use the online interface on obfuscator.io to sitelock your game. Automating the task is easier though; you will surely update your game, apply some bug fixes or add new content. Automating the job costs a bit more time in the beginning, but quickly pays of. And of course make sure to upload the obfuscated code, and not the original file :).

Conclusion

We discussed how you can publish your game on CrazyGames, and how to integrate advertisement in between your levels to increase your revenue. Even if you do not do this last step you still get revenue from the advertisement on CrazyGames itself. Finally, we showed how you can protect your game from being stolen and being hosted without your permission.

Here are the other parts of this series: