The OrderedSortType property controls how Sprites and IDrawableBatches are ordered when they are drawn. Z Buffered Sprites do not use this property when drawing. The following available options exist:
SortType
Description
None
No sorting will be performed. Objects will be drawn in the order that they have been added to the SpriteManager.
Z
(Default) Objects will be sorted by their Z value. Objects further away (negative Z) will appear first in the list.
DistanceFromCamera
DistanceAlongForwardVector
ZSecondaryParentY
CustomComparer
The following code sets the SpriteManager's OrderedSortType to sort by distance from camera:
The following code creates 10 Sprites, rotates them on the X axis, and sizes them to be a little larger so they overlap. Setting the OrderedSortType to DistanceFromCamera results in the Sprites overlapping properly whether the Camera is above or below the Sprites.
The ZSecondaryParentY sort type is useful for top down and 3/4 view games. It allows moving objects (such as character entities) to be sorted based on their Y.
This is recommended for top-down and 3/4 view games. Note that Sprites use this sorting type only if they have the same Z. Therefore, if your entities have mulitple sprites with different Z values, they will interlace with other instances of the same entity.
For example if a character has a BodySprite and ShadowSprite, the ShadowSprite may have a Z value of -0.1 so that it always sorts behind the BodySprite of all other instances of the same entity type.
The following code shows how to set the OrderedSortType to ZSecondaryParentY:
For Sprites, the sorting is performed according to the sprite's parent. This allows sorting to be performed at a point other than the Sprite's origin (center) for more natural sorting. For example, consider a game with units with different sizes. In this situation, developers are advised to align the Sprite objects to the bottom of the entity. For example, the red X marks the origin of the entity:
If these origins are used, then units will sort properly according to where they are "standing" as shown in the following image:
The name ZSecondaryParentY suggests that objects are sorted by their Z value, then secondarily by their parents' Y value. Using a parent object (such as an entity) to control the sorting of a Sprite is useful (as shown above). Although IDrawableBatch implementations can have parents (especially if inheriting PositionedObject), IDrawableBatches are not required to have a parent. Therefore, the secondary sorting for IDrawableBatch instances is done by the Y property. While this limitation prevents using entities to set the origin of an IDrawableBatch, this can be resolved by offsetting the rendering of an IDrawableBatch so that its position marks its bottom. Furthermore, IDrawableBatch instances and Sprite will sort within the same category using Y values, but then Sprite vs. IDrawableBatch rendering is only performed by the Z value, even if the sort type is set to ZSecondaryParentY. If your game requires sorting Sprite vs. IDrawableBatch instances, you may need to adjust their Z value to force a particular sorting rather than relying on the Z value, or you may need to move all of your rendering to one type of object (either all Sprite or all IDrawableBatch).
The default OrderedSortType is SortType.Z. This sort type will result in Sprites overlapping incorrectly with the above example. To see the difference, replace the above code with:
Since all Sprites have an equal Z value (default of 0), then they are drawn in the order that they were added to the SpriteManager; from bottom-up. That means that the Sprites seen from below (at the top of the screen) will appear to overlap incorrectly.
The SortType.CustomComparer allows you to define custom sorting logic for your Sprites. The following shows how to create and use an IComparer that sorts all ordered Sprites along their X axis: Add the following using statement:
Add the following to Initialize after initializing FlatRedBall:
Define the SortByX class:
For simple games (or on faster platforms) the OrderedSortType will not have much impact on performance. However, it may be useful to adjust your sort type if possible for performance if you suspect that the sort type is impacting your frame rate. The fastest sort type is OrderedSortType.Z. This is a stable sorting algorithm performing O(n) operations, and each operation is simply a comparison of Z values. The next fastest is OrderedSortType.ZSecondaryParentY which is a stable sorting algorithm which performs simple comparisons, but it must do two passes to sort first along Z, then along the Parent Y. OrderedSortType.DistanceFromCamera is a stable sort also performong O(n) operations, but requies math operations for comparison. The slowest sort type is OrderedSortType.DistanceAlongForwardVector. Due to floating point errors this is not guaranteed to be a stable sort which hurts its performance. It must also perform numerous math operations per Sprite prior to performing sorting so it can be expensive. The performance of custom sorting is not defined because any type of sorting can be performed in custom code; however, this type of sorting is not stable and uses a binary sorting algorithm meaning it performs O(n*log(n)) operations.
Objects will be sorted by their distance from the
Objects will be sorted by their distance from the along a projection that is parallel to the forward vector. This is useful for sorting billboarded properly when the is rotated.
Sorts objects primarily by their Z value then secondarily by their Y value. This can be used to control how overlap in 3/4 view games. See below for more information on sorting between Sprite and IDrawableBatch instances.
Sorts objects based off of the SpriteComparer property. If CustomComparer is used but no SpriteComparer is set, then the default SortType.Z will be used.
The default ordering mode for Sprites in FlatRedBall is SortType.Z. The definition is rather straight forward - objects which have a Z that positions them further away from the Camera (smaller Z in all but FlatRedBall MDX) will be drawn first. Since closer Sprites are drawn after (within the same frame) Sprites which are further, they will overlap appropriately.
While it may be easy to image how Sprites with different Z values will draw, SortType.Z does not define how Sprites will be drawn when they have the same Z value. Of course, the engine doesn't use a random number generator to decide which should be drawn first - there is a method to it. Most articles which mention this topic encourage you to consider same-Z Sprites to have a random sorting order, but we'll cheat a little bit and explore. Internally FlatRedBall maintains a list of Sprites (as well as other ordered objects like Texts and IDrawableBatches). This list is sorted every frame just prior to drawing to guarantee proper ordering. It is very important that the sorting algorithm used is a "stable sorting algorithm". In other words, the sorting maintains the relative order of all same-Z Sprites. If this wasn't the case, then Sprites with the same Z value would shift positions every time the Sort method was called, causing them to flicker on screen. This means that if Sprite A is drawn on top of Sprite B, then it will *always* be drawn on top of B unless something in the program changes. Therefore, you might be thinking, there must be something that is controlling which is drawn on top of which. There is: For same-Z Sprites, the order is whichever Sprite was added first. Let's look at two blocks of code and their results to see this in action. This block of code adds two Sprites. The one on the right is added last. Since it is added last, it appears later in the list. Since FlatRedBall renders from the front to back of lists, Sprites added later will be drawn in front:
In the example above everything seems pretty clear and predictable - sprite2 is added after sprite1, so sprite2 will appear on top of sprite1 (assuming their Z values aren't changed). Of course, this code is far simpler than code you'll normally write when working with FlatRedBall. In many cases you won't be writing the code that actually creates Sprites. In the following cases the order of Sprite creation may be something you have no control over:
Loading Scenes - Scenes loaded from .scnx files often instantiate Sprites. The instantiation of these Sprites is done inside of FlatRedBall calls, so you do not control which Sprite is instantiated first. Furthermore, different tools may be written in different versions of FlatRedBall, so the way they sort Sprites may also differ.
SpiteGrids - SpriteGrids create and destroy Sprites if they are managed. This means that some Sprites in a SpriteGrid may be created at a much later time than other Sprites. It is possible to create situations where some Sprites in a SpriteGrid appear behind a large Sprite, while others appear in front when the SpriteGrid and the large Sprite all have the same Z.
Emitters - Emitters can continually create Sprites while they are alive. Since they are continually created you may not have control over their ordering relative to other Sprites with the same Z value.
You guessed it: Set your Z values. If you want to control how Sprites sort, then you should set Z values to prevent unexpected sorting.