Drawing the units just in the order they are in the array results in many display errors. To solve this problem we have to add a Z-buffer that sorts the units so they get drawn in the correct order. Since this is a 2D engine Z-sorting happens in Y direction so a unit at 10, 8 is displayed behind a unit at 10, 12.
Lucky we are that we already have the units map where every unit is registered at. Now since the units map is a tile-based map we can't use if for the Z-buffer but we can use this map to get only the units that are on the screen. We add those indices to a list and then perform a Z-sort on this list so we get the indices in the correct drawing order. When done we can simply draw all units contained in this list.
To keep code clear I moved the code for drawing a unit into a new function called DrawUnit, you can look-up the complete code in the sample project. The only thing that changed was the DrawUnits function, we'll discuss this in code right now. I cutted the function into logical parts:
Public Sub DrawUnits() Dim A as Long Dim Done as Boolean Dim X as Long Dim Y as Long Dim Index as Long Dim UnitListCount as Long Dim UnitList() as Long
UnitList will hold the indices to sort. Each index stands for a unit in this list.
'Calculate start index Index = Int( ( Camera.Y / TileSize ) ) * Map.W + Int( ( Camera.X / TileSize ) ) UnitListCount = -1 'Draw the map For Y = 0 To Camera.TilesY For X = 0 To Camera.TilesX 'Check index If Index > ( Map.W * Map.H ) Then: Exit For
Instead of exiting the function we just continue after the loops now. This is because there's still code to execute after the loops this time.
'Get unit index If Map.Units( Index ) > 0 Then 'Allocate memory UnitListCount = UnitListCount + 1 ReDim Preserve UnitList( UnitListCount ) 'Add unit index UnitList( UnitListCount ) = Map.Units( Index ) End If
When there's a unit (index > 0) at the current position add that index to the UnitList.
'Next tile Index = Index + 1 Next 'Get next line start Index = Index + Map.W - Camera.TilesX - 1 Next
Nothing to explain here...
'Z-sort the list While Not Done Done = True For A = 0 To UnitListCount - 1 'If unit is in front of next unit If Unit( UnitList( A ) ).Y > Unit( UnitList( A + 1 ) ).Y Then 'Swap items Index = UnitList( A ) UnitList( A ) = UnitList( A + 1 ) UnitList( A + 1 ) = Index 'Check again Done = False End If Next Wend
This is called a bubble sort because it's the easiest way of sorting. The code just goes through all list items, compares a certain value and if necessary swaps those items in the list. This is repeated until all items are in the correct order. Quite slow but fast enough for a tile engine and easy to implement.
Here we performed a bubble sort to order the units by their Y property. Note again the deepness is done in Y direction in 2D top-down games!
'Now draw the sorted list For A = 0 To UnitListCount DrawUnit UnitList( A ) Next End Sub
Now that the list is sorted we can simply draw all the units.
We're done already, now your engine supports a nice little Z-buffer for the units (and only for the units!). Download the sample code and move your unit around others to check if it's working.