Tuesday, June 21, 2016

Mobile Income Report #23 - May 2016






previous parts
  Mobile Income Report #22 - April 2016
  Mobile Income Report #21 - March 2016
  Mobile Income Report #20 - February 2016
  Mobile Income Report #19 - January 2016
  Mobile Income Report #18 - December 2015
  Mobile Income Report #17 - November 2015
  Mobile Income Report #16 - October 2015
  Mobile Income Report #15 - September 2015
  Mobile Income Report #14 - August 2015
  Mobile Income Report #13 - July 2015
  Mobile Income Report #12 - June 2015
  Mobile Income Report #11 - May 2015
  Mobile Income Report #10 - April 2015
  Mobile Income Report #9 - March 2015
  Mobile Income Report #8 - January and February 2015
  Mobile Income Report #7 - December 2014
  Mobile Income Report #6 - November 2014
  Mobile Income Report #5 - October 2014
  Mobile Income Report #4 - September 2014
  Mobile Income Report #3 - August 2014
  Mobile Income Report #2 - July 2014
  Mobile Income Report #1 - June 2014
  Apps page - Portfolio (what are my assets?)

 If you do not want to miss any of my Income Reports you can follow me on Twitter. Just click the button above.

 Under Apps page you can see my portfolio. It is list of the games that are then reported in Income Reports.


What I did in May

  • worked on endless procedural platformer runner for Gamee platform. Game is finished and I am really prod of the generator. It generates platforms in real time and the result is not looking bad. For player animation I utilized my Spriter player for Phaser:
  • continued work on "Pirates! - the match-3". We started to create final levels. For this I have built Cordova version of game for Android using Google Analytics. In the evenings we can play it and generate statistics for tuning.



Report


 Figures for mobile games are these:


 There is big decrease, compared to April, from $154,5 to $106,8. I did not investigate the reason, but number of downloads is more or less stable.

 More than 90% of income is again from ads.

 Beside this, we got some small fee for our HTML5 games - $95,3.

 This month, I did not get any income for hired work - it is shifted to June.

 Total income for May is $212,2. It is a lot less than in April ($1 391,1) because of absence of income from hired work.



Next 

 

 In June I am still working on "Pirates! - the match-3" - creating final levels and testing it. Working on another client work. We are also trying to sell licences for HTML5 version of Shards - the brickbreaker.







Friday, May 20, 2016

Mobile Income Report #22 - April 2016






previous parts
  Mobile Income Report #21 - March 2016
  Mobile Income Report #20 - February 2016
  Mobile Income Report #19 - January 2016
  Mobile Income Report #18 - December 2015
  Mobile Income Report #17 - November 2015
  Mobile Income Report #16 - October 2015
  Mobile Income Report #15 - September 2015
  Mobile Income Report #14 - August 2015
  Mobile Income Report #13 - July 2015
  Mobile Income Report #12 - June 2015
  Mobile Income Report #11 - May 2015
  Mobile Income Report #10 - April 2015
  Mobile Income Report #9 - March 2015
  Mobile Income Report #8 - January and February 2015
  Mobile Income Report #7 - December 2014
  Mobile Income Report #6 - November 2014
  Mobile Income Report #5 - October 2014
  Mobile Income Report #4 - September 2014
  Mobile Income Report #3 - August 2014
  Mobile Income Report #2 - July 2014
  Mobile Income Report #1 - June 2014
  Apps page - Portfolio (what are my assets?)

 If you do not want to miss any of my Income Reports you can follow me on Twitter. Just click the button above.

 Under Apps page you can see my portfolio. It is list of the games that are then reported in Income Reports. The portfolio is regularly updated with new information (releases for new platforms, new updates, ...)




What I did in April

  • finished HTML5 version of Shards - the brickbreaker. Game was rewritten in Phaser engine. Currently we are looking for sponsors. Shards is modern Arkanoid / Brickbreaker clone with glass bricks and glassy enemies - Shardiens. Game has 80 levels and every single one has its own fractal background:

  • finished hired HTML5 work on game Meteoric for Gamee platform. It is fast paced puzzle in which you merge asteroids into planets and planets into suns:


  • also working on our game "Pirates! - the match-3", which is, as the name says, match-3 game:



Report


 Here are April figures for mobile games:





 Income from mobile games is still quite stable ($175,8 in March) ... and low. Most profitable game remains Shards - the brickbreaker.


 Most of the income is from ads (88% in March) - share of paid apps and in-app purchases decreased.

 In April I got also some income from licences and hired work: $1 223.

 Total income for April is: $1 391,1. This is similar to February ($1 323,0) and much more than March ($175,8).




Next


 In May I am still working on "Pirates!, the match-3". This is my priority now as game is working in all direction. What we are missing are levels. We are also replacing placeholder graphics with our own as well as some static images with animations.
 I am also doing another hired work.





Sunday, April 17, 2016

Phaser tutorial: Using Spriter player for Phaser

 





Previous Phaser tutorials and articles:
Phaser tutorial: Merging fonts into sprite atlas
Phaser: Typescript defs for Phaser Box2D plugin
Phaser tutorial: Spriter Pro features added to Spriter player for Phaser
Phaser tutorial: Using Phaser signals
Phaser tutorial: Breaking the (z-order) law!
Phaser tutorial: Phaser and Spriter skeletal animation
Phaser tutorial: DronShooter - simple game in Typescript - Part 3
Phaser tutorial: DronShooter - simple game in Typescript - Part 2
Phaser tutorial: adding 9-patch image support to Phaser
Phaser tutorial: DronShooter - simple game in Typescript - Part 1
Phaser tutorial: custom easing functions for tweening and easing functions with parameters
Phaser tutorial: sprites and custom properties for atlas frames
Phaser tutorial: manage different screen sizes
Phaser tutorial: How to wrap bitmap text



Introduction


 Some time ago I published here article about Spriter player for Phaser. I made the code freely available at GitHub. Player is written in Typescript and GitHub code contained both the player and small example on how to use it in one project. I thought it would be easy for others to use it, but I was wrong - for some coders it would be better if there was separate .js file and also there was lack of information on usage. But if you want to have nice animations in your game like the parrot above, small obstacles should not discourage you!
 
 So, I made a few changes - check GitHub:
  • player itself and example are both separated from each other,
  • there is added Build folder, where you can grab either spriter.js or spriter.min.js files ready to be used in your project.
 Splitting player and example also forced creation of Typescript defs for player. It can be found in spriter.d.ts file in Build directory.


Example


 I assume you are familiar with Phaser states. On GitHub go into Test/src/States. In Preloader.ts file I am loading export from Spriter program with standard Phaser loader. Export can by either .xml (.scml) od .json (scon). I am also loading atlas with all part visual parts of animation (for test use files from assets folder):

            // load assets
            var path: string = Global.assetsPath;

            // test
            this.load.atlas("TEST", path + "Atlas.png", path + "Atlas.json");
            this.load.xml("TESTXml", path + "TEST.xml");
            this.load.json("TESTJson", path + "TEST.json");

 You will need only to load either xml or json. Both lines are here only to show both possibilities. 

 What is important, Spriter exports list of visual parts with file extension like "head.png". Spriter player cuts the extension off and uses only part name (like "head"). Some tools for making sprite atlases export names with and some without extension. Make sure, that you create atlas with names without extension.

 When your data are loaded you can move to file Test.ts, where we will use it.

 First, we will do some basic setup. Data we loaded in previous step are either .xml or .json. But we need to turn it into some structure player is familiar with. To do it there is Spriter.Loader class. This class takes Spriter.SpriteFile (which can be Spriter.SpriterXml or Spriter.Spriter.JSON) and outputs complete Spriter.Spriter data structure. Loader can process as many files as you need - you do not need to create it for every single processing. All Spriter player classes are in Spriter namespace, so I will not further write it here.

 Let's create loader:

            // create Spriter loader - class that can change Spriter file into internal structure
            var spriterLoader = new Spriter.Loader();

 Now, we will create SpriterFile that loader can proces. It is one of derived classes - SpriterXml or SproterJSON (this time I will choose JSON and leave XML commented out):

            // create Spriter file object - it wraps XML/JSON loaded with Phaser Loader
            //var spriterFile = new Spriter.SpriterXml(this.cache.getXML("TESTXml"));
            var spriterFile = new Spriter.SpriterJSON(this.cache.getJSON("TESTJson"));

 Spriter files are way how to wrap data, so single loader class can ask for information so different formats like JSON or XML in some uniform way. (By the way, there is also possibility to load special binary format through SpriterBin, but this feature is not currently working as I have to add Spriter Pro features into it.)

 In next step we will pass our spriter file to loader and in output we get "unpacked" structure with all objects needed for animation (which sprites it uses, what charmaps are available, list of entities, animations, timelines, ...). This structure is "read only" and no data are stored in it. It means you can use it for many animations running simultaneously on screen.

 In last step we will create the animation itself. For this, player has SpriterGroup object. It extends standard Phaser.Group class. So, everything you can do with Phaser.Group, you can also do with SpriterGroup (scale, rotate, blend, ...). SpriterGroup is main class of Spriter player and most of the things you will need is done through this class (create _spriterGroup variable, so you can reference your animation later):

            // create actual renderable object - it is extension of Phaser.Group
            this._spriterGroup = new Spriter.SpriterGroup(this.game, spriterData, "TEST", "Hero", 0, 100);
            this._spriterGroup.position.setTo(420, 400);

            // adds SpriterGroup to Phaser.World to appear on screen
            this.world.add(this._spriterGroup);

 To tick animation add this into update method:

        update() {
            this._spriterGroup.updateAnimation();
        }

 This is little stupid, because Phaser calls update on Phaser.Group automatically. So, if animation update was in update method of SpriterGroup and not in updateAnimation, then this call would not be needed. I will probably change it in future. Until, you have to tick your animations explicitly.

 Running the example now, you should have animated character on screen. If you used assets from test, you will see this boy:


