Check if Device is Ready in Phonegap

Apparently, you have to check if your device is ready before you can use Phonegap plugins like Google Analytics and Admob.  Use the “deviceready” listener:

if(( /(ipad|iphone|ipod|android|windows phone)/i.test(navigator.userAgent) )) {
  document.addEventListener('deviceready', initApp, false);
} else {
  initApp();
}

Custom Share Buttons in Phaser and Phonegap

So let’s say you want a Twitter share button and a Facebook share button at the end of your game. With Twitter, you can share your high score. With Facebook, you can share your game’s website link. Here’s what you do.

Make a function for opening a window in a browser. For more on that, see http://www.melkybee.com/blog/2015/03/29/how-to-open-links-in-a-browser-in-a-phaser-js-and-phonegap-build-project/.

In index.html:

function openDeviceBrowser(externalLinkToOpen) {
  window.open(externalLinkToOpen, '_system', 'location=no');
}

In JS:

// Custom share buttons in Phaser
shareTwitterButton = game.add.button(10, 10, 'shareTwitterButton', this.shareTwitter, this, 0, 0, 0);
shareFacebookButton = game.add.button(10, 50, 'shareFacebookButton', this.shareFacebook, this, 0, 0, 0);

openDeviceBrowser() opens a URL that uses Twitter web intent. More on that here – https://dev.twitter.com/web/intents

shareTwitter : function() {
  openDeviceBrowser('https://twitter.com/intent/tweet?url=http://custom_url&text=Custom+Text&via=custom_via&hashtags=custom_hashtag');
}

The Facebook sharer.php is no longer documented, but it should still work. Just replace “http://custom_url” with your own custom url.

shareFacebook : function() {
  openDeviceBrowser('https://www.facebook.com/sharer/sharer.php?u=http://custom_url');
}

The HTML of the URL that you are sharing should have the proper <meta> tags. That way, data such as a title and image will populate when you share your link. For Twitter, see https://dev.twitter.com/cards/overview. For Facebook, see https://developers.facebook.com/docs/sharing/best-practices.

