11 Replies Latest reply: May 12, 2012 2:54 AM by XELAD111 RSS

    Depth Manager

    XELAD111

      Hello everyone. Here is a simple package with DepthManager, the question is in performance of it.

      1) Create .fla AS3, size = 600x400, grey background.

      2) Create in library a MovieClip, named THING, linkage = THING, and open it. Draw a 15-corner star in the centre of it. Fill by standart from-black-to-white linear gradient.

      3) Set the name MAIN as main class of the document (don't forget save them all in one directory), open it, and paste there this code:

       

      package 

      {

             import flash.display.MovieClip;

                import flash.events.Event;

                import flash.events.MouseEvent;

       

                public class MAIN extends MovieClip

                {

                         public var array_THINGS:Array = new Array();

                         public function MAIN()

                          {

                                    var tmp_thing:MovieClip;

       

                                    //BECAUSE I'M NOT GOING TO REMOVE THIS, I CAN USE ANONYMOUS FUNCTION

                                    stage.addEventListener(MouseEvent.MOUSE_UP, function()

                                    {

                                              //WE WILL CREATE SOME THINGS TO DISPLAY

                                              for(var i = 1; i <= 100; i++)

                                              {

                                                        tmp_thing = new THING();

                                                        tmp_thing.x = Math.random() * 600;

                                                        tmp_thing.y = Math.random() * 400;

                                                        //LETS MAKE IT EASIER FOR PLAYER BY SETTING cacheAsBitmap TO true

                                                        tmp_thing.cacheAsBitmap = true;

                                                        addChild(tmp_thing);

                                                        array_THINGS.push({INSTANCE:tmp_thing});

                                              }

                                    });

       

                                    stage.addEventListener(Event.ENTER_FRAME, function()

                                    {

                                              ENTER_FRAME_1(); //USING DepthMan

                                              //ENTER_FRAME_2(); //NOT USING DepthMan

                                             //MAKE ONE OF THOSE FUNCTIONS IN // TO SEE THE DEFFERENCE IN FRAMERATE

                                    });

                          }

       

                          private function ARRAY_THINGS_GET_POS_OF_OBJECT(element:*, index:int, arr:Array)

                          {

                                    var thing_x = MovieClip(element.INSTANCE).x;

                                    var thing_y = MovieClip(element.INSTANCE).y;

                                    return {INSTANCE:element.INSTANCE, X:thing_x, Y:thing_y};

                          }

       

                          private function ENTER_FRAME_1()

                          {

                                    var array_DETAILED_THINGS:Array = array_THINGS.map(ARRAY_THINGS_GET_POS_OF_OBJECT);

                                    array_DETAILED_THINGS.sortOn(["Y", "X"], [Array.NUMERIC, Array.NUMERIC | Array.DESCENDING]);

                                    for(var i in array_DETAILED_THINGS)

                                    {

                                              var tmp_mc:MovieClip = MovieClip(array_DETAILED_THINGS[i].INSTANCE);

                                              tmp_mc.rotation += 7;

                                              tmp_mc.parent.setChildIndex(tmp_mc, i);

                                    }

                          }

       

                          private function ENTER_FRAME_2()

                          {

                                    for(var i in array_THINGS)

                                    {

                                              var tmp_mc:MovieClip = MovieClip(array_THINGS[i].INSTANCE);

                                              tmp_mc.rotation += 7;

                                    }

                          }

                }

      }

       

      We click stage = we create 100 stars, each is rotated every frame.

      Each frame the function ARRAY_THINGS_GET_POS_OF_OBJECT gets the position of the INSTANCE (it's a simple example, imagine that things may move, so the constant position will not suite).

      Then things are sorted and reindexed.

      Code works.

      The main problem is:

      With the ENTER_FRAME_1() turned ON (and ENTER_FRAME_2() turned off, ofcourse), the framerate is much lower, when 300 things (3 clicks) and more on the stage. We don't have so big decline, not using DepthManager (ENTER_FRAME_1() turned OFF and ENTER_FRAME_2() turned ON). And I don't even mention, that a star has not much dots to draw. So the problem is in setting indexes, or may be even in Array.map().

      The tip is:

      There is a way to use swapDepths, adding an EnterFrame function to each thing, which will "understand", if the thing is higher or lower(.y) from its neighbours, whose depths +1, -1. So it will be one check but by each star... 

      The question is:

      Will it work faster? Or there is another way to make all this RUN?)

        • 1. Re: Depth Manager
          XELAD111 Community Member

          No one used dynamic depth manager? Nobody wrote code for games?

          • 2. Re: Depth Manager
            _spoboyle Community Member

            I only write code for games and no I have never used a dynamic depth manager

             

            for ENTER_FRAME_1 why do you sort the MoiveClips every frame? surely you could just do this each time the MovieClips are added in your mouse listener?

             

            also it would be a good idea to profile your code to find out where the bottleneck is

             

            and whether the swapDeths will be faster or not well the best way would be to try it and find out

            • 3. Re: Depth Manager
              _spoboyle Community Member

              also you are creating a new object for each star each frame this is not good

               

              I'd recommend subclassing MovieClip and have the result of ARRAY_THINGS_GET_POS_OF_OBJECT cached for each object

               

              this would stop the creation of hundreds of objects every frame and well as the overhead for the map() function

               

              i bet this is where the main loss of performance is

              • 4. Re: Depth Manager
                _spoboyle Community Member

                I have actually had a chance to play around with it now

                 

                and with 400 stars my ENTER_FRAME_1() runs at 10 fps and so does ENTER_FRAME2()

                 

                I am using

                 

                package
                {
                          import flash.display.MovieClip;
                          import flash.events.Event;
                          import flash.events.MouseEvent;
                
                          public class MAIN extends MovieClip
                          {
                                    public var array_THINGS:Array = new Array();
                                    private var stats:Stats = new Stats();
                
                                    public function MAIN()
                                    {
                                              stage.addEventListener(MouseEvent.CLICK, mouseUpHandler);
                                              stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
                                    }
                
                                    private function mouseUpHandler(e:MouseEvent):void
                                    {
                                              var tmp_thing:THING;
                                              //WE WILL CREATE SOME THINGS TO DISPLAY
                                              for (var i = 1; i <= 100; i++)
                                              {
                                                        tmp_thing = new THING();
                                                        tmp_thing.x = Math.random() * 600;
                                                        tmp_thing.y = Math.random() * 400;
                                                        //LETS MAKE IT EASIER FOR PLAYER BY SETTING cacheAsBitmap TO true
                                                        tmp_thing.cacheAsBitmap = true;
                                                        addChild(tmp_thing);
                                                        array_THINGS.push(tmp_thing);
                                              }
                
                                              array_THINGS.sortOn(["y", "x"], Array.NUMERIC | Array.DESCENDING);
                                              for (var j in array_THINGS)
                                              {
                                                        var tmp_mc:THING = THING(array_THINGS[j]);
                                                        tmp_mc.parent.setChildIndex(tmp_mc, j);
                                              }
                                              addChild(stats);
                                    }
                
                                    private function enterFrameHandler(e:Event):void
                                    {
                                              ENTER_FRAME_1(); //USING DepthMan
                                              //ENTER_FRAME_2(); //NOT USING DepthMan
                                              //MAKE ONE OF THOSE FUNCTIONS IN // TO SEE THE DEFFERENCE IN FRAMERATE
                                    }
                
                                    private function ENTER_FRAME_1()
                                    {
                                              for (var i in array_THINGS)
                                              {
                                                        var tmp_mc:THING = THING(array_THINGS[i]);
                                                        tmp_mc.rotation += 7;
                                              }
                                    }
                
                                    private function ENTER_FRAME_2()
                                    {
                                              for (var i in array_THINGS)
                                              {
                                                        var tmp_mc:THING = THING(array_THINGS[i]);
                                                        tmp_mc.rotation += 7;
                                              }
                                    }
                          }
                }
                
                
                

                 

                and a copy of MrDoobs stats class

                 

                 

                /**
                 * stats.as
                 * https://github.com/mrdoob/Hi-ReS-Stats
                 * 
                 * Released under MIT license:
                 * http://www.opensource.org/licenses/mit-license.php
                 *
                 * How to use:
                 * 
                 *          addChild( new Stats() );
                 *
                 **/
                
                
                package {
                
                          import flash.display.BitmapData;
                          import flash.display.Sprite;
                          import flash.events.Event;
                          import flash.events.MouseEvent;
                          import flash.geom.Matrix;
                          import flash.geom.Rectangle;
                          import flash.system.System;
                          import flash.text.StyleSheet;
                          import flash.text.TextField;
                          import flash.utils.getTimer; 
                
                
                          public class Stats extends Sprite { 
                
                
                                    protected const WIDTH : uint = 70;
                                    protected const HEIGHT : uint = 100;
                
                
                                    protected var xml : XML;
                
                
                                    protected var text : TextField;
                                    protected var style : StyleSheet;
                
                
                                    protected var timer : uint;
                                    protected var fps : uint;
                                    protected var ms : uint;
                                    protected var ms_prev : uint;
                                    protected var mem : Number;
                                    protected var mem_max : Number;
                
                
                                    protected var graph : BitmapData;
                                    protected var rectangle : Rectangle;
                
                
                                    protected var fps_graph : uint;
                                    protected var mem_graph : uint;
                                    protected var mem_max_graph : uint;
                
                
                                    protected var colors : Colors = new Colors();
                
                
                                    /**
                                     * <b>Stats</b> FPS, MS and MEM, all in one.
                                     */
                                    public function Stats() : void {
                
                                              mem_max = 0;
                
                
                                              xml = <xml><fps>FPS:</fps><ms>MS:</ms><mem>MEM:</mem><memMax>MAX:</memMax></xml>;
                
                                              style = new StyleSheet();
                                              style.setStyle('xml', {fontSize:'9px', fontFamily:'_sans', leading:'-2px'});
                                              style.setStyle('fps', {color: hex2css(colors.fps)});
                                              style.setStyle('ms', {color: hex2css(colors.ms)});
                                              style.setStyle('mem', {color: hex2css(colors.mem)});
                                              style.setStyle('memMax', {color: hex2css(colors.memmax)});
                
                                              text = new TextField();
                                              text.width = WIDTH;
                                              text.height = 50;
                                              text.styleSheet = style;
                                              text.condenseWhite = true;
                                              text.selectable = false;
                                              text.mouseEnabled = false;
                
                                              rectangle = new Rectangle(WIDTH - 1, 0, 1, HEIGHT - 50); 
                
                                              addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
                                              addEventListener(Event.REMOVED_FROM_STAGE, destroy, false, 0, true);
                
                                    }
                
                
                                    private function init(e : Event) : void {
                
                                              graphics.beginFill(colors.bg);
                                              graphics.drawRect(0, 0, WIDTH, HEIGHT);
                                              graphics.endFill();
                
                
                                              addChild(text);
                
                                              graph = new BitmapData(WIDTH, HEIGHT - 50, false, colors.bg);
                                              graphics.beginBitmapFill(graph, new Matrix(1, 0, 0, 1, 0, 50));
                                              graphics.drawRect(0, 50, WIDTH, HEIGHT - 50);
                
                                              addEventListener(MouseEvent.CLICK, onClick);
                                              addEventListener(Event.ENTER_FRAME, update);
                
                                    }
                
                
                                    private function destroy(e : Event) : void {
                
                                              graphics.clear();
                
                                              while(numChildren > 0)
                                                        removeChildAt(0); 
                
                                              graph.dispose();
                
                                              removeEventListener(MouseEvent.CLICK, onClick);
                                              removeEventListener(Event.ENTER_FRAME, update);
                
                                    }
                
                
                                    private function update(e : Event) : void {
                
                                              timer = getTimer();
                
                                              if( timer - 1000 > ms_prev ) {
                
                                                        ms_prev = timer;
                                                        mem = Number((System.totalMemory * 0.000000954).toFixed(3));
                                                        mem_max = mem_max > mem ? mem_max : mem;
                
                                                        fps_graph = Math.min(graph.height, ( fps / stage.frameRate ) * graph.height);
                                                        mem_graph = Math.min(graph.height, Math.sqrt(Math.sqrt(mem * 5000))) - 2;
                                                        mem_max_graph = Math.min(graph.height, Math.sqrt(Math.sqrt(mem_max * 5000))) - 2;
                
                                                        graph.scroll(-1, 0);
                
                                                        graph.fillRect(rectangle, colors.bg);
                                                        graph.setPixel(graph.width - 1, graph.height - fps_graph, colors.fps);
                                                        graph.setPixel(graph.width - 1, graph.height - ( ( timer - ms ) >> 1 ), colors.ms);
                                                        graph.setPixel(graph.width - 1, graph.height - mem_graph, colors.mem);
                                                        graph.setPixel(graph.width - 1, graph.height - mem_max_graph, colors.memmax);
                
                                                        xml.fps = "FPS: " + fps + " / " + stage.frameRate; 
                                                        xml.mem = "MEM: " + mem;
                                                        xml.memMax = "MAX: " + mem_max; 
                
                                                        fps = 0;
                
                                              }
                
                
                                              fps++;
                
                                              xml.ms = "MS: " + (timer - ms);
                                              ms = timer;
                
                                              text.htmlText = xml;
                                    }
                
                
                                    private function onClick(e : MouseEvent) : void {
                
                                              mouseY / height > .5 ? stage.frameRate-- : stage.frameRate++;
                                              xml.fps = "FPS: " + fps + " / " + stage.frameRate;  
                                              text.htmlText = xml;
                
                                    }
                
                
                                    // .. Utils
                
                
                                    private function hex2css( color : int ) : String {
                
                                              return "#" + color.toString(16);
                
                                    }
                
                          }
                
                }
                
                
                class Colors {
                
                
                          public var bg : uint = 0x000033;
                          public var fps : uint = 0xffff00;
                          public var ms : uint = 0x00ff00;
                          public var mem : uint = 0x00ffff;
                          public var memmax : uint = 0xff0070;
                
                }
                
                
                • 5. Re: Depth Manager
                  XELAD111 Community Member

                  Unfortunately my simple example doesn't show all the necessity of dynamic listening the actual position of each star, so I've mentioned imagine that things may move.

                  In fact, the example is too abstract. In the real code game, the stars are the pieces of grass on the ground. So we might use NOT dynamic DeMan. But also I have people, who move on that ground (walk), so depths should be always changed. So each frame AMV2 should understand, where is the thing, then sort the array of their pos... framerate falls down quickly, though flashPlayer easily processes 500+ "things" when DeMan is not used.

                  • 6. Re: Depth Manager
                    _spoboyle Community Member

                    reimplementing the sort to happen every frame still shows little degradation in frame rate:

                     

                    private function mouseUpHandler(e:MouseEvent):void

                                        {

                                                  var tmp_thing:THING;

                                                  //WE WILL CREATE SOME THINGS TO DISPLAY

                                                  for (var i = 1; i <= 100; i++)

                                                  {

                                                            tmp_thing = new THING();

                                                            tmp_thing.x = Math.random() * 600;

                                                            tmp_thing.y = Math.random() * 400;

                                                            //LETS MAKE IT EASIER FOR PLAYER BY SETTING cacheAsBitmap TO true

                                                            //tmp_thing.cacheAsBitmap = true;

                                                            addChild(tmp_thing);

                                                            array_THINGS.push(tmp_thing);

                                                  }

                                        }

                     

                    private function ENTER_FRAME_1()

                                        {

                                                  array_THINGS.sortOn(["y", "x"], Array.NUMERIC | Array.DESCENDING);

                                                  for (var i in array_THINGS)

                                                  {

                                                            var tmp_mc:THING = THING(array_THINGS[i]);

                                                            tmp_mc.rotation += 7;

                                                            tmp_mc.parent.setChildIndex(tmp_mc, i);

                                                  }

                     

                                                  addChild(stats);

                                        }

                    • 7. Re: Depth Manager
                      XELAD111 Community Member

                      Are you sure, that it is all code? I'm confused:

                      array_THINGS.sortOn(["y", "x"], Array.NUMERIC | Array.DESCENDING);

                      Can AS3 check and sort properties, which are not in array? Because you hadn't pushed .x and .y to array_THINGS.

                      • 8. Re: Depth Manager
                        _spoboyle Community Member

                        yes that is all the code

                         

                        as3 can sort arrays of objects on properties of those objects

                         

                        e.g. if you push 3 sprites into an array you can sort those sprites based any property of Sprite x, y, alpha, etc

                        • 9. Re: Depth Manager
                          XELAD111 Community Member

                          array_THINGS.sortOn(["y", "x"], Array.NUMERIC | Array.DESCENDING);

                          Not using Arrray.map() removes almost half of calculations!

                           

                          Thank you very much for your help, _spoboyle!

                           

                          Just tell me one last thing. I never knew about

                          if you push 3 sprites into an array you can sort those sprites based any property of Sprite
                          . From where you had found out that?) There are no such examples in reference/actionscript/3, and I never heard about that in AS2...


                          • 10. Re: Depth Manager
                            _spoboyle Community Member

                            the documentation for Array.sortOn() does give an example showing this

                             

                            instead of using sprites it uses a custom class called vegetable which has 2 properties name and price and the example sorts on price

                             

                            this is the same method and have Sprites and sorting on y for example

                             

                            http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#sortOn()

                            • 11. Re: Depth Manager
                              XELAD111 Community Member

                              Ou, now I get it) There were used user-defined properties, so I didn't thought of standart properties like x, y, alpha.

                              THANK YOU FOR YOUR HELP, _spoboyle