CrazyGames launches new Developer Portal with revenue share options

Hey web game developers, just seen news regarding CrazyGames, they now have a new developer portal and offer revenue share options for your HTML5 games! Its great to see portals placing value on developers efforts like this.

Note that this also includes web versions of games exported from Unity / Unreal etc..

To celebrate the launch of the public beta version of the CrazyGames Developer Portal, they have organised a contest for game developers. Three independent game experts will choose the best games that have been uploaded between the 1st of October and the 30th of November. The winner will be awarded $2,000! Yes, I think I may be entering some of mine, so fingers crossed :) .

I have been looking for another potential avenue for earning money from my Facebook Instant Games so hopefully re-targeting them to general web gaming can be part of my new strategy.

There are however a couple of caveats that may put many off. You cannot earn revenue unless you satisfy these 3 conditions:

  • The game doesn’t contain advertisements.
  • The game doesn’t contain branding from another games portal.
  • The game has not been published on other portals before (Does NOT include Facebook Instant Games Portal).

Booty5 HTML5 Game Maker Update – Support for Facebook Instant Games Added

Facebook Instant Games Support

Finally released the latest version of Booty with support for Facebook Instant Games. Within the Booty5 engine you will find a new class called Instants which is a small wrapper around the Facebook Instants SDK. Games exported from Booty with Instants enabled in the settings will automatically initialise the Facebook Instants SDK and download all preloaded global resources, note that you will need to download any scene local resources yourself after the main download.

To make your project Facebook IG compatible simply tick the Facebook Instants check box in the projects settings then enter the local launch URL into the Host box in project settings, e.g:

https://www.facebook.com/embed/instantgames//player?game_url=https://localhost:8080/

Dragon Bones Animation Support

Unfortunately you cannot edit Dragon Bones animations within the Booty5 editor but you can add the associated PNG, skeleton and atlas JSON files that are exported from Dragon Bones to the editor as resources and access them from within code, e.g:

// Parse dragon bone data
var factory = dragonBones.b5Factory.factory;
var skel = JSON.parse(b5.Utils.resolveResource("my_skeleton", "raw").data);
var atlas = JSON.parse(b5.Utils.resolveResource("my_atlas", "raw").data);
factory.parseDragonBonesData(skel);
factory.parseTextureAtlasData(atlas, b5.Utils.resolveResource("my_texture", "brush"));

// Create an actor containing the dragon bones armature and attach it to a parent actor
var dba = factory.buildArmatureDisplay("name");
dba.animation.play("anim");
dba.x = 0.0;
dba.y = 0.0;
ParentActor.addActor(dba);

I will in the near future wrap the above into the engine / editor to make it more readily accessible, as well as add the same support for Spine.

Other Stuff

The editor has had a whole host of bug fixes and additional changes to keep pace with the Booty5 game engine. See the Booty5 game engine for more details on those changes.

Upcoming Demos and Documentation

Over the next few days I will be releasing the full Booty5 projects for some of my recent Facebook Instant games so you can use these as a reference / starting point. These games cover many areas of the Facebook Instants SDK including displaying ads, using in-app purchases, submitting leaderboard scores, grabbing and displaying leaderboard entries, inviting other players to play, sharing progress, switching contexts and posting updates to Messenger.

The following full projects have been uploaded thus far:

You can grab the latest version of the Booty5 Game Maker from the Booty5 website.

I am still in the process of updating documentation, I will post details here once that is finished.

Booty5 HTML5 Game Engine Update out – Facebook Instant Games Support Added