SpriterGroup features


 As already said, main class is SpriterGroup. So, I will go through its features here. I will use Typescript syntax as it includes type information, but it should be perfectly readable also for JS developers (take it as pseudocode).

 In example above we created new SpriterGroup like this:

this._spriterGroup = new Spriter.SpriterGroup(this.game, spriterData, "TEST", "Hero", 0, 100);

 Here is what these parameters mean:

        constructor(game: Phaser.Game, spriter: Spriter, texutreKey: string, entityName: string,
            animation?: string | number, animationSpeedPercent?: number);

 You need to pass Phaser.Game like for many other Phaser gameobjects. Next you have to pass Spriter animation structure that you processed with Spriter Loader class. Third is name of atlas with visual parts of animation. Last mandatory parameter is name of entity. Spriter file can have one or more entities. When you create SpriterGroup you have to pass which entity you want to use. You can not change this later.
 If you omit animation then first animation for entity is started. Every entity has one or more animations. Animations within entity can be switched. Last parameter is speed of animation in percent. default value is 100.

 SpriterGroup can inform you on a few events. This is done through standard Phaser.Signals. Here is list of signals you can use:

        // onLoop(SpriterGroup);
        onLoop: Phaser.Signal;
        // onFinish(SpriterGroup);
        onFinish: Phaser.Signal;

        // onSound(SpriterGroup, string); // string for line name which equals soud name without extension
        onSound: Phaser.Signal;
        // onEvent(SpriterGroup, string); // string for line name which equals event name
        onEvent: Phaser.Signal;
        // onTagChange(SpriterGroup, string, boolean); // string for tag name, boolean for change (true = set / false = unset)
        onTagChange: Phaser.Signal;
        // onVariableSet(SpriterGroup, Variable); // Variable is Spriter variable def with access to value
        onVariableSet: Phaser.Signal;

  • onLoop - subscribers are notified when animation loops,
  • onFinish - if animation does not loop, subscribers are notified on finishing,
  • onSound - Spriter Pro animations can have soundline, which allows great synchronization between animation and sounds. Spriter player does not actually play sounds, but notifies subscribers when sound shall be played. Signal dispatches SpriterGroup that fired event and name of  sound to play. In this way it is just specific sound event,
  • onEvent - in this Spriter player implementation it is the same as onSound, but not sound specific. Also here, name of the event is dispatched,
  • onTagChange - tags in Spriter animation says that something is on or off. When this changes you can read it through this signal. Imagine for example starting / stopping particle rain from sky when wizard casts spell (during "castRain" tag on). In this signal you get not only name of tag, but also its on/off state in next parameter,
  • onVariableSet - Spriter Pro animations can have variables, that are set in certain points to certain values. These variables are integers, floats and strings. Current implementation does not interpolate integer and float variables. Currently, it is only set to new value. You can listen to these events when variable is set and do something with its value. You can treat it as "event with value". Here you get Variable object that holds name, type and value.

 Here are few properties you can read:

        // get loaded Spriter structure
        spriter: Spriter;
        // get Spriter entity
        entity: Entity;
        // number of animations for current entity
        animationsCount: number;
        // name of current animation
        currentAnimationName: string;

 pause can be read and set:

        // is anim paused?
        paused: boolean;

 To play or change animation, set its playing speed and to update (tick) whole SpriterGroup, use these methods:

        // set speed of animation in percent (default = 100)
        setAnimationSpeedPercent(animationSpeedPercent: number): void;
        // play animation by Spriter animation id
        playAnimationById(aAnimationId: number): void;
        // play animation by name
        playAnimationByName(aAnimationName: string): void;
        // call this on every frame to tick animation
        updateAnimation(): void;

 Next set of method allows you to work with charmaps. Charmaps are sets of alternative visuals for animation (you can replace only some visuals). These charmaps can be stacked on each other. As a result you can achieve high variability with small amount of assets. Imagine evil orc as base character and charmap for replacing club with rusty sword and another charmap for helmet.

        // add charmap on top of charmap stacky by name
        pushCharMap(charMapName: string): void;
        // remove charmap from stack by name
        removeCharMap(charMapName: string): void;
        // remove all charmaps from charmap stack
        clearCharMaps(): void;

 With last set of methods you can question tags and variables:

        // check if animation tag with given name is on or off
        isTagOn(tagName: string): boolean;
        // check if animation tag with given id is on or off
        isTagOnById(tagId: number): boolean;
        // get animation variable by name
        getVariable(varName: string): Variable;
        // get animation variable by id
        getVariableById(varId: number): Variable;
        // get Spriter object by name - Spriter object contain actual Phaser.Sprite
        getObject(objectName: string): SpriterObject;


