• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Depth Manager

Guest
May 02, 2012 May 02, 2012

Copy link to clipboard

Copied

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

TOPICS
ActionScript

Views

1.9K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Advocate , May 10, 2012 May 10, 2012

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

Votes

Translate

Translate
Guest
May 04, 2012 May 04, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 04, 2012 May 04, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 04, 2012 May 04, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 04, 2012 May 04, 2012

Copy link to clipboard

Copied

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

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

                                        tmp_mc.rotation += 7;

                              }

                    }

                    private function ENTER_FRAME_2()

                    {

                              for (var i in array_THINGS)

                              {

                                        var tmp_mc:THING = THING(array_THINGS);

                                        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;

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
May 04, 2012 May 04, 2012

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 08, 2012 May 08, 2012

Copy link to clipboard

Copied

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

                                        tmp_mc.rotation += 7;

                                        tmp_mc.parent.setChildIndex(tmp_mc, i);

                              }

 

                              addChild(stats);

                    }

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
May 10, 2012 May 10, 2012

Copy link to clipboard

Copied

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.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 10, 2012 May 10, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
May 10, 2012 May 10, 2012

Copy link to clipboard

Copied

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...


Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
May 11, 2012 May 11, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
May 12, 2012 May 12, 2012

Copy link to clipboard

Copied

LATEST

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines