Experimenting with OpenFL, DragonBones and Animate CC – simple Mobile browser game

Categories games, HTML5, OpenFL, Starling

This is what I ended up doing, and here it is on GiHub.

I am on a quest to find out how to build a mobile browser game as fast as I can, while also keeping the quality in check. For this I need an efficient production process, and if possible, I would like to keep using the tools and techniques that I am familiar with.

Quick background and current stats: I have been using Flash (now Animate CC) since the Macromedia era and Flash 5, that is more or less 14 years of flash dev. I do the code and the artwork/animation and I am currently studding how to draw better (in self thought way) at https://www.schoolism.com, they are awesome, while also experimenting with Haxe (also in self thought way). But most of my time it is spent raising my son, which is the most amassing adventure ever 🙂.

Back to work. In order to keep game production costs as low as possible, in my pipeline I need to:

  1. Be able to create 2D Animations fast, visually.
  2. Build UI visually.
  3. When there is a need to make small adjustments in UI or in the Animation, the update process should be seamless and fast.
  4. Code in a similar ActionScript 3 way, using events, objects, etc..
  5. Be able to prepare the code in such a way that modifications during the production are relatively easy to do, because you will always need to accommodate something unexpected.
  6. The code should also be scalable, so new levels or functionality are possible without breaking the entire app.
  7. The browser game (or app) should run on a mobile device, in the browser obviously.

I found Haxe to be the perfect match for my needs, while building Mr Nussbaum Boardwalk Challenge. Unfortunately Flambe was hard to bend to my will, so I am now investing my (extremely limited) energy into OpenFL.

OpenFL has a lot in common with ActionScript 3, so at times it doesn’t feel like I switched to a new language at all.

For the IDE, I used HaxeDevelop for a while, even gave Visual Studio IDE a try, but now I am back to FlashDevelop, because during my coding in HaxeDevelop there were a lot of times when the code would not compile at the first try, and only after about 3 to 5 times, without me touching the code. This obviously makes the development process extremely difficult because you never know if the fault is in your code, or the IDE is misbehaving again. So now I have switched back to FlashDevelop, and I will see if I the issues persists.

Here are the tools I use:

  1. Haxe 3.4.3, with the libs dragonbones: 5.0.0, openfl: 6.2.0, starling: 1.8.11
  2. Animate CC 2017.5 with the OpenFL Plugin 1.0.0
  3. DragonBones Pro 5.5
  4. FlashDevelop 5.2.0.3

The idea was to build a fun crossbow toy, that shoots cute arrows into bubbles of soap. From this, I will probably expand and build some simple educational game, but for production pipeline and tech testing, the simple prototype is enough. The idea to start with a toy (something fun) and build on top of that, came from reading “The Art of Game Design” by Jesse Schell, an eye opening book on how to make games.

 

After I was happy with the crossbow design, I started to test different animation editors, and decided to remain with Dragon Pro, in part because it had support for OpenFL, but also because it worked with AS3 and Starling, so in the case I wanted to develop the project in AS3, I would be able to reuse the artwork.

After a bit of trial and error and some YouTube watching, I was able to accomplish exactly what I wanted with the corners of the crossbow turning inside when you pull it back. So this is how the crossbow armature looks like in DragonBones, and if you want to check it out even more, you can find all the DragonBones files on GitHub.

Now we move to integrating the animation with OpenFL, and unfortunately things started to break, one after another:

First attempt, render the animation with Startling 1.8, which didn’t work. After some digging around the web, I find that in Starling 1.8 the mesh animation is not supported.

Second attempt, using the OpenFL render, it only showed parts of the animation with the mesh deformation, also on Samsung Tab A (some old version), it crashed the Chrome browser. I tried different export data options from DragonBones, neither of them worked.

But, the examples seemed to work fine, so maybe they are made with an earlier version of DragonBones and there is something funny in the newer data format. Who knows?

Third attempt, build the animation în DragonBones, export it as frame sequence (alpha png). Create a new OpenFL project in Animate CC, import the image sequence inside an MovieClip (that you export it for ActionScript), and just like that, it all worked.

This way also lets me augment the animation inside Animate CC, and also lets me build the UI in a visual way. It is kind of the perfect combination.

Here is the catch, the performance is not great, it works fine on medium to higher end mobile devices using Chrome, but Firefox won’t play nice.