It’s been a long long while since I put an update to Booty5 out so I thought it time. I have been playing around with Facebook Instant Games over the last few months so I added support for Facebook Instant Games to the Booty5 engine. You will find a new utility class called Instants that wraps up the Facebook Instants SDK. This has been tightly integrated into the loader for the Booty5 game editor. I will be releasing the updated version of the Booty5 editor with direct Facebook Instant Games export support very soon. Along with that I will be releasing the source to some of my games to help developers learn how to use the new features more easily. The complete list of Booty5 engine changes (v1.5.5) include:

  • New hit property added to Actors. If true then will be included in hit testing
  • New dock_screen property added to Actors. If true then docking will be to screen edge instead of scene edge
  • New padding property added to Actors. Text padding (used when caching)
  • New scale_method property added to Actors. Scale method used to fit actor to screen
  • New draw_reverse property added to Actors. If set to true children are drawn in reverse order
  • New _av property added to Actors. This will set active and visible states at the same time
  • New method removeAllActors added to Actor which removes all actors from the actors child list
  • New getSlot and moveToSlot methods added to Actor which allows you to query a child sort index and modify it
  • New overlapsRect method added to Actors which checks for a rect area overlapping the Actors rect area
  • New circleOverlaps method added to Actors which checks for a circular area overlapping the Actors circular area
  • New circleOverlapsRect method added to Actors which checks for a rect area overlapping the Actors circular area
  • New fullCircleOverlapTest method added to Actors which checks for a circular area overlapping the Actors circular area (taking into account transforms)
  • New stroke_filled property added to all Actor types which if true will cause stroke will be drawn
  • New line_height property added to LabelActor which specifies the height of a line of text
  • New _text property added to LabelActor which sets the labels text and updates its cached version if cached
  • New deactivate property added to Animations. When set to true deactivates and hides target actor when its done (default false), should only be used with actors
  • Many new easinng funnctions added to the animation system
  • App canvas_width and canvas_height now known as design_width and design_width
  • Fonts now added to the app as resources, the underlying font loaded uses the FontObserver lib to load fonts
  • Raw JSON resource type now added to the App
  • New started property added to the App which is a callback that will be called when the app starts
  • All App resource containers are now objecsts instead of arrays
  • App waitForResources now calls a supplied callback to alert the user of progress during loading
  • App main logic loop is now ran on requestAnimationFrame
  • New draw_reverse property added to Scenes. If set to true children are drawn in reverse order
  • New _av property added to Scenes. This will set active and visible states at the same time
  • Added new Task type called TaskQ which is a collection of tasks that are ran serial. Only the first task in the queue is ran, once that tasks is complete the next task in the queue is ran.
  • Resources now checked for load failure and attempt to reload a number of times before giving up
  • Value passed to Actor _atlas can be an atlas object or the name of an image atlas brush
  • Calling playAnim or playTimeline on an inactive or invisible Actor will make activate it and make it visible
  • Hit tests are no longer carried out on inactive Actors
  • Fixed Actor _scale property so that it now updates the main transform
  • Fixed virtual Actor margins
  • Action lists are now optional component and not included by default
  • Support for Facebook Instant Games added

Please note that this version of Booty5 may not be completely compatible with your existing code so back up before trying it!

The complete source to Booty5 is available on Github here.

I will update the game editor, documentation and e-book in the near future.

Oh I also have a Dragon Bones lib coming soon too.

Simple Web Audio Wrapper

Seen this question asked numerous times, how to set up and use the Web Audio API, so I ripped some code out of my engine Booty5 and slimmed it down a bit and here it is, I have also pushed it to Github here.

