Showing posts with label tutorial. Show all posts
Showing posts with label tutorial. Show all posts

Wednesday, October 9, 2013

Building custom controls in Stencyl - Part 3

I expected to be much more complicated but I achieved pausing functionality with just several clicks :)

Check out this page http://www.stencyl.com/help/view/pausing/

Go to physics tab on the SpaceRanger actor. I set the main character to be independent of gravity, and cannot be rotated. In the advanced tab I just unset can be touched ability for iOS. I leave can be pause abilty on. Here are images of events I set for Scene1:




 Same as in the wiki page above. Save your game and test it. Now when you press P button the space ranger will be freezed and the screen will get dimmed.

You can also play with the focus event i.e pause the game if the focus is lost and unpause the game if the focus is restored. Gaining/loosing focus means if you press on the flash player canvas or if you press away from the canwas. I added two more focus events on Scene1.



You can check this with you mouse when you click on the taskbar and then again on the flash canvas

Building custom controls in Stencyl - Part 2

Next is adding custom controlls to you game. Press the settings button. Tnen press Controls tab.

You can now see controls: up, down, left, right, x, z and enter. Remove x, z and enter controls as we will not use them. Add 4 more controls W, A, S and D. Then add control Pause and set it to button P.
Check the images below



Select Actors Behaviors item in the dashboard. Select "8 Way Movement" behavior, right click and press duplicate behavior. Double click on the copied behavior and press the properties tab. Rename it ArrowsWASDController. The trick is to add the missing keyboard buttons in the code so that when changes applied you can controll the character with both WASD and arrow key sets.

Here is a screenshot of the changes I have made to our copied behavior:

Copied "8 Way Movement" behavior

This is on the updating event. See only the top part. I added simple "or" condition and added corresponding button presses. The next pic is the updating event on the original "8 Way movement" behavior just to show you the differences:

Original "8 Way Movement" behavior   
Once you are finsihed editing of ArrowsWASDController behavior don't forget to press the "Attach to Actor" button. Attach it to SpaceRanger. You may think, we have added another behavior that does roughly the same thing as the first one. Well go to behaviors tab of "Space Ranger" actor and deactivate original "8 Way movement" behavior. You may also remove it if you like.

Note: As a practice you can search the behaviors and find "Cannot exit screen" behavior in Motions section. This will prevent the main character to fall off the screen and disapear.

Ok thats it for this part. Press ctrl-enter to test the game. Don't forget File->Save Game to save the progress.

Building custom controls in Stencyl - Part 1

Hello. In this post I will show you how to build custom keyboard controls to control main character. For example one of my games have controls: arrow keys, up, down, left and right but I would like to add controls like WASD and P for pausing the game. I think adding secondary keys is very useful feature simply because some people are left handed but also it is useful when your right or maybe left arm gets tired so you can switch to other key set.

I have built my own sprite sheet of my main character which I call Space Ranger. Here it is:

Space Ranger sprite sheet

This character has 5 states, 4 of which are flying backward, forward, upward and downward. The fifth state is hovering at some point on the screen. So each of the four above states can go to hovering state by releasing keyboard buttons and also from hovering state you can go to above four by pressing the buttons left/A, right/D, up/W and down/S.
For each of the four states this character has two frames taken from the above spritesheet.

Open Stencyl and create new blank game, call it KeyboardControllerTest. Choose custom size of   640 x 480 and press create. Next create new actor and call it SpaceRanger.


I have taken the above screenshot to show you what's going on in Stencyl. On the left pane there are listed 5 animations which represent the 5 states of the main character. Each of the animations has two frames as stated before.

Next we will add behaviours to the main character. Click on the Behaviours tab in the middle.
Click "add behaviour" button on the left bottom of the screen. From the new window select Controls item and add 8 way movement behaviour. After you add this new behaviour you can edit it like controls, animations, check the screenshots below:




Leave all other settings default. Next is adding the main character on a scene but first we need a scene. Create new scene and call it Scene1. Leave everything default. Go back to SpaceRanger page and press "Add to Scene" button in the upper right corner. Add it to Scene1 and press File-> Save Game to save the current progress.

Note: It seems ctrl-s saves the current progress of the game but not toroughly. So always try File-Save Game option.

Now press test game button in upper right or press ctrl-enter to test you game. Try to move the astronaut with the arrow key.

This completes the first part of this tutorial.

Wednesday, April 17, 2013

Collision detection - Hero vs Multiple enemies

Hi. In this tutorial I will show you how to use QuadTree implementation in AS3 to detect whether a Hero object on the stage colide with many Enemy objects.

I asume you have installed FlashDevelop and created AS3 blank project called CollisionDetection in folder with same  name.

Firstly I reused a code from other site but mine code is implemented fully in AS3 and is fitted to suit my needs i.e checking if a Hero object collides with many Enemies. First I recommend read the tutorial from the site before implementing it in AS3. Roughly QuadTree is a data structure that has 4 and only 4 child nodes. It is the same principal as binary tree except it has two child nodes.

How do we use the QuadTree structure to detect collision detection???

Well we can create arrays of objects and use "for loops" to cycle trough each object and check for collision, but the problem that arises is that we might have many operations per frame (in games) so that might crash flash or not work at all on slower computers. So we use a QuadTree to separate the 2D space in 4 subparts and check if there is a collision between objects in a smaller area.
There is no need to check objects that are on the different sides of the stage.
During the separation we check if objects are fitted in quadrant. If there are many objects in a given quadrant we separate that quadrant into again four subquadrants and check again.

First create three folders uder the root of the FlashDevelop project. Call them CollisionDetectionPkg, EnemyPkg, and HeroPkg.

In CollisionDetectionPkg add new blank AS3 class and name it QuadTree.as.
In EnemyPkg add new AS3 class and name it Enemy.as
In HeroPkg follows the same thing, add blank class Hero.as

Our Main.as class will be manager for adding multiple enemies and also do all the stuff for checking and retrieving objects that might collide with Hero object.

QuadTree.as