So I tested on some more browsers:

  • On Chrome it works fine, but no fullscreen from the compiled project (might have to check the html file).
  • Firefox – low fps, and breaks after a while.
  • Firefox Focus – won’t show the hole app.
  • Opera – works perfectly, even the full screen
  • Opera mini – works, no fullscreen
  • Dolphin – seems to work really well, but no fullscreen
  • Cm Browser – works, but no fullscreen
  • Via Browser – works, but no fullscreen

So it seems that only Firefox causes problems

Devices tested:

  • iPhone 6s, it works perfectly
  • iPad 2, not usable, it has very low fps
  • Samsung Tab A, not usable very low fps (CPU 1.2 GHz)
  • Huawei nova (CPU 2 GHz), works great (except Firefox)

Other issues and limitations:

Animation on the timeline that use masks, wont show the right way in OpenFL, so don’t use mask in animations. Another big issue will be memory footprint and file size when you use a lot of animations. Probably a better way would be to build UI, and simple animations in Animate CC, and use DragonBones animations without the mesh editor for characters. Hopefully Starling 2 will be ported to OpenFL soon, and we will be able to use DragonBones without a problem with OpenFL and Starling, while keeping Animate CC for UI and other simple animations.

In conclusion, if you (or the client) are OK with the limitations, you can build a browser game or app, quite fast when you use OpenFL in combination with Animate CC and DragonBones, and because the community is really getting into it, I am pretty sure the tools will evolve fast and the remaining obstacles will fall away soon enough.

If anyone else has tried different things on Animate CC, OpenFL Dragon Bones do share with links in the comments.

 

p.s.

I am taking on new projects, (I will be opening new projects spots in March 2018) let’s talk contact@cosmindolha.com

 

Share this
Facebooktwitter

Source code for a very simple HTML5 Toddlers Game created using Haxe and OpenFL

Categories games, HTML5

Jump to source code.

You can see my son playing with it here, and the full game here, it’s in Romanian, it says the animal on click (I mean touch, but I am not used to this click/touch thing yet), or asks for the animal location when you press the upper right button (asking mode). It’s very basic without any UI effects, because my wife told me so, she is a Psychologist, so she knows better about this stuff, also after watching a lot of Grand Designs episodes, I have come to the conclusion that if you don’t listen to your wife you make dumb mistakes.

Most of the hard work on this game were the drawings, once I had those done, coding everything was pretty straight forward. Prior to this game, I did the MrNussbaums’s Boardwalk Challenge, which was way more complex in scope. That game was done in Flambe., and my first project in Haxe. While I did like Flambe, once I got used with the architecture, I did find adapting the game to the various screen sizes to be quite hard (you only got “scale”, and not “width” proprieties of your game objects). So when I started this new game, some time have already passed and OpenFL seemed the better candidate. Also I didn’t need the swf output since, this was going to be used mostly on mobile devices.

Here is the game specs doc:

Game scope: Learning new words (animals, in this case) using images and sound association.

Target Device use: mobile phones, tablets, mostly Android, but must work on iOS too.

Screen Orientation: must work both in landscape and portrait mode.

Screen sizes: must adapt to various screen resolutions and aspect ratios.

Design considerations: Since the target audience is of such small age, only 3 animals are shown on a screen at a time. Animations, or sound effects are not useful in this case since they would create a big distraction on a very easy to distract user (have you seen how easy toddlers loose concentration, almost as easy as us grownups 🙂 )

The game interaction:

1. The player (a very small child) touches a card and the sound associated is played. She can change the screen animals using the left or right navigation buttons, which loops the cards on the screen.

2. There is a second mode to play the game, when the child or parent touches the upper right button, “the question” mode will start playing. In this mode, the game asks the child where a particular animal is located on the screen. If the child answer correctly, a congratulation sound is played, else the game says the card that was touched and then asks again for the animal, until the child answers correctly, reinforcing the right association and thus teaching the word.

The Source code, together with all the artwork are here.

Prerequisites. To compile the code you need Haxe, OpenFL and Actuate together with your favorite IDE, I use HaxeDevelop.

Reasons to use OpenFL:

  • You don’t like to code in JavaScript
  • You like a more structure  (and scalable) way of doing things.
  • Mostly you will use it because you are an ActionScript developer and want to code in a familiar way,
  • You hate JavaScript ( have no idea why anyone would choose to hate a certain technology, but some people do, so)
Here is the full source code:

