How to add AdMob Reward Ads to Phaser 3 Game

We will be using corodva to compile a Phaser 3 Game to Android App. We are going to go over step by step description of how to implement Admob Reward Ads to our game.

Let us start by creating a Phaser Game. For simplicity we will not have any game code in it but only a butoon to launch reward ads. Create the cordova project by using the following command in Node.js console. Refer to this blog to go over basic steps to compile an HTML5 game to Android app.

cordova create Sample com.mygames.sample Sample
cd Sample

We are going to use Admob Plus cordova plugin for implementing Admob ads in our game. Add plugin by using the command below. Make sure to replace App ID with your App ID in AdMob console. You need to create an App for your Android app and then create a Reward ad for that app which will be used here.

cordova plugin add admob-plus-cordova --save --variable APP_ID_ANDROID="ca-app-pub-0000000000000000~1111111111"

We will now add some html code for our app. We are going to use a javascript library for popup alerts in our app.

https://sweetalert2.github.io/

This is our HTML code

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Sample App</title>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=no">

    <script src="js/phaser.min.js"></script>
	
    <script src="js/sweetalert2.min.js"></script>
    <link rel="stylesheet" href="css/sweetalert2.min.css">
    <script src="js/polyfill.min.js"></script>

    <script src="cordova.js"></script>
    <script src="js/game.js"></script>

    <script src="js/init-app.js"></script>
</head>
<body>
    <div id="game-container">
        <div id="mygame3"></div>
    </div>
</body>
</html>

Our game code has one button which on click sends the request for loading the reward ad.

let emitter = new Phaser.Events.EventEmitter();

let launchGame = function () {
    let config = {
        type: Phaser.AUTO,
        scale: {
            parent: 'mygame3',
            mode: Phaser.Scale.FIT,
            autoCenter: Phaser.Scale.CENTER_BOTH,
            width: window.innerWidth * window.devicePixelRatio,
            height: window.innerHeight * window.devicePixelRatio
        },
        autoResize: true,
        backgroundColor: 0xff5733,
        scene: [GameScene]
    }

    let game = new Phaser.Game(config);
};

class GameScene extends Phaser.Scene {

    constructor() {
        super("GameScene");
    }

    init(config) {
    }

    preload() {
    }

    create() {
        this.cameras.main.setBackgroundColor('#ff5733');

	this.rewardButton = this.add.text(100, 100, 'Click to view Reward Ad', { fontFamily: "Arial", color: "#fff", fontSize: 40, align: 'center' });
	this.rewardButton.setInteractive().on('pointerdown', () => this.confirmRewardPopup() );
		
	emitter.off('sendAward', this.onReward, this);
        emitter.off('sendAwardError', this.onRewardError, this);
        emitter.off('sendAwardClose', this.onRewardClose, this);

	emitter.on('sendAward', this.onReward, this);
        emitter.on('sendAwardError', this.onRewardError, this);
        emitter.on('sendAwardClose', this.onRewardClose, this);

    }

    confirmRewardPopup(button) {
        let _self = this;
        _self.scene.pause();

        Swal.fire({
            animation: true,
            background: 'linear-gradient(#437186, rgb(26 63 80)) rgb(255, 255, 255)',
            html: "<br/><span style='font-size:1.2em; font-weight:400; color: #fbfaf7; text-shadow: 1px 1px 2px #3a3832;'>\nWatch the video and get your reward.</span><span style='font-size:0.75em; font-weight:400; color: #fbfaf7; text-shadow: 1px 1px 2px #3a3832;'><br/>Reward will be shown after the video.</span>",
            showCloseButton: false,
            showCancelButton: true,
            cancelButtonColor: 'rgb(253, 80, 80)',
            onClose: function () {
                _self.scene.resume("GameScene");
            },
            showConfirmButton: true,
            confirmButtonText: 'Yes, Show video',
            confirmButtonColor: '#18b3a4',
        }).then((result) => {
            if (result.value) {
                showReward();
            }
        });
    }
	
    onReward() {
        this.isReward = true;
        this.showRewardMessage();
    }

    onRewardClose() {
    }

    onRewardError() {
        let _self = this;
        _self.scene.pause();

        Swal.fire({
            animation: false,
            background: 'linear-gradient(#437186, rgb(26 63 80)) rgb(255, 255, 255)',
            html: "<br/><span style='font-size:1.2em; font-weight:400; color: #fbfaf7; text-shadow: 1px 1px 2px #3a3832;'>\nError while loading video. Check network connection.</span>",
            showCloseButton: true,
            showCancelButton: false,
            onClose: function () {
                _self.scene.resume("GameScene");
            }
        });
    }