package CollisionDetectionPkg
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.geom.Rectangle;

    public class QuadTree
    {
        private var _stage:DisplayObject;
        private var MAX_OBJECTS:int = 10;
        private var MAX_LEVELS:int = 5;
       
        private var level:int;
        private var objects:Array; // sprites that are put on the stage
        private var bounds:Rectangle;
        private var nodes:Array; //array of QuadTree objects
       
        /*
          * Constructor
        */
        public function QuadTree(pLevel:int, pBounds:Rectangle, stage:DisplayObject)
        {
            _stage = stage;
            level = pLevel;
            objects = new Array();
            bounds = pBounds;
            nodes = new Array(4);
        }
       
        /*
         * Clears the quadtree
         */
        public function clear():void
        {
            for (var i:int = 0; i < objects.length; i += 1)
            {
                if (objects[i] != null)
                {
                    objects.splice(i, 1);
                }
            }
           
            for (var j:int = 0; j < nodes.length; j += 1)
            {
                if (nodes[j] != null)
                {
                    nodes.splice(j, 1);
                }
            }
        }
       
        /*
         * Splits the node into 4 subnodes
        */
        private function split():void
        {
            var subWidth:int = int(bounds.width / 2);
            var subHeight:int = int(bounds.height / 2);
            var x:int = int(bounds.x);
            var y:int = int(bounds.y);
           
            nodes[0] = new QuadTree(level + 1, new Rectangle(x + subWidth, y, subWidth, subHeight), _stage);
            nodes[1] = new QuadTree(level + 1, new Rectangle(x, y, subWidth, subHeight), _stage);
            nodes[2] = new QuadTree(level + 1, new Rectangle(x, y + subHeight, subWidth, subHeight), _stage);
            nodes[3] = new QuadTree(level + 1, new Rectangle(x + subWidth, y + subHeight, subWidth, subHeight), _stage);
        }
       
        /*
         * Determine which node the object belongs to. -1 means
         * object cannot completely fit within a child node and is part
         * of the parent node
         */
        private function getIndex(pRect:Rectangle):int
        {
            var index:int = -1;
            var verticalMidpoint:Number = bounds.x + (bounds.width / 2);
            var horizontalMidpoint:Number = bounds.y + (bounds.height / 2);
           
            // Object can completely fit within the top quadrants
            var topQuadrant:Boolean = (pRect.y < horizontalMidpoint && pRect.y + pRect.height < horizontalMidpoint);
            // Object can completely fit within the bottom quadrants
            var bottomQuadrant:Boolean = (pRect.y > horizontalMidpoint);
 

            // Object can completely fit within the left quadrants
            if (pRect.x < verticalMidpoint && pRect.x + pRect.width < verticalMidpoint)
            {
                if (topQuadrant)
                {
                    index = 1;
                }
                else if (bottomQuadrant)
                {
                    index = 2;
                }
            }
            // Object can completely fit within the right quadrants
            else if (pRect.x > verticalMidpoint)
            {
                if (topQuadrant)
                {
                    index = 0;
                }
                else if (bottomQuadrant)
                {
                    index = 3;
                }
            }
       
            return index;
        }
       
        /*
         * Insert the object into the quadtree. If the node
         * exceeds the capacity, it will split and add all
         * objects to their corresponding nodes.
         */
        public function insert(pRect:Sprite):void
        {
            if (nodes[0] != null)
            {
                var index:int = getIndex(pRect.getRect(_stage));
               
                if (index != -1 && nodes[index] != null)
                {
                    nodes[index].insert(pRect);
                    return;
                }
            }
           
            objects.push(pRect);
       
            if (objects.length > MAX_OBJECTS && level < MAX_LEVELS)
            {
                if (nodes[0] == null)
                {
                    split();
                }
               
                var i:int = 0;
                while (i < objects.length)
                {
                    var index1:int = getIndex(objects[i].getRect(_stage));
                    if (index1 != -1 && nodes[index1] != null)
                    {
                        nodes[index1].insert(objects[i]);
                        objects.splice(i, 1);
                    }
                    else
                    {
                        i += 1;
                    }
                }
            }
           
        }
       
        /*
         * Return all objects that could collide with the given object
         */
        public function retrieve(returnObjects:Array, pRect:Sprite):Array
        {
            var index:int = getIndex(pRect.getRect(_stage));
          
            if (nodes[0] != null && index != -1 && nodes[index] != null)
            {
                nodes[index].retrieve(returnObjects, pRect);
            }
       
            for (var i:int = 0; i < objects.length; i += 1)
            {
                if (objects[i] != null)
                {
                    returnObjects.push(objects[i]);
                }
            }
       
            return returnObjects;
         }
    }

}

-----------------------------------------------------------------------------------------------------------------

Enemy.as

our Enemy is 50x50 white rectangle with red border



 