Example (put these in your <head> tag in the HTML of the web page (http://custom_url above) that you are sharing):

<!-- Twitter Card data -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@custom_twitter_handle">
<meta name="twitter:title" content="Custom Title">
<meta name="twitter:description" content="Custom Description">
<meta name="twitter:image" content="http://custom_image.png">
<!-- Facebook Open Graph data -->
<meta property="og:type" content="website">
<meta property="og:title" content="Custom Title">
<meta property="og:url" content="http://custom_url">
<meta property="og:description" content="Custom Description">
<meta property="og:image" content="http://custom_image.png">

Object Pooling Example in Phaser

Scuba Chibi is potentially endless, so if I’m up to 120 points or so, I could experience lots of lag if I don’t use object pooling. It’s because I’m doing a lot of creating and deleting of objects (i.e. the enemies), and that wastes memory. This is a situation when object pooling becomes useful, so that I just deactivate objects that aren’t used and then reactivate them when they need to be reused. http://en.wikipedia.org/wiki/Object_pool_pattern

So let’s make an object pool for enemies and have up to 10 enemies of one type on the screen at one time.

this.enemyPool1 = [];
this.MAX_ENEMIES_PER_TYPE = 10;

Create all the enemies in the object pools, but deactivate them. Setting “obstacle.outOfBoundsKill = true;” means that the enemy will be deactivated when they go offscreen.

create: function() {
  var obstacle;

  // define obstacle group
  this.obstacles = game.add.group();
  this.obstacles.enableBody = true;
  this.obstacles.physicsBodyType = Phaser.Physics.ARCADE;

  // create enemy object pools and deactivate enemies
  for (i = 0; i < this.MAX_ENEMIES_PER_TYPE; i++) {
    obstacle = this.obstacles.create(-1000, -1000, 'enemy1');
    obstacle.checkWorldBounds = true;
    obstacle.outOfBoundsKill = true;
    obstacle.kill();
    this.enemyPool1.push(obstacle);
  }
}

Activate an enemy.

addObstacle: function(x, y, type) {
  var obstacle,
    i = 0;
  if (type === 1) {
    for (i = 0; i < this.enemyPool1.length; i++) {
      if (!this.enemyPool1[i].alive) {
         obstacle = this.enemyPool1[i];
         obstacle.reset(x, y);
         return obstacle;
      }
    }
  }
  return obstacle;
}

So basically, a couple of important functions in Phaser for object pooling are:

sprite.kill(); // halts rendering, but the object still exists
sprite.reset(); // reactivates the object so that it renders again and you can interact with them

Resizing Sprites to Fit Screen Resolutions Using Phaser

When I started Scuba Chibi, I made the mistake of making sprites small, and then scaling them up to fit larger screen resolutions.

game.stage.smoothed = true; // render crisp art
game.stage.scale.fullScreenScaleMode = Phaser.ScaleManager.SHOW_ALL;

One problem is that they never scaled up at all. They remained small instead of resizing to larger resolutions. I had to do something more than those 2 lines of code.

But if they did scale up, I realized a potential second problem — the sprites would be artifacted and not crisp and clear. So, it’s best to create sprites that are really large and then scale them down for lower resolutions. Luckily, I use vector art, so resizing them (I used Flash to draw the images in the first place, and then used Flash to resize them 4x larger and then exported them as PNG’s) was not a problem at all.

So, I thought about the larger resolutions to support. I was at first thinking of my own device which was really small, 960×640, but it appeared to show things even smaller, at 480×320. So I resized everything to 4x larger. That means the base dimensions are now 1920×1280. And that is my baseline for all the sizes of my sprites.  1920×1280 is what is considered 100% width and 100% height.

Here are some examples of that in my code:

var GAME_WIDTH = screen.height,
 GAME_HEIGHT = screen.width,
// 1920x1280
 BASE_WIDTH = 1920,
 BASE_HEIGHT = 1280;
// add a chibi to the screen - 360x360
this.chibi = game.add.sprite(0, 0, 'chibi');
this.chibi.scale.setTo(((GAME_WIDTH/BASE_WIDTH)*360)/360, ((GAME_HEIGHT/BASE_HEIGHT)*360)/360);
this.chibi.anchor.setTo(0.5, 0.5);
this.chibi.x = GAME_WIDTH/2;
this.chibi.y = (GAME_HEIGHT/9)*4.5;
this.chibi.smoothed = true;

The actual chibi.png is 360×360. scale.setTo() considers “1” as being being “100%.”

The formula is this:

this.chibi.scale.setTo(((GAME_WIDTH/BASE_WIDTH)*BASE_CHIBI_WIDTH)/BASE_CHIBI_WIDTH, ((GAME_HEIGHT/BASE_HEIGHT)*BASE_CHIBI_HEIGHT)/BASE_CHIBI_HEIGHT);

GAME_WIDTH and GAME_HEIGHT is synonymous to the width and height of a device’s resolution (notice they are set to screen.width and screen.height above).

So if my device is 480×320, let’s try inputting the numbers:

this.chibi.scale.setTo(((480/1920)*360)/360, ((320/1280)*360)/360);

becomes

this.chibi.scale.setTo(0.25, 0.25);

which is what we want. 1/4 of 360 is 90, and that was my chibi’s size in the first place in a 480×320 screen.

The iPhone 6 is 1334×750.  Let’s input the numbers for that:

this.chibi.scale.setTo(((1334/1920)*360)/360, ((750/1280)*360)/360);

which is:

this.chibi.scale.setTo(0.6947916666666667, 0.5859375);

You’ll notice that the chibi will no longer be proportional in an iPhone 6, but that is one of the things to accept when developing for multiple devices.