This is the Main.hx file:

 

 

ActionScript

  1. package primelecuvinte;
  2.  
  3. import openfl.display.Sprite;
  4. import openfl.display.BitmapData;
  5. import openfl.display.Bitmap;
  6. import openfl.display.StageDisplayState;
  7. import openfl.utils.Assets;
  8. import openfl.Lib;
  9. import openfl.events.Event;
  10. import openfl.events.MouseEvent;
  11. import motion.actuators.SimpleActuator;
  12. import motion.easing.Linear;
  13. import motion.Actuate;
  14. /**
  15. * ...
  16. * @author Cosmin Dolha
  17. */
  18. class Main extends Sprite
  19. {
  20. var bg:Bitmap;
  21. var gameStarted:Bool;
  22. var bgGameSp:Sprite;
  23. var scale:Float;
  24. var bgsp:Sprite;
  25. var title:Sprite;
  26. var intsrt:Sprite;
  27.  
  28. public function new()
  29. {
  30. super();
  31.  
  32. buildGameUI();
  33.  
  34. onResize(null);
  35. stage.addEventListener(Event.RESIZE, onResize);
  36.  
  37. }
  38. private function picSp(pic:String, sp:Sprite):Void
  39. {
  40. //empy sprite first
  41. if (sp.numChildren > 0)
  42. {
  43. sp.removeChildren();
  44. }
  45. var bd:BitmapData = Assets.getBitmapData('img/$pic');
  46. var bmp = new Bitmap(bd);
  47.  
  48. sp.addChild(bmp);
  49.  
  50. }
  51. private function buildGameUI():Void
  52. {
  53. bgsp = new Sprite();
  54. title = new Sprite();
  55. intsrt = new Sprite();
  56.  
  57. bgGameSp = new Sprite();
  58.  
  59. bgGameSp.alpha = 0;
  60.  
  61. addChild(bgGameSp);
  62.  
  63. addChild(bgsp);
  64. addChild(title);
  65. addChild(intsrt);
  66.  
  67. picSp("bg.png", bgGameSp);
  68. picSp("start_screen.jpg", bgsp);
  69. picSp("title.png", title);
  70. picSp("instr.png", intsrt);
  71.  
  72. addEvents();
  73. }
  74.  
  75. function addEvents():Void
  76. {
  77. stage.addEventListener(MouseEvent.CLICK, onStartGame);
  78. }
  79.  
  80. private function onStartGame(e:MouseEvent):Void
  81. {
  82.  
  83. Assets.getSound("img/sillent.mp3").play();
  84.  
  85. stage.removeEventListener(MouseEvent.CLICK, onStartGame);
  86.  
  87. stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
  88.  
  89. Actuate.tween (bgGameSp, 1, { alpha: 1 }).ease (Linear.easeNone).onComplete(startMyGame);
  90.  
  91. }
  92.  
  93. private function startMyGame():Void
  94. {
  95. gameStarted = true;
  96. bgsp.visible = false;
  97. intsrt.visible = false;
  98. title.visible = false;
  99.  
  100. bgsp.removeChildren();
  101. intsrt.removeChildren();
  102. title.removeChildren();
  103.  
  104. removeChild(title);
  105. removeChild(intsrt);
  106. removeChild(bgsp);
  107.  
  108. var gamePlay:GamePlay = new GamePlay();
  109. Lib.current.stage.addChild(gamePlay);
  110. }
  111.  
  112. private function onResize(e):Void
  113. {
  114. var scaleX = stage.stageWidth / 1280;
  115. var scaleY = stage.stageHeight / 720;
  116.  
  117. scale = Math.min(scaleX, scaleY);
  118.  
  119. stage.scaleX = scale;
  120. stage.scaleY = scale;
  121.  
  122. stage.x = (stage.stageWidth - 1280 * scale) / 2;
  123. stage.y = (stage.stageHeight - 720 * scale) / 2;
  124.  
  125. var pmode:Bool = stage.stageWidth > stage.stageHeight;
  126.  
  127. if (!gameStarted)
  128. {
  129.  
  130. if (pmode)
  131. {
  132.  
  133. fitScreenP(bgsp);
  134.  
  135. centerScreenP(title);
  136. centerScreenP(intsrt);
  137.  
  138. intsrt.y = stage.stageHeight - intsrt.height*1.5;
  139. title.y = title.height*1.5;
  140.  
  141. }
  142. if (!pmode)
  143. {
  144. fitScreenBgL(bgsp);
  145.  
  146. fitScreenL(title);
  147. centerScreenL(intsrt);
  148.  
  149. intsrt.y = stage.stageHeight - intsrt.height*4;
  150. title.y = title.height;
  151.  
  152. }
  153.  
  154. }
  155.  
  156. fitScreenStretch(bgGameSp);
  157.  
  158. }
  159. private function fitScreenStretch(sp:Sprite):Void
  160. {
  161. sp.width = stage.stageWidth;
  162. sp.height = stage.stageHeight;
  163. }
  164. private function fitScreenP(sp:Sprite):Void
  165. {
  166. sp.width = stage.stageWidth;
  167.  
  168. sp.scaleY = sp.scaleX;
  169. sp.x = Math.floor(stage.stageWidth / 2) - sp.width / 2;
  170. sp.y = Math.floor(stage.stageHeight / 2) - sp.height / 2;
  171. }
  172.  
  173. private function centerScreenP(sp:Sprite):Void
  174. {
  175. sp.scaleX = (stage.stageHeight / 720)*1.5;
  176. sp.scaleY = (stage.stageHeight / 720)*1.5;
  177. sp.x = Math.floor(stage.stageWidth / 2) - sp.width / 2;
  178. sp.y = Math.floor(stage.stageHeight / 2) - sp.height / 2;
  179. }
  180.  
  181. private function fitScreenL(sp:Sprite):Void
  182. {
  183. sp.scaleX = (stage.stageHeight / 720 );
  184. sp.scaleY = (stage.stageHeight / 720);
  185. sp.x = Math.floor(stage.stageWidth / 2) - sp.width / 2;
  186. sp.y = Math.floor(stage.stageHeight / 2) - sp.height / 2;
  187. }
  188.  
  189. private function fitScreenBgL(sp:Sprite):Void
  190. {
  191. sp.scaleX = (stage.stageHeight / 720);
  192. sp.scaleY = (stage.stageHeight / 720);
  193. sp.x = Math.floor(stage.stageWidth / 2) - sp.width / 2;
  194. sp.y = Math.floor(stage.stageHeight / 2) - sp.height / 2;
  195. }
  196.  
  197. private function centerScreenL(sp:Sprite):Void
  198. {
  199. sp.scaleX = (stage.stageHeight / 720 );
  200. sp.scaleY = (stage.stageHeight / 720);
  201. sp.x = Math.floor(stage.stageWidth / 2) - sp.width / 2;
  202. sp.y = Math.floor(stage.stageHeight / 2) - sp.height / 2;
  203. }
  204.  
  205. }

