i'm having a difficult time understanding how to control the z property of display objects in a 3D space. i know how depth works, but what i don't understand is how i can get the maximum depth, or the number at which the display object just disappears into the background.
i assume depth is based on the stage's width and height, and that is why assigning the same depth of the same display object appars mismatched with different stage sizes.
so how can i appropriately measure depth?
You need to consider the childIndex property. There is no Z-index in actionscript.
To get the depth you could use:
// returns the number of direct display children in stage
stage.numChildren;
// returns the number of direct display children in you object
myObj.numChildren;
To set the child Z-index use
//sets the newIndex of child in stage
stage.setChildIndex(child:DisplayObject, newIndex:int):void;
If newIndex is 0 then child is top visible element.
newIndex must be in [0, numChildren-1] else flash will throw errors
Take care.
As of Flash 10, there is a 'z' property.
Checkout this link for a tutorial:
http://www.kirupa.com/developer/as3/intro_3d_as3_pg1.htm
it's explained here: Perspective in Flash
Related
I've noticed that most Flash games (and other SWFs) have foregrounds incorporated into them. The reason being to cover up graphic you're not supposed to see upon entering full screen (graphic outside the boundaries of the stage).
The foreground is simply a piece of graphic with a stage-sized hole in the middle, where the stage will show through. (Or that is what it seems to be, anyway).
What would be the simplest way to incorporate something like this into a Flash game? (In terms of highest childIndex etc). All help appreciated.
Masking is the best solution for this. You have to simply create a shape (rectangle or even circle or a complex set of drawing) and then setting it as mask. Then The masked viewport only shows the area of the mask's shape.
Take a look at this
http://www.republicofcode.com/tutorials/flash/as3masking/
stage.addChildAt(myMC,stage.numChildren-2);
This will add myMC to the stage at the z level that is just below the highest z-order (which should be where you put your border).
To explain further, numChildren returns the number of children that the DisplayObject it is called on has. But remember, the z-order index is "zero based" which means that if the parent display object has 12 children, the numChildren method will return 12, but the highest z-order index will be 11 and the first will be 0. So the highest z-order child will have an index of 'numChildren-1(this could be where the mask/border) and the highest level below that would benumChildren-2`.
I've included a zoom functionality similar to the one explained at this website:
http://www.flashandmath.com/howtos/zoom/
This works perfectly on my background image(a map, that is), but I want to keep the symbols on my map the same size while zooming in.
I probably could work this out by changing all the children's size when calling the zoom-function, but I am hoping there is some kind of easy code adapt in my children class to make the size of the instances unchangable. Is there?
Thanks!
One crude way, so you don't have to calculate the symbols scale, would be to remove the symbols from the mapDisplayObject so they're no longer a child and instead put symbol placeholders. Then match each symbol's x and y to each place holder, using localToGlobal...
If your children are not scaled or skewed or rotated you can iterate all of them and set transformation matrix to 1/parentScale. Something like:
for each (var child:DisplayObject in parent) {
var matrix:Matrix = child.transform.matrix;
matrix.a = 1/parentScale;
matrix.d = 1/parentScale;
child.transform.matrix = marix;
}
So I have trouble with the z-index,
all of my objects have z-index of 0, and as new objects are created they come above the ones that need to be in front.
I know about setting z index commands, but if I have 50 objects, I have to write and manually set z-index for each one, witch is kinda lame.
How can I fix this? This is probably simple but Im new to AS3.
If by z-index you mean the z value of a DisplayObject, that doesn't affect the layering of them. Depth ordering is handled by the display list of its parent.
You can make a DisplayObject go all the way to the back by using container.addChildAt(displayObject, 0); or container.setChildIndex(displayObject,0); if it's already added to that parent's display list.
You don't have to change the indexes of all other children of the same parent.
If you want something to be layered right behind another DisplayObject, first find out what the index of that child is:
var i:uint = container.getChildIndex(theOneToHideBehind);
and then set the index of your DisplayObject to that value:
container.setChildIndex(myDisplayObject, i);
I am trying to create a way of controlling movieclip depths, which movieclip is show above another, so that I can set the depth of a movieclip to any number and they will be displayed with higher values above lower values.
I was thinking of creating a MovieClipDepth class that extends MovieClip with the added property depth, and a Container class that extends DisplayObjectContainer which all objects will be placed inside of.
The Container class will override the addChild method to update the child display order when a child is added.
What I need help with is how do I reorder the children according to
their depth value?
As you can read in the comment below your question, there are several methods for this.
But actually, what you asked "set the depth of a movieclip to any number" can't really be done in AS3. If i'm correct, you could do this in AS2, so...
... how was it ...
_root.createEmptyMovieClip("mc", -1000);
or
_root.createEmptyMovieClip("mc1", 1);
_root.createEmptyMovieClip("mc2", 10);
worked, but does not work in AS3. In AS3 depth starts with 0 and you can't force a DisplayObject to sit on a level what is not continous from zero.
So the depths' of 3 movieclips in a container is only possible with these values: 0, 1, 2.
Depth can't be a negative number for example.
Now, if you want to build a custom depth manager, you can do that, but you have to consider these facts.
So to say, you could create virtual depths.
So I guess, you could override the addChildAt method for example. At the moment, if you would give a wrong number: negative, or higher then the number of children, flash would give back the error:
RangeError: Error #2006: The supplied index is out of bounds.
So mc.addChildAt(newchild, -1000) gives an arror.
But with overriding the method, you could make a trick, so you could store the depths in an array. You could store any numbers and then transform that order for the needs of AS3.
Like pairing the depths with the added children, sorting the array by the depths, then manage the children according to the order.
If you have more questions, feel free to ask, hope this gets you closer to the solution.
I suggest you take a look at this tutorial :
A Tour of Depths Management Methods on the website http://www.flashandmath.com/. I presume you not a newbie .
The link is this:
http://www.flashandmath.com/intermediate/depths/index.html
I want to move a display object from one container to another, but have it appear in the same place on screen.
I thought I'd understood this years ago, but the following does not work:
function moveToNewContainer(obj:DisplayObject, newParent:DisplayObjectContainer):void {
var pos:Point = new Point(obj.x, obj.y);
var currentParent:DisplayObjectContainer = obj.parent;
pos = currentParent.localToGlobal(pos);
currentParent.removeChild(obj);
newParent.addChild(obj);
pos = newParent.globalToLocal(pos);
obj.x = pos.x;
obj.y = pos.y;
}
This doesn't position the object in the same place as I would have expected.
Does anyone know what I am doing wrong, please?
Thanks,
James
Using localToGlobal/globalToLocal and setting the x and y properties like you showed calculates the correct position for the object in its new parent, but does not adjust for other aspects of the transformation such as scaling or rotation. In other words, the object's registration point will indeed remain in the same place, but the object may be rotated, scaled, or sheared differently.
The solution to your problem will need to take into account the transform.concatenatedMatrix properties of the old and new parents--you'll need to multiply the object's transformation matrix by one and then by the inverse of the other, or something along those lines. Leave a comment if you need help working out the math.
There is nothing wrong with your code, provided that both containers have no transformations applied. If your clips are scaled, rotated, etc.. you need to handle that in addition to the coordinate space transformations that localToGlobal and globalToLocal do.
You have to check if your containers are actually placed on stage. If your new container isn't added as a child to stage, function globalToLocal fails, just because it doesnt know how to correctly calculate that data.