I have a 2.5D game (2D game that acts like a 3D game) where you constantly switch depths, where the player displays on top of an object when it walks in front of it and when it walks behind it, the object displays on top of the player. Like when the player's y is less than the object's y, the player would be going behind the object and vice versa.
I tried to use a code like this:
if (player.y < block.y)
{
setChildIndex(block, numChildren - 5);
}
else if (player.y > block.y)
{
setChildIndex(block, numChildren - 10);
}
However, I see if I do it this way with multiple times, I would need tons of codes and the display list would get mixed up and sort the wrong depths in the wrong orders. Would anyone please show an organized depth changer with minimal code?
Use a z-index stack sorting, (also refered as z-buffer
in the 3D graphics literature) the same used to create the 3D depth effect using just 2D techniques.
In other words assign to each object a zIndex
and at regular intervals (e.g onEnterFrame
event) run a zsort
routine which sorts (the order of) display objects based on their zIndex
value. Or, alternatively, you can run zsort
routine manualy each time a change of zIndex
happens on objects.
Then in your code you simply assign zIndex
values to display objects to simulate an object passing in-front or behind another object and zsort
takes care of the rest.
A trick here is to have appropriate gaps (i.e not necessarily next zIndex+1
) in the values of zIndex
assigned on objects, so that objects can be placed between these gaps to simulate passing in front or behind other objects, without having to adjust more than one zIndex
value each time, i.e you adjust only one zIndex
value of the object passing in-front or behind another object, and not the zIndex
of that other object.
The amount of gap between successive zIndexes
can be estimated from the maximum number of (other) objects which at any given time might be between these objects (so for example, if, at maximum, 3
objects might at some time move between, in-front or behind any given object, then a gap value for successive zIndexes
would be 3
so that all the objects can be accomodated)
here is a very simple zsorter
routine which runs periodicaly onEnterFrame
event and does the necessary depth sorting for you (from reference 1. below)
package {
import flash.display.*;
import flash.events.*;
public class DepthSortSpace extends MovieClip {
public function DepthSortSpace() {
super();
this.addEventListener( Event.ADDED_TO_STAGE, this.addedToStage, false, 0, true );
}
private function addedToStage( e:Event ) {
this.stage.addEventListener( Event.ENTER_FRAME, this.enterFrame, false, 0, true );
}
private function sortDisplayList():void {
var len:uint = numChildren;
var i,j;
for( i=0; i < len-1; i++ )
for (j=i+1; j < len; j++)
if ( getChildAt(i).y > getChildAt(j).y ) this.swapChildrenAt( i, j );
}
private function enterFrame(e:Event) {
this.sortDisplayList();
}
}
}
The zsorter
above is in-fact a movieClip
which acts as a scene
container, in that you add your display objects to the zsorter
movieClip and this takes care to sort them accordingly, but one can just take the zsort
routine and apply it to any DisplayObjectContainer
or Scene
object instance.
Note, the zsorter
above uses a bubbleSort
sorting algorithm, which has a O(n^2)
complexity, but one can use another sorting algorithm (e.g mergeSort
with O(n lgn)
complexity)
examples and references