Conclusion


 I hope this tutorial helped to clarify some point, that were not clear before. Using Spriter animation as just another Phaser gameobject should be convenient. More, you can use all Phaser.Group methods with it.
















Mobile Income Report #21 - March 2016






previous parts
  Mobile Income Report #20 - February 2016
  Mobile Income Report #19 - January 2016
  Mobile Income Report #18 - December 2015
  Mobile Income Report #17 - November 2015
  Mobile Income Report #16 - October 2015
  Mobile Income Report #15 - September 2015
  Mobile Income Report #14 - August 2015
  Mobile Income Report #13 - July 2015
  Mobile Income Report #12 - June 2015
  Mobile Income Report #11 - May 2015
  Mobile Income Report #10 - April 2015
  Mobile Income Report #9 - March 2015
  Mobile Income Report #8 - January and February 2015
  Mobile Income Report #7 - December 2014
  Mobile Income Report #6 - November 2014
  Mobile Income Report #5 - October 2014
  Mobile Income Report #4 - September 2014
  Mobile Income Report #3 - August 2014
  Mobile Income Report #2 - July 2014
  Mobile Income Report #1 - June 2014
  Apps page - Portfolio (what are my assets?)

 If you do not want to miss any of my Income Reports you can follow me on Twitter. Just click the button above.

 Under Apps page you can see my portfolio. It is list of the games that are then reported in Income Reports. The portfolio is regularly updated with new information (releases for new platforms, new updates, ...)



What I did in March

  • in the very beginning of March I published Typescript defs for Phaser Box2D plugin at GitHub,
  • I wrote another Phaser tutorial - how to merge fonts generated with Kvazar's Littera or other program for generating fonts into your sprite atlas and thus decrease number of draw calls,
  • continued work on "Pirates!, the match3" game. Tomas Kopecky painted some new sprites, so we are removing placeholders and finishing individual parts of game. Game has really lot of different tasks for players. On first image below you can see digging treasures from sand. On second image, there is another test level with web stick gems.
  •  in March I also started conversion of our game Shards - the brickbreaker, which was originally for Android / iOS, into HTML5. I am using Phaser Box2D plugin. Currently, most of it is finished. Following screenshots are from actual version:
  •  finished some hired work on small HTML5 game.



Report


 Here are March figures for mobile games:

 Income is more or less stable from January: $173,3 - $166,0 - $175,8. Most profitable game remains Shards - the brickbreaker.

 Also structure of income is stable - most of the income is from ads.

 I had no other income this month from HTML5 licences nor hired HTML5 work.

 Total income for March is: $175,8. It is decrease compared to February ($1 323,0). But I am expecting some income from hired work I finished and we also have "frozen" income in our current work: Pirates!, the match3 and Shards - the brickbreaker.



