Skip navigation
XELAD111
Currently Being Moderated

Depth Manager

May 3, 2012 2:52 AM

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?)

 
Replies
  • Currently Being Moderated
    May 4, 2012 2:48 AM   in reply to XELAD111

    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

     
    |
    Mark as:
  • Currently Being Moderated
    May 4, 2012 2:54 AM   in reply to _spoboyle

    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

     
    |
    Mark as:
  • Currently Being Moderated
    May 4, 2012 3:36 AM   in reply to _spoboyle

    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;
     
    }
     
    
     
    |
    Mark as:
  • Currently Being Moderated
    May 8, 2012 2:25 AM   in reply to XELAD111

    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);

                        }

     
    |
    Mark as:
  • Currently Being Moderated
    May 10, 2012 4:16 AM   in reply to XELAD111

    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

     
    |
    Mark as:
  • Currently Being Moderated
    May 11, 2012 1:06 AM   in reply to XELAD111

    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/Arr ay.html#sortOn()

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points