package EnemyPkg
{
    import flash.display.Sprite;
    import flash.events.Event;
    /**
     * ...
     * @author SpinnerBox
     */
    public class Enemy extends Sprite
    {
        private var unitSprite:Sprite;
        private var _main:Main;
       
        public function Enemy(main:Main)
        {
            _main = main;
            unitSprite = new Sprite();
            unitSprite.graphics.lineStyle(2, 0xff0000, 1);
            unitSprite.graphics.beginFill(0xffffff, 1);
            unitSprite.graphics.drawRect(-25, -25, 50, 50);
            unitSprite.graphics.endFill();
            addChild(unitSprite);
           
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
       
        public function destroy():void
        {
            removeEventListener(Event.ENTER_FRAME, onEnterFrame);
            _main.stage.removeChild(this);
        }
       
        private function onEnterFrame(e:Event):void
        {
            this.x -= 2;
        }
       
    }

}

--------------------------------------------------------------------------------------------------------

Hero.as

Our hero is 60x60 white rectangle with green border








package HeroPkg
{
    import flash.display.Sprite;
    /**
     * ...
     * @author SpinnerBox
     */
    public class Hero extends Sprite
    {
        private var unitSprite:Sprite;
       
        public function Hero()
        {
            unitSprite = new Sprite();
            unitSprite.graphics.lineStyle(2, 0x00ff00, 1);
            unitSprite.graphics.beginFill(0xffffff, 1);
            unitSprite.graphics.drawRect(-30, -30, 60, 60);
            unitSprite.graphics.endFill();
            addChild(unitSprite);
        }
       
    }

}

---------------------------------------------------------------------------------------------------------

and Main.as

In main we add ENTER_FRAME listener to add new enemies and to check collisions using the QuadTree constructed in the constructor.
Note: We can use hitTestObject function only on DisplayObject or Sprite types of objects in AS3 so in insert() and retrieve() we send Sprite type of object instead of Rectangle and then we get the bounding rectangle by using getRect() function and sending  main.stage object to it like this

objects[i].getRect(_stage);

Remeber that _stage = main.stage. Once that our Hero rectangle has collided with enemy the enemy object gets destroyed.

package
{
    import CollisionDetectionPkg.QuadTree;
    import EnemyPkg.Enemy;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.display.StageScaleMode;
    import flash.geom.Rectangle;
    import HeroPkg.Hero;
  
    /**
     * ...
     * @author SpinnerBox
     */
    public class Main extends Sprite
    {
        private var enemyArray:Array;
        private var enemy:Enemy;
        private var hero:Hero;
        private var unitCounter:uint = 0;
        private var unitRate:uint = 40;
        private var quadTree:QuadTree;
      
        public function Main():void
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
      
        private function init(e:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            stage.scaleMode = StageScaleMode.NO_SCALE;
          
            quadTree = new QuadTree(0, new Rectangle(0, 0, 700, 550), this.stage);
            enemyArray = new Array();
          
            hero = new Hero();
            hero.x = 100;
            hero.y = 200;
            stage.addChild(hero);
      
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
      
        private function onEnterFrame(e:Event = null):void
        {
            hero.x = stage.mouseX;
            hero.y = stage.mouseY;
          
            if (unitCounter >= unitRate)
            {
                for (var i:uint = 1; i <= 5; i += 1 )
                {
                    var enemy:Enemy = new Enemy(this);
                    enemy.x = 750;
                    enemy.y = i*100;
                    stage.addChild(enemy);
                    enemyArray.push(enemy);
                }
              
                unitCounter = 0;
            }
            else
            {
                unitCounter += 1;
            }
          
            quadTree.clear();
            for each( var newEnemy:Enemy in enemyArray)
            {
                quadTree.insert(newEnemy);
            }

            var returnObjects:Array = new Array();

            quadTree.retrieve(returnObjects, hero);
            for (var k:int = 0; k < returnObjects.length; k += 1)
            {
                // Run collision detection algorithm between enemies and hero
                if (returnObjects[k].hitTestObject(hero))
                {
                    if (returnObjects[k].parent != null)
                    {
                        returnObjects[k].destroy();
                        returnObjects.splice(k, 1);
                    }      
                }
            }
          
          
            // clear memory from returned objects
            for (var m:int = 0; m < returnObjects.length; m += 1)
            {
                if (returnObjects[m] != null)
                {
                    returnObjects.splice(m, 1);
                }
            }
          
            // clear enemies if they reach x = -100
            for (var j:uint = 0; j <= enemyArray.length; j += 1 )
            {
                if (enemyArray[j] != null && enemyArray[j].x < -100)
                {
                    enemyArray[j].destroy();
                    enemyArray.splice(j, 1);
                }
            }
        }
    }
  
}


 Final result: When green square touches red square they get destroyed.


















I tried the compiled swf file on old Intel Celeron machine and it works still fairlly smooth.

Again thanks to TutsPlus and Steven Lambert for his awesome tutorial. Cheers :)

Tuesday, March 27, 2012

Tiny mp3 player tutorial using the xml editing tool

In this post I will examples on how to use the xml editing too that comes with tiny mp3 player component.

Here is a sample image of it:


The editor part are closely related to the structure of the xml playlist file that comes with the tiny mp3 player. Each song tag contains 4 attributes: dir, band, songTitle and songAlbum.

- dir is for directory i.e path of the sound file
- band is the name of the artist or band that composed the song. It will be shown on the player.
- songTitle is the name of the song
- songAlbum is the name of the album.

So to add new song to the playlist firts fill in the four textfields on the left and than press add song.
You can edit the generated xml at any time in the right panel. If you want to clear the generated xml press reset.

Here is a sample image of one song added:


Ok, so after adding 4 songs to the playlist the xml looks like this:


Now when finished editing open the playlist file which comes with the package and clear all text, copy the xml from the editor and paste it into the playlist.xml file. Than save it. thats it, you are done editing the xml file. Now you are ready to use the player.

Note: you can use also special characters from UTF-8 encoding

cheers :)

