Some background

A few months ago I blogged about TypeScript on production. In the post I talked about my first experience with TypeScript and how we integrated it into an existing pure JavaScript project.

Many people are starting to get interested in TypeScript and are asking (with some fear) questions, and how can they benefit from moving to TypeScript. So I've decided to blog about it, so everyone can gain.



What’s going on today

According to Wikipedia, EcmaScript 6 specifications are planned for Dec. 2014. FireFox has already implemented many of the features, Chrome are pushing hard too, we have Node Harmony, and even IE11 already implemented the Let, Set, Map and much more.
So things are looking good, and will be much better in the near future. But till then we have TypeScript (Version 1.0 was released not long ago)



Why would you want Types?

If you write your code with tests (and you should), you probably know the feeling when a test fails. “Yeah, I didn't do that right; I should have sent this object and not that one.” It’s a very human thing to make mistakes, and the tests help you find them before you even run your code.

The same goes for Type Safe coding. It is actually a test that needs to pass before you run your code. If you told the test that a function must receive 2 string parameters, any call to this function should fail if it didn’t do that. That’s what happens in the compilation of TypeScript code.

Besides testing your code types, TypeScript provides many more features like classes, interfaces, generics, arrow functions and much more. All these features are planned in ES6 and are implemented in TypeScript, so once the world is ES6, you are too.



"Classes and Interfaces, Ugh!"

You may argue that Classes and Interfaces and bad things, and you are very comfortable with the module pattern. This is great and you can keep doing that, TypeScript does NOT force you to do Classes and Interfaces! 

In my mind, there are some situations that classes and interfaces are very welcome, and should be used, and there are places that functional programming is the right thing to do. choose your style.


"I hate generated code"

Me too! most of the debugging that I do, I do it on the browser.
The TypeScript generated code is very similar to the code that you write, with some additions.
The types are omitted, the names of the variables, functions, and modules remain the same, your comments are still there, so you will have no problem debugging TypeScript generated code. Belive me, I've been doing for this for the past year with no problems at all.


Remember: ANY existing JavaScript code is a valid TypeScript code.

3 Baby steps

Types:

If you're a JavaScript developer who enjoy the freedom of the language, keep doing that! TypeScript will not do anything to your code – nothing!
But, if you find a place that you want to be more strict – for example, specify a function parameter type as string – TypeScript will help you enforce that, just like a test. And after the compilation, all the type definitions are removed and your code will be as it would have without TypeScript. You just added a test.



Modules:

The next step I would suggest is to start using modules. The Module Pattern is well known in the JavaScript world, and many developers are using it to namespace their code and hide code that they consider private.
TypeScript implemented the module pattern and it’s very easy to use. It’s a much more organized code, and it’s loadable using commonjs or AMD .



Arrow functions:

In pure JavaScript, you have to make sure that “this” is the right ”this” all the time. Callbacks from events will have the caller’s “this” and not the callback owner. To solve this issue, people use “that” or “_this” and there’s the “bind” and “unbind.”
Those days are over. From now on you should use the arrow function; it will generate the “_this” behind the scenes for you (you can see that on the generated js files).

For starters, this is more than enough to get you started and get your feet wet. So I’m not going to talk about classes, interfaces, generics, and all the other great stuff… :-)


Before you start

  • Use Grunt to compile your code, I would suggest using grunt-ts as it has more features over the grunt-typescript task.
  • DefinitelyTyped is a great repository for type definitions for existing libraries like AngularJS, JQuery, or anything you can think of.
  • WebStorm and VisualStudio are the best IDEs for TypeScript, but if you don't like it, be sure that your current IDE supports TypeScript.
  • Like all Compile-to-JavaScript compilers, TypeScript offers source maps to be used for debugging your original code.
  • You can play with TypeScript here
  • ES6 is a great language for small, medium, and mostly large apps. Read about it; after all, it’s coming soon, and you don't want to be left behind.


Traceur (By Google)

Traceur is yet another Compile-to-JavaScript, with more features implemented vs TypeScript. It aims to be exactly aligned with ES6 specs. But types are experimental feature (for now), And it can compile your code at run-time (Just like a browser would).
The only downside that I see is the generated code, it looks very complicated and I guess that with Traceur you must use source maps to debug your code.


