Flash Z-Buffer

Subscribe to Flash Z-Buffer 11 posts

Sign in to reply


 
avatar for Super_Llama Super_Llama 54 posts
Flag Post

I have various tall sprites in an isometric world, and I need a way to position them correctly depth-wise.

My old method is buggy and slow:

Iterate through each sprite, check if any other sprites SHOULD be on top, but are not, and swap the depth of the two if so.

The problem with this is that swapping messes up the depth of the other sprite and there are obvious artifacts left behind. As far as I know, there’s no way to simply put one on top of another without affecting the other sprites, and of course iterating through every visible sprite is rather slow (the map walls are made of the sprites.)

I’d use a conventional Z-Buffer, but I can’t find a way to do this with flash’s object system. I guess I could make the level draw each sprite manually on render instead of having each sprite be its own object, or I could make the sprite’s object invisible and only drawn when told to… but I’m not sure how to do this either.

Is there any way to override flash’s depth system for objects and draw them when and where you want regardless of what the child object says?

 
avatar for rarapompoms rarapompoms 184 posts
Flag Post

Your problem seems to be that you’re swapping the depths. Surely you just want to move the one that should be on top? If you want to bypass the display list completely you should look into blitting. You basically use copyPixels() to copy the bitmapdata to the stage. It’s a lot quicker than the display list as well so you’ll get a nice performance boost.

 
avatar for Super_Llama Super_Llama 54 posts
Flag Post

The problem is, the sprites are vector drawings made in flash 5 and embedded into FlashDevelop as a MovieClip. Is there any way to blit from these?

I should mention that they are animated and make fairly heavy use of gotoAndStop…

EDIT:

The system needs to work in the case of several sprites overlapping one another in a chain, and flash doesn’t seem to have a way to move something above something else without changing its depth in relation to another sprite.

Oh, and I’m using AS3

 
avatar for rarapompoms rarapompoms 184 posts
Flag Post

I not sure what the problem is exactly. You have objects in the display list in the wrong order:

s1
s3
s4
s2
s5

So you then you just cycle through them, and when you find one in the wrong place:

setChildIndex(s2, 2);


and you’ll get:

s1
s2
s3
s4
s5


?

 
avatar for JWBSoftware JWBSoftware 76 posts
Flag Post

In AS3 you’re better off thinking in terms of layers than depths. For isometric rendering e.g. you could do the following. Suppose your world is an 8 × 8 grid (a chessboard) viewed isometrically.

Create 15 Sprites, one for distance from the player. Something like this

01234567
12345678
23456789
3456789A
456789AB
56789ABC
6789ABCD
789ABCDE

0 – E being their names/indices in hex. Use addChild() to add them to a top level Sprite in index order. As that’s back to front the furthest corner of the chessboard from the player is at the corner marked 0. Add this sprite to your scene or MC for rendering.

Then to render a chess piece use addChild() add it to the Sprites with index (x + y), where x and y are it’s column and row on this grid. If it moves so (x + y) changes add it to the Shape with the new index (it’s removed automatically from the other).

This should work provided the objects are in separate grid squares, as in a game of chess. If they are closer/can occupy the same grid square you’ll need to add more layers or sort close objects within layers by distance from the player – or live with occasional flickering.

If your world is bigger you’ll need more layers, but never more than a + b – 1, where a and b are the dimensions of the grid you’re using. You can use other containers than Sprites but they are the most lightweight.

 
avatar for Super_Llama Super_Llama 54 posts
Flag Post

This all becomes more complicated when rotation is added. My isometric world is rotatable (I have drawings of each object at different angles), all objects are cubic, and can be shifted between tiles in 4 directions. They will generally occupy a single tile, but they’ll have to move smoothly from one to the other.

I suppose my current method isn’t that bad, it solves the depth rather quickly, and it could probably be modified to use setChildIndex instead of swapChildrenAt. All game objects are derived from one “BaseObj”, which handles the internal UV coordinates and converts them to XY, as well as picks the correct frame for the given angle. The graphics are specified in the derived classes, and Z-Ordering is handled by the Level class.

 
avatar for JWBSoftware JWBSoftware 76 posts
Flag Post

If the world’s rotatable my approach will still work, with a bit of extra work. you can either

1) maintain two lists of Sprites. One as above, the other from top right to bottom left. Each thing is added to both set: in one at (x + y) the other at (7 – x + y), and updated as it moves. Then add these sprites to four top level sprites, one for each look direction, Switch between them as you rotate, i.e. you only ever draw one. The extra overhead comes from maintaining both lists, which scales with the complexity of your world and the number of things moving at once.

2) Or maintain one list, as in my 1st post, for the current direction. If the user changes direction simply re-create it based on the new direction. This sounds expensive but it only happens with a view change so the user won’t notice the e.g. few frames it takes. The rest of the time it runs the same speed.

Smooth moving’s not a problem, as long as things never occupy the same grid square. So e.g. if a pawn moves smoothly from one empty square to another it should cleanly transition between layers without overlapping in either. The only problem is if two things are closer than this, so they’re in the same layer but in front of each other: you can detect this and sort them within the layer, or make sure it never happens, or even ignore it if your design calls for some other approach to sorting.

 
avatar for Super_Llama Super_Llama 54 posts
Flag Post

Forgot to mention that there are 32 degrees of rotation it can assume. Since the objects are vector-drawings and rather simple, it doesn’t hurt size-wise to have that many frames, but it seems like it could make z-sorting a lot harder. Plus, the levels are on the order of 30×30 tiles (most are not filled in though). The graphics have been made, but the current z-sorting algorithm is rather atrocious. The way things work currently ends up with a lot of tiles like this:

s5
s4
s3
s2
s1

or also like this:

s1
s4
s5
s2
s3

I need to find a way to sort them quickly and efficiently in a single frame…

I also tried a z-buffer method where each object “claims” tiles when it’s drawn and any objects drawn on those tiles attempt to switch places with its original owner if they’re behind… it sounds fool-proof, but for some reason it simply does not work. Things get “stuck” on top, and bounce back and forth in the array… extremely obvious.

 
avatar for JWBSoftware JWBSoftware 76 posts
Flag Post

If you’ve 32 directions of view it’s not really isometric: with isometric you’ve got at most eight, and that’s if you include the views from below. And for directions other than NW, NE, SW, SE I don’t think my approach would work, or at least it would be much more complex.

I think you’re looking at something more like a general z-sort, though hopefully with discrete view directions and with the angles between view directions being small (11.25°) you can won’t ever need to do a full re-sort once everything has started: just use bubble sort to sort things by z, using swapChildren() as you do.

 
avatar for Super_Llama Super_Llama 54 posts
Flag Post

I suppose what I’m doing now isn’t all bad. It works okay:
Wall Test
Animated Test same controls

But there are still flicker-artifacts on edges.

I think I’m going to end up precompiling things so stationary objects (the metal boxes) simply don’t have the sides that would conflict with nearby metal boxes, then exclude them from z-sorting. That way only the moving objects would have to be sorted, saving time, and the larger, more important portions of the level (structure, made with the metal boxes) wouldn’t matter anyway.

 
avatar for JWBSoftware JWBSoftware 76 posts
Flag Post

You can include static objects in your sort. That’s why I recommended bubble sort. Slow for a general sort but it works well when either few things are out of place or things aren’t out of place by much. So it works very well when z-sorting a scene that’s mostly static and where things haven’t moved much since the last sort 33ms ago. It’s also about the easiest sort algorithm to implement which is a plus.

Sign in to reply