/**
 * A Sound represents a sound effect object and can be used to play back audio
 *
 * Generally a sound should be added to either a {@link b5.Scene} or the global {@link b5.App}'s resources so that it can be managed by them.
 *
 * Example showing how to load and play a sound effect
 *
 *      var sound = new b5.Sound("explosion", "sounds/explosion.mp3", true);
 *      var instance = sound.play();
 *
 * For a complete overview of Resources see {@link http://booty5.com/html5-game-engine/booty5-html5-game-engine-introduction/resources-the-stuff-that-games-are-made-of/ Booty5 Resources Overview}
 *
 * @class b5.Sound
 * @constructor
 * @returns {b5.Sound}                      The created sound
 * @param name {string}                     Name of sound resource
 * @param location {string}                 The sound file location
 *
 * @property {b5.App|b5.Scene}          parent          - Parent resource manager (internal)
 * @property {object}                   snd             - Sound instance (re-usable sound only) (internal). For Web Audio stores a {source:AudioBufferSourceNode, gain:GainNode} object for auto play sounds
 * @property {object}                   buffer          - AudioBufferSourceNode containing decoded audio data (Web Audio only)
 * @property {string}                   name            - Name of this sound resource
 * @property {string}                   location        - The location of the sound file that is used to create the audio object
 * @property {boolean}                  loop            - If set to true then sound will be looped
 * @property {boolean}                  preload         - If set to true then this sound will be preloaded
 * @property {boolean}                  auto_play         - If set to true then this sound will be preloaded
 * @property {boolean}                  loaded          - If true then this resource has finished loading
 */

var loadFile = function(filename, blocking, callback, binary)
{
    var req = new XMLHttpRequest();
    req.open("GET", filename, !blocking);
    req.overrideMimeType("application/json");
    if (binary)
        req.responseType = "arraybuffer";
    if (!blocking)
    {
        req.onreadystatechange = function()
        {
            if (req.readyState === 4)
            {
                if (req.status === 200 || req.status === 0) // 0 for node-webkit
                {
                    if (binary)
                        callback(req.response);
                    else
                        callback(req.responseText);
                }
                else
                    callback(null);
            }
        };
    }
    try
    {
        req.send();
    }
    catch(e)
    {
        return false;
    }

    if (blocking)
    {
        if (req.status === 200)
        {
            if (binary)
                callback(req.response);
            else
                callback(req.responseText);
        }
        else
            callback(null);
    }

    return true;
};

b5.Sound = function(name, location)
{
    // internal variables
    this.parent = null;                 // Parent container
    this.snd = null;                    // Sound instance (re-usable sound only). For Web Audio stores a {AudioBufferSourceNode, GainNode } object for auto play sounds
    this.buffer = null;                 // AudioBufferSourceNode containing decoded audio data (Web Audio only)

    // Public variables
    this.name = name;					// The sound name
    this.location = location;			// Location of the sound
    this.loop = false;                  // If set to true the this sound will replay continuously
    this.preload = false;               // Set to true to preload sound
    this.loaded = false;                // Set to true once audio cam be played
    this.auto_play = false;             // Set to true to auto play sound when loaded
    this.load_retry = 0;
};

/**
 * AudioContext used by Web Audio API
 * @type {object}
 */
b5.Sound.context = null;
b5.Sound.muted = false;

/**
 * Initialises the sound system
 * @parm app {b5.App}   The App that will manage the audio engine
 * @returns {boolean}   true for success or false if error
 */
b5.Sound.init = function(app)
{
    if (app.use_web_audio)
    {
        try
        {
            window.AudioContext = window.AudioContext || window.webkitAudioContext;
            if (window.AudioContext === undefined)
                return false;
            b5.Sound.context = new AudioContext();
        }
        catch(e)
        {
            return false;
        }
        return true;
    }
    return false;
};

/**
 * Loads the sound
 */
b5.Sound.prototype.load = function(force)
{
    var debug = b5.app.debug;
    //var snd;
    var that = this;
    var filename = this.location;
    var auto_play = this.auto_play;
    if (!loadFile(filename, false, function(data) {
        if (data !== null)
        {
            b5.Sound.context.decodeAudioData(data, function(buffer) {
                that.buffer = buffer;
                if (auto_play)
                    that.play(force);
            }, function(e)
            {
                console.log(e)
            });
        }
        else
        {
            that.load_retry++;
            if (that.load_retry < 3)
                that.load();
        }
    }, true))
    {
        that.load_retry++;
        if (that.load_retry < 3)
            that.load();
    }
};