Tuesday, March 13, 2012

FXG - Inkscape demo


This is the demo I managed to develop using the flex sdk 4.6, Flash Develop 4 and Inkscape.
Click on the image and the light bulb will turn on and off. It is that easy to add other flash functionality to an fxg graphic.



Here is the code I used to develop this demo:

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import resources.BugattiVeyron;

    public class Main extends Sprite
    {
        private var bugatti:BugattiVeyron;
        private var lightBulb:Sprite;
        private var lightOn:Boolean;
        private var cable:Sprite;
        private var lighBulbSize:int;
      
        public function Main():void
        {
            if (stage)
                init();
            else
                addEventListener(Event.ADDED_TO_STAGE, init);
        }
      
        private function init(e:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
          
            // general settings
            lightOn = true;
            lighBulbSize = 40;
          
            // add the bugatti veyron fxg graphic
            bugatti = new BugattiVeyron();
            bugatti.addEventListener(MouseEvent.CLICK, clicked);
            addChild(bugatti);
          
            // create the light cable
            cable = new Sprite();
            cable.graphics.lineStyle(2, 0x000000);
            cable.graphics.moveTo(60, 0);
            cable.graphics.lineTo(60, 60);
            addChild(cable);
          
            // create the light bulb that hangs on the cable
            lightBulb = new Sprite();
            lightBulb.graphics.lineStyle(1, 0xFBEC5D);
            lightBulb.graphics.beginFill(0xEEE8AA);
            lightBulb.graphics.drawEllipse(lighBulbSize, lighBulbSize, lighBulbSize / 2, lighBulbSize / 2);
            lightBulb.graphics.endFill();
            lightBulb.x = 10;
            lightBulb.y = 10;
            addChild(lightBulb);
        }
      
        public function
clicked(e:MouseEvent):void
        {
            if (lightOn)
            {
                lightBulb.graphics.clear();
                lightBulb.graphics.lineStyle(1, 0x8B8B83);
                lightBulb.graphics.beginFill(0xCBCAB6);
                lightBulb.graphics.drawEllipse(lighBulbSize, lighBulbSize, lighBulbSize / 2, lighBulbSize / 2);
                lightBulb.graphics.endFill();
                lightOn = false;
            }
            else
            {
                lightBulb.graphics.clear();
                lightBulb.graphics.lineStyle(1, 0xFBEC5D);
                lightBulb.graphics.beginFill(0xEEE8AA);
                lightBulb.graphics.drawEllipse(lighBulbSize, lighBulbSize, lighBulbSize / 2, lighBulbSize / 2);
                lightBulb.graphics.endFill();
                lightOn = true;
            }
        }
   
    }

}



preety neat isnt it :)

FXG with Inkscape plugin tryout

- In this tryout I tried the fxg plugin for Inkscape. You can find them here svg2fxg.inx and svg2fxg.xsl Download them and put them in the Inkscape/share/extensions folder in Program Files on windows.
- Start  Inkscape and draw something. You have to have the option to save the document as an fxg file if the extension was succesffuly installed.