    showRewardMessage() {
        let _self = this;

        _self.scene.pause();

        Swal.fire({
            animation: false,
            background: 'linear-gradient(#437186, rgb(26 63 80)) rgb(255, 255, 255)',
            html: "<br/><span style='font-size:1.2em; font-weight:400; color: #fbfaf7; text-shadow: 1px 1px 2px #3a3832;'>\nYou have got a reward.</span>",
            showCloseButton: true,
            showCancelButton: false,
            onClose: function () {
                _self.scene.resume("GameScene");
            }
        });
    }
	
}

We will be using Phaser EventEmitter to bind Phaser and Cordova AdMob libraries and exchange specific events which we will be listening to. Notice the emitter object we have created at the beginning. Admob code will use this to raise specific events which we will subscribe to in our Phaser code.

let emitter = new Phaser.Events.EventEmitter();

Our app looks something like this

Clicking on the Reward link opens a popup window for confirmation

Clicking on “Yes, Show video” will launch reward ad and once the video is over, we get a reward poup. In order to understand what we have done here, let us look into the code. In our game code, we are listening to three events; sendAward, sendAwardError, sendAwardClose. Once we send the request for reward ad from the code, cordova AdMob library will handle the request and once the ad has been loaded and ready to show, we will raise sendAward, sendAwardError, sendAwardClose from there which are listened by the game and will handle accordingly. Let us now look at the code which runs when the app is initialized by cordova. On “deviceready” event, we are preloading reward ad and keeping it in the background to show on request. There is no need to preload the ad and it can be loaded on request as well but since the ad video takes time to download, its always a good idea to preload it for better user experience since users might not like to wait for the video to download.

// reward
let rewardVideoLoaded = false;
let rewardVideoRequestCount = 0;
let sendReward = false;
let showRewardCalled = false;

let rewardAdId = 'ca-app-pub-3940256099942544/5224354917';
// reward video
let rewarded;

document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {
    initAd();
    launchGame();
}

//initialize the goodies
function initAd() {
    try {
        if (admob) {
            prepareReward();
        }
    } catch (err) {
    }
}

function prepareReward(canShow) {
    try {
        if (admob) {
            if(!rewarded){
                rewarded = new admob.RewardedAd({ adUnitId: rewardAdId });

                rewarded.on('load', (evt) => {    
                    rewardVideoLoaded = true;
                    showRewardCalled = false;
                });

                rewarded.on('loadfail', (evt) => {    
                    // if load has failed once try one more time
                    if (rewardVideoRequestCount === 1) {
                        prepareReward();
                    }
                    // called from game and failed, take some action
                    if (showRewardCalled) {
                        showRewardCalled = false;
                        if(emitter)
                            emitter.emit('sendAwardError');
                    }
                });

                rewarded.on('reward', (evt) => {    
                    sendReward = true;
                });

                rewarded.on('dismiss', (evt) => {    
                    rewardVideoLoaded = false;
                    rewardVideoRequestCount = 0;
                    if (sendReward) {
                        sendReward = false;
                        if(emitter)
                            emitter.emit('sendAward');
                    } else {
                        if(emitter)
                            emitter.emit('sendAwardClose');
                    }
                });
            }

            rewardVideoRequestCount++;

            if(canShow){
                rewarded.load().then(function (result) {
                    rewardVideoRequestCount = 0;
                    rewarded.show();
                });
            } else{
                rewarded.load();
            }
        }
    } catch (err) { }
}

function showReward() {
    try {
        if (admob) {
            showRewardCalled = true;
            if (rewardVideoLoaded) {
                rewardVideoRequestCount = 0;
                rewarded.show();
            } else {
                rewardVideoRequestCount = 0;
                prepareAndShowReward();
            }
        }
    } catch (err) { }
}

function prepareAndShowReward() {
    try {
        if (admob) {
            prepareReward(true);
        }
    } catch (err) { }
}

Notice how we have used emitter object to raise 3 events which we were listening in our Phaser game code. In this example we have used test id to display reward ad which is given by Google for testing. This sample code can be downloaded from github.


Leave A Comment

Your email address will not be published.