/**
 * Starts playback of the sound
 * @returns {object} An Audio object representing the playing sound or a {source, gain} object if using Web Audio API
 */
b5.Sound.prototype.play = function(force)
{
    if (force != true && b5.Sound.muted)
        return null;
    if (this.buffer === null)
        return null;
    var context = b5.Sound.context;
    var source = context.createBufferSource();
    var gain = context.createGain();
    source.buffer = this.buffer;
    source.loop = this.loop;
    source.connect(gain);
    gain.connect(context.destination);
    gain.gain.value = 1;
    source.start(0);
    if (this.auto_play)
        this.snd = { source: source, gain: gain };
    return { source: source, gain: gain };
};

/**
 * Stops playback of thr sound (re-usable sound only)
 */
b5.Sound.prototype.stop = function()
{
    var snd = this.snd;
    if (snd === null || snd === undefined)
        return;
    snd = snd.source;
    snd.stop();
};

Happy coding!

Simple Messaging System with Redis and Node.js

Hey all, been a while since I posted anything constructive, I’ve been so busy wasting my time creating games for Facebook Instant Games Messenger (I will do a proper write up with my analysis and final findings / thoughts on this very soon). Not all has been lost working on Instant Games however. Two of my games required an instant messaging system that enables me to send real-time messages between players which ironically the Instant Games SDK doesn’t cater for. So I created one using Node.js and Redis (these two bad boy pieces of tech together are like sweet music). You can grab the code from Github here.

Note that you will need to install this to your own server, I like to run most of my node modules using PM2. So to get the messaging system up and running just run pm2 msys. The server looks to the /msys endpoint, but you can change this in msys.js if you need it to go elsewhere. No, I don’t answer questions on how to set up servers and mess with Apache config files because I hate all that junk, it gets in the way of my actual coding which I do enjoy :) . If you cannot do this stuff yourself then you probably should be paying someone else do this for you.

Oh word of warning, any messages sent will time out after 7 days (this is to keep Redis memory usage down), but you can extend this to whatever time limit you like. Messages are queued, when you collect the pending messages it collects them all and deletes them from the database.

Ok, how to use client side? Here is a simple class (erm I mean collection of functions) with an awesome original name that I ripped out of one of my games for you guys to use:

var Backend = {};

Backend.SendMessage = function(data, done_callback)
{
    var url = "https://yourdomain.com/msys?c=s&t=<your token>";
    url += "&g=1";
    url += "&u=" + data.to_id;
    url += "&d=" + encodeURIComponent(JSON.stringify(data));
    b5.Utils.SendGetRequest(url, function(response) {
        if (done_callback !== undefined)
            done_callback(response);
    })
}

Backend.SendMessageMulti = function(recipients, data, done_callback)
{
    var users = "";
    var len = recipients.length;
    for (var t = 0; t < len; t++)
    {
        users += recipients[t];
        if (t < (len - 1))
            users += "_";
    }
    var url = "https://yourdomain.com/msys?c=s&t=<your token>";
    url += "&g=1";
    url += "&m=" + users;
    url += "&d=" + encodeURIComponent(JSON.stringify(data));
    b5.Utils.SendGetRequest(url, function(response) {
        if (done_callback !== undefined)
            done_callback(response);
    })
}

Backend.GetMessages = function(done_callback)
{
    var url = "https://yourdomain.com/msys?c=g&t=<your token>";
    url += "&g=1";
    url += "&u=" + Social.GetPlayerID();
    b5.Utils.SendGetRequest(url, function(response) {
        if (response.status == 200)
        {
            var data = decodeURIComponent(response.responseText);
            var obj = JSON.parse("[" + data + "]");

            if (done_callback !== undefined)
                done_callback(obj);
        }
        else
        {
            if (done_callback !== undefined)
                done_callback();
        }
    })
}