- So I used a Bugatti veyron image as a schetch to draw a vector based bugatti veyron in Inkscape
This is the result:


I created the image in Inkscape and saved it as BugattiVeyron.fxg. Then I created  flex sdk 4.6 and Flash Develop 4, AS3 plain project and imported this graphic onto the stage. Althoug I get some errors after compilation if you press the continue button in FlashDevelop and dissmis all errors afterwards you will get the above image. So it surely does work but with some errors.

Here is the code I used for the AS3 project

package
{
    import flash.display.Sprite;
    import flash.events.Event;
    import resources.BugattiVeyron;
   
     public class Main extends Sprite
    {
        private var bugatti:BugattiVeyron;
      
        public function Main():void
        {
            if (stage)
                init();
            else
                addEventListener(Event.ADDED_TO_STAGE, init);
        }
      
        private function init(e:Event = null):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
          
            // add the bugatti veyron fxg graphic
            bugatti = new BugattiVeyron();
            addChild(bugatti);
          
          }
      }

}


Surely you can use the Inkscape to export fxg graphics, but for the errors I get I will try to make another tutorial.

Cheers :)

Sunday, March 11, 2012

Sand Clock preloader how to...

Firstly here is the page of the preloader sand-clock-preloader

Quick preview of the component



The package includes  6 files, but the important for this tutorial are:

- Bottle.as
- SandClock.as
- SandClockPreloader.as

The first three are not relevant to this tutorial so I will not talk about them. The second three are what we are after.

Bottle.as

- Bottle.as is a class for showing the upper or lower glass pot of the sand clock. So SandClock.as instansiates two Bottle.as objects, one of which is flipped 180 degrees.
- I use drawPath command to draw the shpe of the upper/lower bottle. You can go and change the color of the glass but the quartz is most common for glass like objects. For drawing free shapes using the Graphics class please visit this sample

SandClock.as

- SandClock.as is the sand clock class which contains all it parts, like the two bottles, and the three wooden parts that hold the bottles.

- Find the liquidColor color in SandClock.as to change the color of the liquid. For example you can make it blue like some blue coctail or something :) 

- Find darkWoodColor and chocolateColor to change the fill and the stroke of the wooden parts accordingly.
 For example you can make them look like steel.  

- Find the tformat = new TextFormat(); segment on the bottom of the constructor to hange the formating of the preloader text. Maybe change font or color, size etc...

- SandClock.as has one very important function, it is called 

public function redrawBottle(percent:Number):void
{
       //code here......
}
This function draws the bottles with certain number of percents i.e how much percent is loaded in both upper and lower bottles. So if I use redrawBottle(49) that means the Sand clock will be redrawn to show (49%)  of the upper and (49%) of the lower bottle filled. (see above sample image).


SandClockPreloader.as
Has all the code you need to start using the sand clocl preloader. Here is a code part of it


        public function SandClockPreloader():void
        {
            delay = 100;
            repeat = 100;
            timer = new Timer(delay, repeat);
            timer.addEventListener(TimerEvent.TIMER, onTimerEvent);
            timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);

            // add preloader
            sandClock = new SandClock();
            sandClock.x = 300;
            sandClock.y = 135;
            sandClock.scaleX = sandClock.scaleY = 0.8;
            addChild(sandClock);
            timer.start();
        }

        public function onTimerEvent(e:TimerEvent):void
        {
            // when using redrawBottle() always use
            // 100 - percent because of the logic of the
            // preloader. It starts with 100% so
            // 100 - percent in order to start with 0%
            percentLoaded = 100 - timer.currentCount;
            sandClock.redrawBottle(percentLoaded);
        }

        public function onTimerComplete(e:TimerEvent):void
        {
            timer.reset();
            timer.start();
        }


As you can see i add timer for loading animation. But when using something to load you will measure the loading progress with the bytesLoaded and bytesTotal properties with Loader object. Have a look on the onTimerEvent function. I use these lines  

   percentLoaded = 100 - timer.currentCount;
   sandClock.redrawBottle(percentLoaded);