Notes:

Not all the features are implemented in TypeScript just because they don't want to generate a complicated js file (Like you see in Traceur), for example: the Let command was not implemented because it meant inner scope and variable duplication. But the current version has many features implemented, and it’s more than enough to get your feet wet in the ES6 world.

Emanuele Feronato, a well known Flash/Html PROgrammer posted in his blog "Managing multiple iOS resolutions with Starling – real world example" (Part1, Part2)
Emanuele's solution (Many people use the same solution) was to check what is the device and load the right texture, use "Magic Numbers" to place the texture on the screen, and we have a working UI...

The problems

  • You can support a limited number of resolutions, Android has many.
  • You need to refactor your code for a new device.
  • It's very hard to maintain code with "Magic Number"
  • You are embedding all the resolutions that you support, may results in a very large app.

DMT to the rescue

  • Much smaller (No embedded Pngs, only one SWC) 
  • Will fit ANY device resolution (Even TV).
  • Easy to maintain and refactor, even redesign.
So I took the Circle Chain UI, and made everything using DMT, the full source code (FlashBuilder project) is on gitHub.

The project uses two classes, the UILayout.as to build the UI relative to the device width and height. And GameWithDMT.as which uses DMT to rasterize the UILayout result, and animate it just like Emanuele did in the original post.

UILayout.as

package
{
 import flash.display.Sprite;
 
 public class UILayout
 {
  public var UIContainer:Sprite;

  private var deviceWidth:Number;
  private var deviceHeight:Number;

  private var gameTitle:Sprite;
  private var mainBG:Sprite;
  private var gridEdition:Sprite;

  public function UILayout(deviceWidth:Number, deviceHeight:Number)
  {
   this.deviceWidth = deviceWidth; 
   this.deviceHeight = deviceHeight;
   
   // This class will build and layout the Vector assets according to the give device width and height
   // The result of the layout will be at the UIContainer Sprite (Flash Sprite with Vectors children, no artifacts)
   UIContainer=new Sprite();
   
   createBackground();
   createGameTitle();
   createGridEdition();
   createButtons();
  }
  
  private function createBackground():void {
   mainBG=new MainBG();
   mainBG.name = "MainBG";
   mainBG.width = deviceWidth;
   mainBG.height = deviceHeight;
   UIContainer.addChild(mainBG);
  }
  
  private function createGameTitle():void {
   gameTitle=new GameTitle();
   gameTitle.name = "gameTitle";
   gameTitle.width = deviceWidth*0.65; // will take 65% of the screen width
   gameTitle.scaleY = gameTitle.scaleX; // keep the same aspect ratio
   gameTitle.x=(deviceWidth-gameTitle.width)/2; // center it
   gameTitle.y=deviceHeight*0.2; // 20% of the screen height
   UIContainer.addChild(gameTitle);
  }
  
  private function createGridEdition():void {
   gridEdition=new GridEdition();
   gridEdition.name = "gridEdition";
   gridEdition.height = gameTitle.height*0.25; // make it 25% of the game title
   gridEdition.scaleX = gridEdition.scaleY; // keep the same aspect ratio
   gridEdition.y=gameTitle.y+gameTitle.height*1.1;
   gridEdition.x=gameTitle.x+gameTitle.width-gridEdition.width; // align to the right of the gameTitle
   UIContainer.addChild(gridEdition);
  }
  
  private function createButtons():void {
   var normalMode:Sprite=new NormalMode();
   normalMode.name = "normalMode";
   normalMode.height = gameTitle.height*0.25; // 25% of the game title height
   normalMode.scaleX = normalMode.scaleY; // keep the same aspect ratio

   UIContainer.addChild(normalMode);
   normalMode.x=(deviceWidth-normalMode.width)/2;
   normalMode.y=deviceHeight*0.5; // 50% of the screen height

   var timeAttackMode:Sprite=new TimeAttackMode();
   timeAttackMode.name = "timeAttackMode";
   timeAttackMode.height = gameTitle.height*0.25; // 25% of the game title height
   timeAttackMode.scaleX = timeAttackMode.scaleY; // keep the same aspect ratio

   UIContainer.addChild(timeAttackMode);
   timeAttackMode.x=(deviceWidth-timeAttackMode.width)/2;
   timeAttackMode.y=deviceHeight*0.65; // 65% of the screen height
  }

  
 }
}