Next


 In April I am working further on our game "Pirates!, the match-3" and finishing Shards - the brickbreaker. I am still slowly experimenting with Unity and learning WPF.






Sunday, March 20, 2016

Mobile Income Report #20 - February 2016






previous parts
  Mobile Income Report #19 - January 2016
  Mobile Income Report #18 - December 2015
  Mobile Income Report #17 - November 2015
  Mobile Income Report #16 - October 2015
  Mobile Income Report #15 - September 2015
  Mobile Income Report #14 - August 2015
  Mobile Income Report #13 - July 2015
  Mobile Income Report #12 - June 2015
  Mobile Income Report #11 - May 2015
  Mobile Income Report #10 - April 2015
  Mobile Income Report #9 - March 2015
  Mobile Income Report #8 - January and February 2015
  Mobile Income Report #7 - December 2014
  Mobile Income Report #6 - November 2014
  Mobile Income Report #5 - October 2014
  Mobile Income Report #4 - September 2014
  Mobile Income Report #3 - August 2014
  Mobile Income Report #2 - July 2014
  Mobile Income Report #1 - June 2014
  Apps page - Portfolio (what are my assets?)

 If you do not want to miss any of my Income Reports you can follow me on Twitter. Just click the button above.

 Under Apps page you can see my portfolio. It is list of the games that are then reported in Income Reports. The portfolio is regularly updated with new information (releases for new platforms, new updates, ...)



What I did in February

  • worked on our game "Pirates!, the match-3". In February I did only small changes as I was mainly updating Spriter player for Phaser, which the game uses,
  • big update of Spriter player for Phaser. Most of the Pro features is now supported, including character maps, events, tags, variables, sounds. See live demo here,
  • in the end of  2015 I purchased Phaser Box2D plugin. As it is missing Typescript defs, I decided to make mine. In the very beginning of March I put result on public GitHub repository (short post here),
  • did another hired HTML5 work on fast paced puzzle game.
 



Report


 Here is February table with income from mobile games:



  Income remains more or less stable ($173,3 in January). As in previous months, the most profitable game is still Shards - the brickbreaker (iOS, Android).




 Most of the income came from ads (85%), which decreased a little compared to January (90%). Futoshiki (iOS, Android) game has very low download rate (2-3 downloads a day). But it has good conversion rate - looks like people who enjoy Futoshiki puzzle appreciate built in puzzle generator and are willing to pay for unlocking unlimited number of puzzles. And it also has better visual presentation than other Futoshiki games in my opinion.

 Beside income from mobile games I got some money for HTML5 hired work ($1 157).

 Total income for February for mobile games and HTML5 hired work is: $166,0 +$1 157,0 = $1 323,0. It is increase compared to January ($1 128,9) by 17%.




Next


 In March I am continuing in some hired work and also on our game "Pirates!, the match-3". Beside this I am playing with Phaser Box2D plugin. And finally, I am still experimenting with Unity and learinig WPF.





Thursday, March 17, 2016

Phaser tutorial: Merging fonts into sprite atlas

 





Previous Phaser tutorials and articles:
Phaser: Typescript defs for Phaser Box2D plugin
Phaser tutorial: Spriter Pro features added to Spriter player for Phaser
Phaser tutorial: Using Phaser signals
Phaser tutorial: Breaking the (z-order) law!
Phaser tutorial: Phaser and Spriter skeletal animation
Phaser tutorial: DronShooter - simple game in Typescript - Part 3
Phaser tutorial: DronShooter - simple game in Typescript - Part 2
Phaser tutorial: adding 9-patch image support to Phaser
Phaser tutorial: DronShooter - simple game in Typescript - Part 1
Phaser tutorial: custom easing functions for tweening and easing functions with parameters
Phaser tutorial: sprites and custom properties for atlas frames
Phaser tutorial: manage different screen sizes
Phaser tutorial: How to wrap bitmap text


Introduction


 Everybody with at least short experience in game development came across sprite atlases. Its benefits are in merging multiple sprites into one large bitmap and so decreasing draw calls. We can simplify draw call as request to GPU to draw something with some set of parameters. One of these parameters is also texture. Changing any of parameters results into quite expensive setup on GPU side (flushing current work and doing setup for different set of parameters) - this is reason why to build larger textures made from individual sprites.
 Currently there is lot of tools, that help you with creating sprite atlas from individual sprites. But, when it comes to fonts, the situation starts to get complicated.

 For creating fonts I am using on-line tool Littera. This tool is great, but when you are exporting your font, you already get some atlas that contains your font characters. Alongside, you get file with characters metadata saying where in atlas is character positioned, how big it is, ... 
 Export from Littera can look like this:


 With metadata like this:

<font>
  <info face="MapNormal" size="40" bold="0" italic="0" charset="" unicode="" stretchH="100" smooth="1" aa="1" padding="2,2,2,2" spacing="0,0" outline="0"/>
  <common lineHeight="75" base="24" scaleW="42" scaleH="252" pages="1" packed="0"/>
  <pages>
    <page id="0" file="MapNormal.png"/>
  </pages>
  <chars count="10">
    <char id="48" x="2" y="2" width="18" height="24" xoffset="2" yoffset="3" xadvance="19" page="0" chnl="15"/>
    <char id="49" x="2" y="28" width="15" height="24" xoffset="0" yoffset="3" xadvance="13" page="0" chnl="15"/>
    <char id="50" x="2" y="54" width="21" height="25" xoffset="0" yoffset="2" xadvance="19" page="0" chnl="15"/>
    <char id="51" x="22" y="2" width="18" height="26" xoffset="1" yoffset="1" xadvance="17" page="0" chnl="15"/>
    <char id="52" x="2" y="81" width="20" height="25" xoffset="2" yoffset="3" xadvance="18" page="0" chnl="15"/>
    <char id="53" x="2" y="108" width="18" height="25" xoffset="1" yoffset="2" xadvance="16" page="0" chnl="15"/>
    <char id="54" x="2" y="135" width="20" height="27" xoffset="1" yoffset="0" xadvance="18" page="0" chnl="15"/>
    <char id="55" x="2" y="164" width="19" height="26" xoffset="1" yoffset="2" xadvance="12" page="0" chnl="15"/>
    <char id="56" x="2" y="192" width="19" height="28" xoffset="1" yoffset="1" xadvance="16" page="0" chnl="15"/>
    <char id="57" x="2" y="222" width="19" height="28" xoffset="1" yoffset="3" xadvance="18" page="0" chnl="15"/>
    <char id="32" x="0" y="0" width="0" height="0" xoffset="1" yoffset="3" xadvance="11" page="0" chnl="15"/>
  </chars>
  <kernings count="0"/>
</font>


 

Problem


 So, let's have some sprite atlas and above font created in Littera. Let's also imagine we have some object, that is made from sprites and text. This is exactly what map screen with map spots is in our upcoming game Pirates! - the match three game (graphics is made by Tomáš Kopecký):


 Every single map spot is object made from sprites and text (level number). Scene graph for it looks like this:


 Map has 65 level spots and drawing it takes 136 draw calls. 130 (65 * 2) of them is for map spots. It is very bad, but it is impact of switching between atlas with sprites and atlas with fonts. On above picture it is clear, that every time renderer renders single map spot, it has to switch texture twice.

 What we need is somehow merge font into our sprite atlas and keep valid font metadata. Then we will get rid of that texture switching and we will be able to decrease draw calls.


 

Solution


 Long time ago I made tool for creating sprite atlases. It is very old and it has messy code inside, not too good GUI and also name is messy - I call it sometimes PicOpt and more recently Spritor. Anyway, it has some nice features and I used it for all games I made. You can get it for free here. One of these nice features is, that it can do what we need. So, download it and follow next steps:

 Open Spritor tool and pres Ctrl+N to create new project. Give it name (it is not saved, it only created new project):
 

 Press Ctrl+A to add some sprites (individual .png images):


 Your screen should look similar to this:


 Now, pres Ctrl+A again and open you Littera font atlas. You need to have Littera .xml/.fnt file in the same directory. Also, do not forget to check "Is font" in bottom of dialog window:


 This will add Littera font atlas into your project. It will read through Littera metadata in .xml/.fnt and cut Littera font atlas into individual sprites. The role of metadata is not finished yet. It will play important role once again during export. You can now select type of export. To have one compatible with TexturePacker export, select format in top bar as this:


 (Btw, export just one line below ("JSON - TP + Properties") is adding custom properties, that you can add to your sprites in Spritor tool, into final export). You can now save your project by pressing Ctrl+S.

 It's time to make atlas. Go to menu and select Optimize -> Best Place:
 

 After some short time for optimiaztion, there will be created folder with name "export" and you will find several files there:
  • your atlas image,
  • your atlas metadata (in TexturePacker format),
  • one Littera metadata file (.xml or .fnt) for every font you merged into atlas. This file already has all character specs adjusted to positions in new atlas.
 This is how atlas from our walkthrough looks like:


Not finished yet - Phaser part


 As we have our assets ready, we can load it into Phaser and see what happes.

 Normally, you would load your font and atlas in preload method with code like:

this.load.atlas("Atlas", "assets/Atlas.png", "assets/Atlas.json");
this.load.bitmapFont("Font", "assets/Font.png", "assets/Font.xml");

 But in our case we already have fonts merged into atlas, so we do not need to load "Font.png" file. So, we will first change this to:

this.load.atlas("Atlas", "assets/Atlas.png", "assets/Atlas.json");
this.load.xml("Font", "assets/Font.xml");

 Then, when assets are loaded, in create method we have to build our font from loaded atlas and xml metadata. At first, it looks like easy task:

this.cache.addBitmapFont("MyFont", null, this.cache.getImage("Atlas"), this.cache.getXML("Font"), "xml");

 If you do above and run your game, You will see, that you can use "MyFont" in your game. It is taking characters from atlas, that is common with other sprites, but number of draw calls did not decreased! Something went wrong.

 Let's look into Phaser source. Method for addBitmapFont has this in the beginning:

    addBitmapFont: function (key, url, data, atlasData, atlasType, xSpacing, ySpacing) {

        var obj = {
            url: url,
            data: data,
            font: null,
            base: new PIXI.BaseTexture(data)
        };
           :
           :
           :

 And if we dive a little bit deeper into PIXI.WebGLSpriteBatch.prototype.flush() method we find this (shortened and lots of code omitted for clarity):

              :
              :
            nextTexture = sprite.texture.baseTexture;
              :
              :
        if ((currentBaseTexture !== nextTexture && !nextTexture.skipRender) || blendSwap || shaderSwap)
        {
            this.renderBatch(currentBaseTexture, batchSize, start);
              :
              :

 Batches are flushed based not on underlaying atlas image, but on baseTexture. As we have one atlas we have to achieve somehow to have the same baseTexture for atlas as well as for font. For this we will create our custom method that will add functionality to Phaser Cache class. Let's call it addBitmapFontFromImage. Code for it is mostly copy of original addBitmapFont:

module Utils {

    export class PhaserUtils {

        // -------------------------------------------------------------------------
        public static AddBitmapFontAddMethod(): void {

            Phaser.Cache.prototype["addBitmapFontFromImage"] = function addBitmapFont(key: string, url: string,
                imageName: string, atlasData: any, atlasType: string, xSpacing?: number, ySpacing?: number): void {

                var img = this.getImage(imageName, true);

                var obj = {
                    url: url,
                    data: img.data,
                    font: null,
                    base: img.base
                };

                if (xSpacing === undefined) { xSpacing = 0; }
                if (ySpacing === undefined) { ySpacing = 0; }

                if (atlasType === 'json') {
                    obj.font = Phaser.LoaderParser.jsonBitmapFont(atlasData, obj.base, xSpacing, ySpacing);
                }
                else {
                    obj.font = Phaser.LoaderParser.xmlBitmapFont(atlasData, obj.base, xSpacing, ySpacing);
                }

                this._cache.bitmapFont[key] = obj;

                this._resolveURL(url, obj);
            }
        }
    }
}

 Our new method is wrapped in special PhaserUtils class. Btw, I have this class filled with other small engine tweaks and in the very beginning of the game I call one or more static methods to apply these tweaks. You have to do the same - do it before you create game object!:

Utils.PhaserUtils.AddBitmapFontAddMethod();

 Now, replace line for creating font in create method with call to our new method:

this.cache["addBitmapFontFromImage"]("MyFont", null, "Atlas", this.cache.getXML("Font"), "xml");

 Call is using square brackets as we did not add our method into phaser.d.ts file. If you used standard call, you would get Typescript complaints.

 If you run your game now, you should see that number of draw calls decreased. In my case it went down from 136 to 6!!!


 

 Conclusion


 In our game we have in fact three different fonts for map spots - depends on whether spot is normal, finished, special battle spot... All three fonts contain only numbers. Instead of having three font atlases and one for sprites, we have only one for everything.
 This helps us to save resources, reduce draw calls and as the process of creating atlas is easy we do not get any overhead.