The mechanics is reversed i.e it goes from 100 to 0. Thats why I use 100 - percent in this case timer.currentCount. So that means you should do the same because it will now work properly. 

Next is the Loader example on how to use the redrawBottle function
 
     var swfLoader:Loader; 
 
     function loadSwf(url:String):void { 
           // Set properties on swfLoader object 
           swfLoader= new Loader(); 
           swfLoader.load(new URLRequest(url));                                                                                     swfLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, swfLoading); 
           swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoaded); 
     } 
    
     loadSwf("SandClockDemo.swf"); 
      
     function swfLoaded(e:Event):void { 
              // Load Image 
              swfContainer.addChild(swfLoader); 
     } 


     function swfLoading(e:ProgressEvent):void {
          percentLoaded = 100 - (e.bytesLoaded*100 / e.bytesTotal);
          sandClock.redrawBottle(percentLoaded); 

      }
 It uses ProgressEvent bytesLoaded and bytesTotal properties to get the loaded percent and subtract from 100 to get the real percent suitable for this component.


You might wanna visit this tutorial, it works with loading images but with swf is the same, just change the extension.


Happy flashing :)


FXG editor, pros and cons

In this post I will write about the FXG editor pros and cons. But as far as I was able to test it I am more not satisfied than satisfied :(

link to installation of the editor 

Here is a test image which I drew with the FXG editor:

 

Pros:

- This tool is good for fast and easy drawing, i.e things that are simple and easy to draw, like patterns, square shapes, circular shapes etc...

- It has lots of prebuilt tools for drawing, like circle, square, free hand drawing tool, bezier curve point to point tool,

- You can load image and strech it or rotate it.(See the monitor)

- You can add whichever shape and convert it to a path and edit it with the end-points, which is preety handy. (The romboid on the right top part of the image)

-  You can add a mask to an object to mask other objects.

Cons:

- You cannot adjust the alignment of the text i.e no left, justified, right alignment. You have to do it mannualy with space :) (I couln't align the text in the center)

- If you delete something you cannot restore it with ctrl-z.

- You have to add the "fxg" extension mannually :(

- If you load a saved file, it is more likely that the image showed will be changed by some not known circumstances :) and it will look different than the original. So you have to make again changes in order to restore it to the original. (the computer cable is brown instead of dark grey).

- You can import image only using URL path. There is no browse button so if you want to load image from local file system you have to open the image in browser and that copy and paste the the url into the URL field. Example:



- You cannot name a group with id attribute i.e there is no option for that in the right click menu. That means you cannot use the group like a MovieClip or Sprite in you AS3 project if you dont edit the fxg code yourself.
BTW if you add id attribute to different group elements in the fxg code if you load it again the editor will erase the id attributes :(

- There is no zooming option.

- If you add very small object on the stage, you are not able to move it properly. When you try that the mouse selects the object handles for streching and rotating so instead of moving you get streching and rotating functionality.

All in all this is not a tool for proffesional production of FXG file and its usage, but if you have small task it will do your job perfectly.

Speaker created using FXG and FXG editor AIR application

This is the image i deveoped using only the FXG editor which is an AIR application.


Quite good isn't it :)

FXG is an adobe xml specification format for creating vector based graphics, so you would be able to create graphics from scratch using only code. This format is good for people that need opensource solution for fast and easy creating and editing graphics. But also it can be used with most of graphics editing programs like Adobe Ilustrator, Adobe FireworksMicrosoft Expression Blend , FXG editor AIR app, Inkscape with FXG plugin, etc... You can edit vector based graphics and export it as an fxg file format which than can be used in Flash/Flex/AS3 based projects.

There are two versions by now for FXG format,  version 1 and 2.
FXG is much like SVG format but its not the same, there are lots of differences. But the main goal is the same.

This is just an intro to FXG, i will add some more content on version 1 and 2 and differences, pros and cons.

Happy flashing :)