GameWithDMT.as

package {
 
 import com.xtdstudios.DMT.DMTBasic;
 
 import flash.events.Event;
 
 import starling.animation.Tween;
 import starling.core.Starling;
 import starling.display.DisplayObject;
 import starling.display.Sprite;
 
 public class GameWithDMT extends Sprite {
  private var _dmtBasic     : DMTBasic;
  private var starlingUIContainer : Sprite;
  
  public function GameWithDMT() {
   _dmtBasic = new DMTBasic("DMTCircleChain", false); // change to "true" to turn ON caching
   _dmtBasic.addEventListener(Event.COMPLETE, dmtComplete);
   if (_dmtBasic.cacheExist() == true)
    _dmtBasic.process(); // will use the existing cache
   else
    doLayoutUI(); // will be done one time per device  
  }
  
  private function doLayoutUI():void {
   var uiLayout: UILayout = new UILayout(Starling.current.nativeStage.stageWidth, Starling.current.nativeStage.stageHeight);
   uiLayout.UIContainer.name = "UIContainer"; // name it so we can ask DMT for it
   _dmtBasic.addItemToRaster(uiLayout.UIContainer);
   _dmtBasic.process(); // will rasterize the given assets  
  }
  
  protected function dmtComplete(event:Event):void {
   starlingUIContainer = _dmtBasic.getAssetByUniqueAlias("UIContainer") as starling.display.Sprite;
   addChild(starlingUIContainer);

   // animate
   var gameTitle    : DisplayObject = starlingUIContainer.getChildByName("gameTitle");
   var gridEdition   : DisplayObject = starlingUIContainer.getChildByName("gridEdition");
   var normalMode    : DisplayObject = starlingUIContainer.getChildByName("normalMode");
   var timeAttackMode   : DisplayObject = starlingUIContainer.getChildByName("timeAttackMode");
   var gameTitleTween  : Tween=new Tween(gameTitle, 0.7);
   var gridEditionTween : Tween=new Tween(gridEdition, 0.7);
   var normalModeTween  : Tween=new Tween(normalMode, 0.7);
   var timeAttackModeTween : Tween=new Tween(timeAttackMode, 0.7);
   var gameTitleY    : Number;
   var gridEditionX   : Number;
   
   // save final postion
   gameTitleY = gameTitle.y;
   gridEditionX = gridEdition.x;
   
   // starting position/alpha
   gameTitle.y = -100;
   gridEdition.x = starlingUIContainer.width;
   normalMode.alpha = 0;
   timeAttackMode.alpha = 0;
   
   gameTitleTween.moveTo(gameTitle.x, gameTitleY);
   gridEditionTween.moveTo(gridEditionX, gridEdition.y);
   gridEditionTween.delay = 0.7;
   normalModeTween.fadeTo(1);
   normalModeTween.delay = 0.7+0.7;
   timeAttackModeTween.fadeTo(1);
   timeAttackModeTween.delay = 0.7+0.7+0.2;
   Starling.juggler.add(gameTitleTween);
   Starling.juggler.add(gridEditionTween);
   Starling.juggler.add(normalModeTween);
   Starling.juggler.add(timeAttackModeTween);
  }
 }
}

What's going on today?

The current version of JavaScript that you see in most modern browsers uses the ECMAScript 5 standard. The next version, ECMAScript 6, is still not determined, and is still under development.

ECMAScript 6 is supposed to include many of the missing features such as classes, modules, iterators for for/of loops, arrow functions, collections and more! These features will allow developers write big and complex applications with JavaScript.

Even after the specifications will be released, it will take some time until it will be available to the majority of the public's browsers. This means that if you want to develop a web-app or just write something for the web, you must use ECMAScript 5 standard.

Today, companies that develop big and complex web apps with more than a few developers must find a way to handle huge amount of prototype-based, un-typed, fragile code. The more code/developers you have in your project, the unhappier you will be with pure JavaScript.

There are many solutions out there: some build their own in-house class framework, some use open-source class frameworks. Also, there are the new languages like Dart, CoffeeScript, Haxe, and many more, and now TypeScript.


What is TypeScript

TypeScript is another JavaScript replacement; actually it's a super-set of JavaScript, and it extends the current JavaScript. This means that you can still write JavaScript code inside TypeScript code, and it will compile with no problems (yes, you have to compile your code)

So, the basic idea behind TypeScript is that it is ECMAScript 6 compatible, while supporting the current version ECMAScript 5. This is the biggest benefit that it has over the other JavaScript replacement languages.


Pros

  • Compile time type-checking (Dynamic typing).
  • Classes and Interfaces, function visibility, and all the benefits of inheritance.
  • Modules.
  • Generics.
  • Intellisense, code completion and refactoring.
  • Definitions for existing libraries.
  • Output human readable JavaScript code.
  • Compatible with the current JavaScript!
  • Open-Source (Apache 2).
All the pros we have with TypeScript are huge time savers for existing JavaScript developers, and TypeScript is very welcoming for existing Java, C#, C++ developers.
You can actually take your current JavaScript code and add TypeScript to it with no problems, do the migration slowly, and only to the parts you select.


Cons

  • No packages, only modules.
  • Compilation time.
  • Debug code that you didn't write (you can use maps).
  • Type safety will never be part of the ECMAScript specs. so you'll always have to stay with TypeScript, if you want Type safety.
The most problematic issue is the modules; the other cons are easily acceptable. A developer coming from Java or C# is used to the package model; TypeScript uses the modules pattern, a different way to scope your code. ECMAScript 6 will use modules and not packages (TypeScript follows this concept) and modules are good for loading parts of your code on demand (look at AMD).


Before TypeScript

Our project was constructed with a Java back-end, and a single page application, JavaScript/HTML.
We didn't build an in-house JavaScript class framework, nor use an external class framework; we used a pure prototype inheritance approach. (Yuck)
We decided to go that way to save time and get the product out as soon as was possible, we had to prove the need for this product.
These days we "pay" for the "speedy" development, with hard refactoring (if we dare), and new features are not being implemented so fast anymore... But it was taken into account, and now we have some time to build things right.

The JavaScript frameworks that we did use were JQuery, JQueryUI, and HandleBars a very minor setup according to web-apps standards these days.

Now that we know for sure that our product is worth the effort. We started thinking on how to do the refactoring without harming existing code.

This is where TypeScript came into the picture.


The beginning of the transition

First we started using Node and Grunt to do the minifying of the code and CSS (First versions were not even minified!). We've also added tests with Karma.

When we felt more up-to-date with the world of Front End Developers, we decided to try out TypeScript, mostly because of all its features and its ability to assimilate into existing JavaScript projects with ease.

I started by taking existing parts of our code (BI Manager) and rewrote it in TypeScript. This gave me a feeling of the language and the workflow.


Working with TypeScript

IDE

The first thing that was important is the IDE. We use IntelliJ IDEA, and we were lucky to find out that the latest version (12.1.4) supports TypeScript code. I gave it a try.
After some minor configurations, I managed to compile TypeScript code on save of files, with errors and hints on the code. Intellisense and code completion works great!
If you don't use IntelliJ, you should consider Visual Studio, as they integrated TypeScript very well.

Code Generation

The language itself (as you can imagine) was quite a surprise! All the language features are being translated into the JavaScript prototype perfectly. The generated code is totally readable, and debuggable. I even decided to debug only the generated JavaScript code, and not use source maps. It was surprisingly easy; I sometimes didn't even remember that I was looking at a generated code. It felt like my own code; it was not one to one, but was very familiar.

Refactoring

IntelliJ can help refactor your TypeScript code, but it is not something that I would currently use. Any class variable should be accessed using the ‘this’ keyword. When using refactoring with IntelliJ, it will remove the ‘this’ from all the refactored items. I guess that it will be fixed soon.
Again, I know that Visual Studio is doing great job in the refactoring area.

External references

When you change a TypeScript code and save it, your IntelliJ watcher will detect that, and will compile the code on the fly. Sometimes you can change a code that is being referenced by other modules, you can break the code without knowing. These modules should also get compiled, and any errors caused by your change should be raised at the time of your change. This does not happen as of today.
The obvious solution is to detect errors on the full project compilation.

Working with existing libraries

When working with existing code or libraries you should have a definitions file, a file that defines the interface to existing code that was written in JavaScript. This can be your legacy code, or an open-source code like JQuery that was written in JavaScript.
You can find more than 90% of all the common libraries definition files at DefinitelyTyped.


The project

I'm working at Wix.com, [THE best website builder e-v-e-r :-)]
I'm on the eCommerce team, and we build the store manager. The next thing planned was the Orders Tab. After "playing" with TypeScript on the BIManager (a closed module in our system), we decided to go for TypeScript and build the Orders Tab with it.

Here's the product design, done by our UX team:




This tab is isolated (in logic too) from the other tabs, so doing a separate module in TypeScript was not a scary thing; at any time we could just take the generated code and continue from there.

I have decided to go a bit bigger and go full MVC structure, while still using the existing JQuery and HandleBars libraries.


The code structure

EventDispatcher

To achieve working MVC pattern you should have an EventDispatcher (observer pattern) in your arsenal.
Coming for AS3 and Flash, I've have decided to implement the EventDispatcher in TypeScript. This was very straightforward and easy to implement.

MVC

The Model is pure TypeScript code which dispatched Change events.
The View is generated using HandleBars, and the Controller uses the view and notifies the model, nothing special here.
It was very easy to implement it using Classes and Interfaces. The language was flawless, and I was thinking about the logic and not on how not to mess things up, a feeling that I always had when developing with pure JavaScript.
I know that I could use BackBoneJS or any other MVC framework (all the TypeScript definition files are available online), but we didn't use them in the JavaScript code, so I didn't want to use something new while coding in a new language. Next time, this is definitely a valid option.


The result

The result was surprisingly similar to the design that was given to me, and I was quite happy with the result. But this has nothing to do with TypeScript, this could be achieved in any language.
The most notable thing that was achieved here is that I now feel that there's a real and working solution for medium/big web-app projects!
Developing the same project using JavaScript would have taken much more time, I'd say up to two times as much time!


The near future

First of all, we want to progress a bit more regarding the frameworks that we use and tryout AngularJS or EmberJS (I'll probably blog about it).
I will investigate the Modules a bit more and see how we can use AMD in our project.
There are some new features in TypeScript 0.9 like Generics that I want to investigate and get to know better.
Besides me, the rest of the team is learning TypeScript, reviewing the code, fixing bugs, and even writing new code with it.


Conclusion

TypeScript is a refreshing change from all the problems of the old JavaScript: you can count on TypeScript for your next project, as well as existing projects. It worked well, and it is still working well, and I don't see any good reason for going back to JavaScript anymore.

There are still some minor issues with the IDE, but this has nothing to do with the language itself. Things are looking great for this language.

Using TypeScript is writing with the future-web-language today!

Full source code for the example project is on gitHub.

What is DMT?

In short, DMT will lets create texture atlases from vector based assets at run-time.
I'll show you a very simple example on how to do that, and what are the benefits of DMT.
Next time we'll talk about Dimethyltryptamine, for now let's do some code :-)


Creating a project

For this example we'll use Flash-Builder 4.7, but this can be done with any other IDE.

Create an ActionScript Mobile AIR Project, name it HelloDMT. You can also use Desktop AIR, it doesn't really matters, as long as you use AIR. AIR is important here because the basic DMT API uses the file-system to save the texture atlases and some more data. To use DMT on pure Flash projects you'll have to use a more advance DMT API.


Basic Starling setup

Lets create a very basic Starling app.
  • First include Starling.swc in your project (Download from here)
  • Edit the HelloDMT.xml, and set the renderMode to direct. To be able to use the Stage3D.
  • Create your Starling main class, Main.as (Inherit from starling.display.Sprite)
  • And on HelloDMT.as use this code:
package
{
 import flash.display.Sprite;
 import flash.display.StageAlign;
 import flash.display.StageScaleMode;
 
 import starling.core.Starling;
 
 public class HelloDMT extends Sprite
 {
  private var m_starling:Starling;
  
  public function HelloDMT()
  {
   super();
   
   stage.align = StageAlign.TOP_LEFT;
   stage.scaleMode = StageScaleMode.NO_SCALE;
   
   Starling.multitouchEnabled = true;
   Starling.handleLostContext = true;
   
   // initialize Starling
   m_starling = new Starling(Main, stage);
   m_starling.simulateMultitouch  = false;
   m_starling.start();
  }
 }
}