This is the GamePlay.hx file

ActionScript

  1. package primelecuvinte;
  2.  
  3. /**
  4.  * ...
  5.  * @author Cosmin Dolha
  6.  */
  7. import openfl.display.Sprite;
  8. import openfl.display.BitmapData;
  9. import openfl.display.Bitmap;
  10. import openfl.display.Stage;
  11. import openfl.display.StageDisplayState;
  12. import openfl.media.SoundChannel;
  13. import openfl.utils.Assets;
  14. import openfl.Lib;
  15. import openfl.events.Event;
  16. import openfl.events.MouseEvent;
  17. import motion.actuators.SimpleActuator;
  18. import motion.easing.Linear;
  19. import motion.Actuate;
  20. import Random;
  21. import haxe.Timer;
  22. class GamePlay extends Sprite
  23. {
  24.     var cardsHolderSp:Sprite;
  25.     var cardLeft:Sprite;
  26.     var cardMiddle:Sprite;
  27.     var cardRight:Sprite;
  28.     var navRight:Sprite;
  29.     var navLeft:Sprite;
  30.     var autoPlayOff:Sprite;
  31.     var autoPlayOn:Sprite;
  32.     var scale:Float;
  33.     var myStage:Stage;
  34.     var soundChannel:SoundChannel;
  35.     var playingSound:Bool;
  36.     var picsArray:Array<string>;
  37.     var totalPages:Int = 3;//starts at 0
  38.     var currentPage:Int = 0;
  39.     var autoPlayPickedCard:Int;
  40.     var cardClicked:Int;
  41.     var autoPlayMode:Bool;
  42.     var id:Int;
  43.    
  44.    
  45.     public function new()
  46.     {
  47.        
  48.         super();
  49.        
  50.         //the name of the picture and the mp3 sound associated with each
  51.         picsArray = ["albina", "vaca", "bufnita", "gasca", "caine", "oaie", "lup", "lama", "lebada", "papagal", "peste", "magar"];
  52.        
  53.         soundChannel = new SoundChannel();
  54.        
  55.         cardsHolderSp = new Sprite();
  56.        
  57.         cardLeft = new Sprite();
  58.         cardMiddle = new Sprite();
  59.         cardRight = new Sprite();
  60.        
  61.         navRight = new Sprite();
  62.         navLeft = new Sprite();
  63.        
  64.        
  65.         autoPlayOn = new Sprite();
  66.         autoPlayOff = new Sprite();
  67.  
  68.        
  69.         addChild(cardsHolderSp);
  70.        
  71.         addChild(navRight);
  72.         addChild(navLeft);
  73.         addChild(autoPlayOn);
  74.         addChild(autoPlayOff);
  75.        
  76.        
  77.        
  78.         cardsHolderSp.addChild(cardLeft);
  79.         cardsHolderSp.addChild(cardMiddle);
  80.         cardsHolderSp.addChild(cardRight);
  81.        
  82.  
  83.        
  84.         gotoPage(0);
  85.        
  86.         picSp("navarrow.png", navRight);
  87.         picSp("navarrowl.png", navLeft);
  88.        
  89.        
  90.         picSp("autooff.png", autoPlayOff);
  91.         picSp("autoon.png", autoPlayOn);
  92.        
  93.        
  94.        
  95.         cardLeft.addEventListener(MouseEvent.CLICK, leftClick);
  96.         cardMiddle.addEventListener(MouseEvent.CLICK, middleClick);
  97.         cardRight.addEventListener(MouseEvent.CLICK, rightClick);
  98.        
  99.        
  100.         navRight.addEventListener(MouseEvent.CLICK, navRightClick);
  101.         navLeft.addEventListener(MouseEvent.CLICK, navLeftClick);
  102.        
  103.         autoPlayOn.addEventListener(MouseEvent.CLICK, autoPlayOnClick);
  104.         autoPlayOff.addEventListener(MouseEvent.CLICK, autoPlayOffClick);
  105.        
  106.         addEventListener(Event.ADDED_TO_STAGE, onAdded);
  107.        
  108.         autoPlayOn.visible = false;
  109.         Lib.current.stage.addEventListener(MouseEvent.CLICK, goFullScreen);
  110.        
  111.     }
  112.     private function goFullScreen(e:Event):Void
  113.     {
  114.        
  115.         Lib.current.stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
  116.     }
  117.     private function anotherQuestionDelayed(e:Event):Void  
  118.     {
  119.         Timer.delay(anotherQuestion, 1500);
  120.     }
  121.    
  122.     private function anotherQuestion():Void
  123.     {
  124.                
  125.         autoPlayPickedCard = Random.int(0, 2);
  126.        
  127.         askQuestion();
  128.     }
  129.    
  130.     private function startAutoPlayGame():Void
  131.     {
  132.         autoPlayMode = true;
  133.         anotherQuestion();
  134.     }
  135.    
  136.     function askQuestion():Void  
  137.     {
  138.         soundChannel.stop();
  139.        
  140.         soundChannel = Assets.getSound("img/unde_este.mp3").play();
  141.         soundChannel.addEventListener(Event.SOUND_COMPLETE, askingFinished );
  142.        
  143.        
  144.        
  145.     }  
  146.    
  147.     function telTheCardClicked(e:Event):Void  
  148.     {
  149.         soundChannel.stop();
  150.        
  151.         Assets.getSound("img/"+picsArray[id*3+cardClicked]+".mp3").play();
  152.         soundChannel.addEventListener(Event.SOUND_COMPLETE, repeatQuestionDelayed );
  153.     }  
  154.    
  155.    
  156.     function repeatQuestionDelayed(e:Event):Void  
  157.     {
  158.         Timer.delay(repeatQuestionD, 1500);
  159.     }
  160.    
  161.     function repeatQuestionD():Void
  162.     {
  163.         soundChannel.stop();
  164.        
  165.         soundChannel = Assets.getSound("img/unde_este.mp3").play();
  166.         soundChannel.addEventListener(Event.SOUND_COMPLETE, askingFinished );
  167.     }
  168.    
  169.     function repeatQuestion(e:Event):Void
  170.     {
  171.         repeatQuestionD();
  172.     }
  173.    
  174.     function checkAnswer():Void  
  175.     {
  176.         if (autoPlayPickedCard == cardClicked)
  177.         {
  178.             soundChannel.stop();
  179.        
  180.             soundChannel = Assets.getSound("img/bravo.mp3").play();
  181.             soundChannel.addEventListener(Event.SOUND_COMPLETE, anotherQuestionDelayed );
  182.            
  183.         }else{
  184.            
  185.             soundChannel.stop();
  186.        
  187.             soundChannel = Assets.getSound("img/acolo_este.mp3").play();
  188.             soundChannel.addEventListener(Event.SOUND_COMPLETE, telTheCardClicked );
  189.            
  190.         }
  191.        
  192.     }
  193.     function playPickedCardSound():Void  
  194.     {
  195.         soundChannel.stop();
  196.        
  197.         soundChannel = Assets.getSound("img/"+picsArray[id*3+autoPlayPickedCard]+".mp3").play();
  198.        
  199.    
  200.     }
  201.    
  202.     private function askingFinished(e:Event):Void
  203.     {
  204.         soundChannel.removeEventListener(Event.SOUND_COMPLETE, askingFinished );
  205.         playingSound = false;
  206.        
  207.         playPickedCardSound();
  208.     }
  209.    
  210.    
  211.     private function autoPlayOffClick(e:MouseEvent):Void
  212.     {
  213.         autoPlayOff.visible = false;
  214.         autoPlayOn.visible = true;
  215.         startAutoPlayGame();
  216.        
  217.     }
  218.    
  219.     private function autoPlayOnClick(e:MouseEvent):Void
  220.     {
  221.         autoPlayOff.visible = true;
  222.         autoPlayOn.visible = false;
  223.         autoPlayMode = false;
  224.        
  225.     }
  226.    
  227.     function gotoPage(ids:Int) :Void
  228.     {
  229.         id = ids;
  230.        
  231.         picSp(picsArray[id*3]+".jpeg", cardLeft);
  232.         picSp(picsArray[id*3+1]+".jpeg", cardMiddle);
  233.         picSp(picsArray[id * 3 + 2] + ".jpeg", cardRight);
  234.        
  235.         if (autoPlayMode)
  236.         {
  237.              anotherQuestion();
  238.         }
  239.        
  240.     }
  241.    
  242.     private function navRightClick(e:MouseEvent):Void
  243.     {
  244.         currentPage++;
  245.         if (currentPage > totalPages)
  246.         {
  247.             currentPage = 0;
  248.         }
  249.        
  250.         gotoPage(currentPage);
  251.     }  
  252.    
  253.     private function navLeftClick(e:MouseEvent):Void
  254.     {
  255.         currentPage--;
  256.         if (currentPage < 0)
  257.         {
  258.             currentPage = totalPages;
  259.         }
  260.         gotoPage(currentPage);
  261.     }
  262.  
  263.    
  264.     private function cardsClicked(cardID:Int):Void
  265.     {
  266.         cardClicked = cardID;
  267.        
  268.         if (!playingSound && !autoPlayMode)
  269.         {
  270.             playingSound = true;
  271.             soundChannel.stop();
  272.             soundChannel = Assets.getSound("img/"+picsArray&#91;id*3+cardID]+".mp3").play();
  273.             soundChannel.addEventListener(Event.SOUND_COMPLETE, onSoundFinished );
  274.            
  275.         }
  276.        
  277.        
  278.         if (autoPlayMode)
  279.         {
  280.             checkAnswer();
  281.            
  282.         }
  283.     }
  284.     private function onSoundFinished(e:Event):Void
  285.     {
  286.         soundChannel.removeEventListener(Event.SOUND_COMPLETE, onSoundFinished );
  287.         playingSound = false;
  288.     }
  289.    
  290.     private function leftClick(e:MouseEvent):Void
  291.     {
  292.         cardsClicked(0);   
  293.     }
  294.    
  295.     private function middleClick(e:MouseEvent):Void
  296.     {
  297.         cardsClicked(1);
  298.        
  299.     }  
  300.    
  301.     private function rightClick(e:MouseEvent):Void
  302.     {
  303.         cardsClicked(2);
  304.     }
  305.    
  306.     private function onAdded(e:Event):Void
  307.     {
  308.         removeEventListener(Event.ADDED_TO_STAGE, onAdded);
  309.        
  310.         onResize(null);
  311.         stage.addEventListener(Event.RESIZE, onResize);
  312.        
  313.        
  314.        
  315.     }
  316.  
  317.    
  318.     private function onResize(e):Void
  319.     {
  320.         var scaleX = stage.stageWidth / 1280;
  321.         var scaleY = stage.stageHeight / 720;
  322.        
  323.         scale = Math.min(scaleX, scaleY);
  324.         var buttonScale = scaleY;
  325.  
  326.         var pmode:Bool = stage.stageWidth > stage.stageHeight;
  327.    
  328.         if (pmode)
  329.         {
  330.    
  331.             cardLeft.x = 0;
  332.             cardMiddle.x = 420;
  333.             cardRight.x = 840;     
  334.            
  335.             cardLeft.y = 0;
  336.             cardMiddle.y = 0;
  337.             cardRight.y = 0;
  338.             fitScreenL(cardsHolderSp);
  339.            
  340.             var buttonScale = scaleY;
  341.            
  342.         }  
  343.        
  344.         if (!pmode)
  345.         {
  346.            
  347.             cardLeft.y = 0;
  348.             cardMiddle.y = 420;
  349.             cardRight.y = 840;
  350.            
  351.             cardLeft.x = 0;
  352.             cardMiddle.x = 0;
  353.             cardRight.x = 0;   
  354.            
  355.             fitScreenP(cardsHolderSp);
  356.            
  357.             buttonScale = scaleY*0.75;
  358.         }
  359.         navRight.scaleX = buttonScale;
  360.         navRight.scaleY = buttonScale; 
  361.            
  362.         navLeft.scaleX = buttonScale;
  363.         navLeft.scaleY = buttonScale;
  364.            
  365.            
  366.         autoPlayOff.scaleX = buttonScale;
  367.         autoPlayOff.scaleY = buttonScale;      
  368.        
  369.         autoPlayOn.scaleX = buttonScale;
  370.         autoPlayOn.scaleY = buttonScale;
  371.        
  372.        
  373.         autoPlayOn.x = stage.stageWidth - autoPlayOn.width;
  374.         autoPlayOff.x = stage.stageWidth - autoPlayOff.width;
  375.        
  376.         navRight.x = stage.stageWidth - navRight.width;
  377.        
  378.         if (pmode)
  379.         {  
  380.            
  381.             navRight.y = stage.stageHeight - navRight.height;
  382.             navLeft.y = stage.stageHeight - navRight.height;
  383.        
  384.         }
  385.         if (!pmode)
  386.         {
  387.            
  388.             navRight.y = stage.stageHeight/2 - navRight.height/2;
  389.             navLeft.y = stage.stageHeight / 2 - navRight.height / 2;
  390.         }
  391.     }
  392.    
  393.     private function fitScreenL(sp:Sprite):Void
  394.     {
  395.         sp.scaleX = stage.stageWidth / 1280;
  396.         sp.scaleY = stage.stageWidth / 1280;
  397.         sp.x = Math.floor(stage.stageWidth / 2) - sp.width / 2;
  398.         sp.y = Math.floor(stage.stageHeight / 2) - sp.height / 2;
  399.     }
  400.        
  401.     private function fitScreenP(sp:Sprite):Void
  402.     {
  403.         sp.scaleX = stage.stageHeight / 1280;
  404.         sp.scaleY = stage.stageHeight / 1280;
  405.        
  406.         sp.x = Math.floor(stage.stageWidth / 2) - sp.width / 2;
  407.         sp.y = Math.floor(stage.stageHeight / 2) - sp.height / 2;
  408.     }
  409.    
  410.     private function picSp(pic:String, sp:Sprite):Void
  411.     {
  412.         //empy sprite first
  413.         if (sp.numChildren > 0)
  414.         {
  415.             sp.removeChildren();
  416.         }
  417.         var bd:BitmapData = Assets.getBitmapData('img/$pic');
  418.         var bmp = new Bitmap(bd);
  419.         bmp.smoothing = true;
  420.         sp.addChild(bmp);
  421.        
  422.     }
  423. }

Thats it, pretty simple code, nothing fancy in here. I hope you can take chunks from it and use it in you HTML5 game/app.

 

Share this
Facebooktwitter