There are a few functions in here that you will need to implement yourself:

  • Social.GetPlayerID() – Replaced with your players user ID, if you are using Facebook Instants SDK then use FBInstant.player.getID()
  • b5.Utils.SendGetRequest() – Performs a GET request, e.g:
b5.Utils.SendGetRequest = function(url, callback)
{
    var req = new XMLHttpRequest();
    req.onreadystatechange = function()
    {
        if (callback != undefined && req.readyState == 4)
            callback(req);
    }
    req.open("GET", url, true);
    req.send();
}

Anyway, that’s it, hope you find more useful than I did. Happy coding :) .

Multi-game Facebook Instant Games Bot (free code)

So, I decided to post the code to my Facebook Instant Games Bot to save other devs a lot of research and time. The bot is written using node.js, you will need to set up a hosting service that will run your bot. I chose Digital Ocean to host mine because Droplets are super simple to set up and cheap as chips. I service 5 games with the single bot and I never go over my $5 per month limit. If you do sign up with them then please use my referral link, you get $10 of free credit.

This bot server can handle many games at once, simply add new games to the pages.js source file. Click this link to download the bot.

Files in this archive include:

  • bot.js – The main bot which accepts requests and creates new players
  • bot_none_cluster.js – None cluster version of bot.js (can be used with pm2 -i option)
  • crawler – Crawls through the database checking for players that need to be messaged and messages them, also removes players that do not respond from the database
  • messaging.js – Sends messages out to players
  • pages.js – Stores page data

Usage:

  • node bot.js – Runs the bot which listens for connections and adds players to the database
  • node crawler.js – Periodically crawls through the database finding players that need to be messaged and sends them a message

Note that you will need to set up both node and redis on your server in order for the bot to work. Performance wise the bot is incredibly fast. I am servicing 5 games with mine and using only 1% CPU.

To help get you started see my other blogs:
Installing and running Node.js on a VPS
Installing Redis to Windows / Linux

Facebook Instant Games Category Breakdowns

I track all things Facebook Instant Games related, its a new little obsession of mine. I went ahead and calculated how many games are in each genre out of the current crop of just under 3000 available games. Below is a list of Facebook game genres along with how many games are in each:

  • Action – 577 games
  • Puzzle – 1035 games
  • Trivia & Word – 118 games
  • Simulation – 150 games
  • Board – 98 games
  • Sports – 282 games
  • Match 3 – 100 games
  • Card – 64 games
  • Slots – 43 games
  • Runner – 260 games
  • Strategy – 73 games
  • Role Playing – 91 games
  • MOBA – 4 games
  • Builders – 15 games
  • Bingo – 9 games
  • Poker & Table – 34 games
  • Card Battle – 4 games

Lets take a look at the list sorted by total MAU in those categories:

  • Puzzle – 1035 games (49116400 total MAU – avarage per game is 47455)
  • Sports – 282 games (44689600 total MAU – avarage per game is 158473)
  • Trivia & Word – 118 games (41406500 total MAU – avarage per game is 350902)
  • Action – 577 games (38617000 total MAU – avarage per game is 66927)
  • Board – 98 games (17343200 total MAU – avarage per game is 176971)
  • Simulation – 150 games (16033700 total MAU – avarage per game is 106891)
  • Runner – 260 games (14430399 total MAU – avarage per game is 55501)
  • Card – 64 games (10803200 total MAU – avarage per game is 168800)
  • Match 3 – 100 games (6334800 total MAU – avarage per game is 63348)
  • Role Playing – 91 games (4992400 total MAU – avarage per game is 54861)
  • Strategy – 73 games (4511700 total MAU – avarage per game is 61804)
  • Slots – 43 games (1562100 total MAU – avarage per game is 36327)
  • Bingo – 9 games (1474800 total MAU – avarage per game is 163866)
  • Poker & Table – 34 games (1464900 total MAU – avarage per game is 43085)
  • Card Battle – 4 games (924500 total MAU – avarage per game is 231125)
  • MOBA – 4 games (322000 total MAU – avarage per game is 80500)
  • Builders – 15 games (193300 total MAU – avarage per game is 12886)