Vector Assets

Most artists create their vector game/app assets in Flash or Illustrator. To be able to use these assets, you must give it a linkage name, so we will be able to create it on run-time.
In our example we will use a simple Square, Triangle, and Circle assets that I've created, as you can see they all share the same LeftEye and RightEye assets (Download swf or fla).
The library looks like this:


Create assets folder under the main project and put the HelloDMT-Assets.swf in that folder, so we can embed it in our project.


The DMT library

Clone the code from gitHub, or just download it.
On the main directory you can see 4 folders:
  1. libs: This contains the Starling.swc, and XTDCommon.swc. Starling you should know, and XTDCommon is another open-source library (gitHub) with some useful utilities (You'll see soon)
  2. Samples: This folder contains an example project with the examples of the DMT library.
  3. DMT: This is the full source-code of the library.
  4. swc: Contains the compiled swc, in case you don't want to include the code in your project.
Copy the DMT.swc & XTDCommon.swc to your project, and include it just like you did with Starling.swc.
Your project tree should look like this:



Loading the assets

Before we can start using our assets, we must load them into our Application Domain.
There are few ways to load swf assets into your application domain. You can load from external file, remote url, or embed the swf. In our example we'll embed the swf and load it into our application domain, so we can create our three assets.
  [Embed(source="/../assets/HelloDMT-Assets.swf", mimeType="application/octet-stream")] 
  private var AllAssetsClass:Class;


To load the embedded assets into our application domain we'll use a utility class named AssetsLoaderFromByteArray, available on XTDCommon library (Told you we'll use it).
Using this class we can shorten our code of loading the assets and registering them on the application domain.

private var _assetsLoader  : AssetsLoaderFromByteArray;

private function loadAssets():void
{
  var assetsByteArrays : Vector.<bytearray> = new Vector.<bytearray>;
  assetsByteArrays.push(new AllAssetsClass());
  _assetsLoader = new AssetsLoaderFromByteArray(assetsByteArrays);
  _assetsLoader.addEventListener(Event.COMPLETE, onAssetsReady);
  _assetsLoader.initializeAllAssets();
}

protected function onAssetsReady(event:Event):void
{
  sendVectorAssetsToDMT();
}  


Lets examine the code:
I've defined a private variable _assetsLoader in the type of AssetsLoaderFromByteArray.
Created a function loadAssets, which will handle the loading process.
The AssetsLoaderFromByteArray class excepts a Vector of ByteArrays (SWFs that you embedded) and loads them all into the current ApplicationDomain. Once the assets are loaded and ready (Listening to Event.COMPLETE), we can start working on the DMT side, and start the rasterization process (Converting Vectors to Textures).


Initialize DMT

To use DMT we will create an instance of DMTBasic, and listen to Event.COMPLETE (We can also listen to Event.PROGRESS to get processing/loading progress) Now, if we have cache, we can start the processing right away. if we don't have cache we should first load the assets and rasterize them.
private var _dmtBasic   : DMTBasic;

private function initDMT():void 
{
  _dmtBasic = new DMTBasic("HelloDMT", true);
  _dmtBasic.addEventListener(flash.events.Event.COMPLETE, dmtComplete);
  if (_dmtBasic.cacheExist() == true)
    _dmtBasic.process(); // will use the existing cache
  else
    loadAssets();
}


Get ready for the Rasterization

In the case that we don't have cache, we will create the three vector assets, add them to DMT, and start the processing.
private function addVectorsToDMT():void 
{
  var square : DisplayObject = new (ApplicationDomain.currentDomain.getDefinition("Square"))
  square.name = "square";   
 
  var circle : DisplayObject = new (ApplicationDomain.currentDomain.getDefinition("Circle"))
  circle.name = "circle";

  var triangle : DisplayObject = new (ApplicationDomain.currentDomain.getDefinition("Triangle"))
  triangle.name = "triangle";

  _dmtBasic.addItemToRaster(square);
  _dmtBasic.addItemToRaster(circle);
  _dmtBasic.addItemToRaster(triangle);
  _dmtBasic.process(); // will rasterize the given assets  
}
I've given each asset a name, so later we will be able to ask DMT for these specific assets by name.