What can we ascertain from these figures? Well, Puzzle games seem to be the most popular amongst developers, unfortunately users do not share that view with a very low average MAU per game. Trivia & Word is the leading category in terms of of average MAU per game whilst having far fewer games has an average MAU many times greater.

Facebook Messenger Instant Games Charts

I’ve been tracking the positions and MAU of Facebook Messenger Instant Games for a while now. I track them for many reasons include:

  • Get an overall picture of where all IG games are at
  • Get an overall picture of how IG itself is performing
  • Analyse which games are rising / falling
  • Guess at how much developers are roughly earning
  • Spot clones and dodgy developers
  • See how my own games and performing

I use this information to improve my own games. Whilst its not offered much success for me it may do to some. With that in mind I am posting a much stripped down version of the charts here to enable other developers can utilise some of the information and help improve their own games / track where their games are at in the grand scheme of things.

Facebook Messenger Instant Game Charts 2018

Shuffle Match live on Facebook Instant Games in Messenger

Shuffle Match Facebook Instant Game

Shuffle Match Facebook Instant Game

My first HTML5 Facebook Instants games is now live on Messenger. I actually finished this games a couple of months back, but because of the Facebook privacy saga all further game reviews were put on hold, so hundreds (potentially thousands) of games have been sat in limbo. Its good to finally see a product live on the platform however.

Shuffle Match is basically a memory matching game where you are shown a bunch of numbered tiles, you memorise them then they slide off screen and you have to try and remember where they all were. The game is monetised by offering the player the ability to continue by watching an ad if they run out of lives. Its a simple, fun game that’s great to play against friends.

Play Shuffle Match on Messenger Now

Just released my latest cross platform game Idle Gangsters on iOS, Android and Facebook Gameroom. The game is an experiment o see if it was possible to mix Idle Incremental and Match-3 game play styles and it seems to have worked.

Rise through the ranks of the mafia in this fun, addictive idle incremental match-3 game.

Start out as a low life punk and work your way up through the mafia ranks to Godfather using every manner of lie, trick and scheme possible.
Muscle in on cities, launder goods, build up illegal rackets and generate cash, gaining the respect of your fellow mafians and rising through the ranks of the mafia. Hire bosses, kit them out, order hits, bribe cops, fight off rival gangs and the feds and much more.

  • Launder loot for the mob using Match-3 generating large amounts of cash and respect
  • Buy into 20 rackets to earn cash without lifting a finger
  • Free upgrades for all rackets
  • Smash your way through 10 ranks of the mafia from Punk to Godfather unlocking exciting new content
  • Muscle in on and take over 10 different cities from Brooklyn to Las Vegas
  • Hire upgradeable city bosses to increase cash flow, reduce racket costs, generate cash offline and use perks
  • Equip bosses with up to 16 perks to boost city rackets and laundering
  • 20 loot laundering boosts / hazards
  • 10 global powerups which affect time and cash flow
  • Unlimited missions for big cash boosts
  • Unlimited special missions for huge cash boosts which take place across 10 unique minigames
  • Extra 5 daily bonus minigames which generate cash, respect and diamonds
  • Stats tracking, over 150 individually tracked stats
  • Around 300 achievements to earn
  • Facebook connect with invites, gifting and leaderboards
  • Cloud save game backup and restore

Idle Gangsters is available for free on the App Store for iPhone and iPad

Idle Gangsters is available for free on the Google Play for Android

The game is also available for free on Facebook and Facebook Gameroom

Idle Gangsters Title Screen

Idle Gangsters Title Screen


Idle Gangsters Match-3

Idle Gangsters Match-3


Idle Gangsters Idle Incremental

Idle Gangsters Idle Incremental