Game on!

After the cache was loaded, or after the rasterization is complete, DMT will fire the Event.COMPLETE, in this event listener we can be sure that we have our Starling assets ready to use.
In this example I've created all three assets, and put them on the stage, I've also rotated the eyes of the Triangle to show that the eyes are not baked into the texture.
Pay attention that we used the names that we gave the assets.
protected function dmtComplete(event:Event):void
{
  var starlingSquare : Sprite = _dmtBasic.getAssetByUniqueAlias("square") as starling.display.Sprite;
  starlingSquare.x = 100;
  starlingSquare.y = 100;
  addChild(starlingSquare);

  var starlingCirlce : Sprite = _dmtBasic.getAssetByUniqueAlias("circle") as starling.display.Sprite;
  starlingCirlce.x = 100;
  starlingCirlce.y = 300;
  addChild(starlingCirlce);

  var starlingTriangle : Sprite = _dmtBasic.getAssetByUniqueAlias("triangle") as starling.display.Sprite;
  starlingTriangle.x = 100;
  starlingTriangle.y = 500;
  addChild(starlingTriangle);
   
  starlingTriangle.getChildByName("right_eye_instance").rotation = Math.PI/2;
  starlingTriangle.getChildByName("left_eye_instance").rotation = -Math.PI/2;
}

This is how the Texture will look like, as you can see the left and right eyes were created once because they are actually the same assets with the same linkage.


Best practices

  • Instead of doing what I did in this example, created and added items one by one. You can do this:
    • Design your level/screen in Flash-Pro into one asset.
    • Make sure that all the children are with instance names (So you'll be able to access them).
    • Give it a linkage name, say "Level1".
    • Load this asset the same as we did in this example.
    • Re-position and re-scale the children to best fit the screen-resolution.
    • Call the DMT process() function.
    • Your level is ready as Starling objects with all the inner children positioned/scaled and accessible.
    • Because we use cache, this process will be done once, and DMT will load the textures and data next time.
  • Listen to DMT Event.PROGRESS, and show the user a "Loading..." message. if DMT doesn't have cache show the user "First time Loading, please wait..."
  • The third parameter of the DMT constructor is the cache version. In case that you've updated your game, and your game has changed assets. You want DMT to clear the previous cache, and create a new one, just increase the version.
  • Don't use huge vector assets, remember that the current limit is 2048x2048.
  • DMT will rasterize each frame in a MovieClip, so be smart about it.
  • You can checkout our game (Android, iOS, Amazon), and see for yourself, everything there was done with DMT, and it fits perfectly on ALL possible resolutions with crisp graphics!



Conclusion

DMT is quite easy after few minutes, and it gives you fast and powerful technique in just few lines of code.
You can animate the inner children, just like you would in the flash timeline, but in code.
No more stretched/squashed textures!


Troubles, Solutions, and some notes

  • Most of the first time users of DMT forget about the cache, they add assets, ask DMT to process them, and get an error when asking DMT to create these new assets... DMT will use the old cache if exists. So while in development don't use cache, until the late stages of your game/app.
  • Where is the Cache saved? The answer to that is "Depends on what device", on Windows it's under C:\Users\USER_NAME\AppData\Roaming\DATA_NAME, on Android and iPhone it's on a temp folder that will not get saved to the app cloud data (As noted by Apple)
  • If you want DMT to stop "digging" into your assets display-tree and stop rasteraizing. you can do two things:
    • When you call dmtInstance.process, the second parameter is the maxDepth, use that as an overall limit. DMT will not rasterize deeper children.
    • To stop "digging" into a specific instance, name it "stop_raster", and DMT will raster this instance as it is, and not its children.
  • dmtInstance.getAssetByUniqueAlias is returning starling.display.DisplayObject, but you want MovieClip? If you are sure that your assets was a movieClip, just cast it to MovieClip.
  • MovieClips are rasterized as is, DMT will lot try to rasterize each frame's children.
  • Make sure that you use linkage name to your assets that you re-use, DMT will detect the same assets (As you saw in this example) as will not re-rasterize them.
  • Be sure to checkout the DMT source code, there are some example projects there.
Powered by Blogger.