Custom Compare() method causes problems...

BlitzMax Forums/BlitzMax Programming/Custom Compare() method causes problems...

Hi,
Below you find a very familiar piece of code for managing all elements in your game.
I was experimenting with the Compare() method to change the order of the list. In that way I'm able to draw elements in the correct order on the screen if I give each element a Z-value (higher values are on top of lower values). This works great (you can try) but if you have more than one element with the same Z-value (which should be possible) you can not remove that element from the list with the provided functions: Remove(), RemoveLink() or ListRemove() because these functions use the Compare() method to find the right link in the list.

I would like to keep the z-ordeing thing AND be able to manage the list properly.
Any ideas how to solve this?
Type TElement
	Global glElements:TList

	Field piZ% = 0			'used for layering the sprites (higher Z-values are on top of lower Z-values)

	Method New() 
		If Not glElements Then glElements = CreateList() 
		glElements.AddLast(Self) 
	End Method
	
	Method Kill() 
'none of these functions work because they all use Compare() to find the proper link :(
'		RemoveLink(ListFindLink(glElements, Self)) 
'		ListRemove(glElements, Self)
		glElements.Remove(Self) 
	End Method
		
   Function UpdateAll() 
      For Local e:TElement = EachIn glElements
         e.update() 
      Next
   End Function
	
'	You must actively call this function in order to get all sprites sorted by Z-value (performance issue)
'	optional argment 'bAscending' can be used to sort the sprites reversed (highest Z-value first)  
	Function SortZ(bAscending% = True) 
		glElements.Sort(bAscending) 
	End Function
		
'	This method is used for sorting the glSprites list in Z-order (ascending)
	Method Compare%(OtherObj:Object) 
		Local e:TElement = TElement(OtherObj) 
		If Not e Return Null
		Return piZ - e.piZ
	End Method


'	Abstract Methods
	Method Update() Abstract
	Method Draw() Abstract

'	----------------
End Type


Hello.

Erase your method Compare() from TElement and change the method SortZ() with a pointer to compareFunc%( o1:Object,o2:Object )

Bye,
Paposo

Your english is fine :) but I don't think I understand your suggestion.
Do you mean: "write your own SortZ() and Compare() methods"?
Can you give an example?

Seems to work fine here :

Your code with some test stuff added...
Type TElement
	Global glElements:TList

	Field piZ% = 0			'used for layering the sprites (higher Z-values are on top of lower Z-values)

	Method New() 
		If Not glElements Then glElements = CreateList() 
		glElements.AddLast(Self) 
	End Method
	
	Method Kill() 
'none of these functions work because they all use Compare() to find the proper link :(
'		RemoveLink(ListFindLink(glElements, Self)) 
'		ListRemove(glElements, Self)
		glElements.Remove(Self) 
	End Method
		
   Function UpdateAll() 
      For Local e:TElement = EachIn glElements
'         e.update() 
      Next
   End Function
	
'	You must actively call this function in order to get all sprites sorted by Z-value (performance issue)
'	optional argment 'bAscending' can be used to sort the sprites reversed (highest Z-value first)  
	Function SortZ(bAscending% = True) 
		glElements.Sort(bAscending) 
	End Function
		
'	This method is used for sorting the glSprites list in Z-order (ascending)
	Method Compare%(OtherObj:Object)
		Local e:TElement = TElement(OtherObj) 
		If Not e Return Null
		Return piZ - e.piZ
	End Method


'	Abstract Methods
	'Method Update() Abstract
	'Method Draw() Abstract

'	----------------
End Type

Local e:TElement = New TElement
e.piZ = 3

e = New TElement
e.piZ = 1


e = New TElement
e.piZ = 5

DebugLog "Ascending..."
TElement.SortZ()

For e = EachIn TElement.glElements
	DebugLog e.piZ
Next

DebugLog "Descending..."
TElement.SortZ(False)

For e = EachIn TElement.glElements
	DebugLog e.piZ
Next


Like this:

function sortZ(bAscending:int=true)
  gElements.sort(bAscending,comparar)
end function

function comparar:int(Object o1, Object o2)
  local e1:TElement = TElement(o1) 
  local e2:TElement = TElement(o2)
  return o2.piZ-o1.piZ
end function


You not need the method compare%

Bye,
Paposo

@Paposo: thanks!
I didn't know about the second argument in the list.Sort() function.

I made some corrections in your code:
	Function SortZ(bAscending% = True) 
		glElements.Sort(bAscending, CompareZ) 
	End Function
		
'	This function is used for sorting the glSprites list in Z-order (ascending)
	Function CompareZ:Int(o1:Object, o2:Object) 
		Local e1:TElement = TElement(o1) 
		Local e2:TElement = TElement(o2) 
		Return e1.piZ - e2.piZ
	End Function


<edit> ... too late.
Kistjes, it is so much easier if you had provided a working example showing the issue. That way people are more inclined to change it and repost.

@tonyg: You're right. Combining the brucey's and Paposo code will result in a working example.
Ok, here it is (with some additions):
Type TElement
	Global glElements:TList

	Field piZ% = 0			'used for layering the sprites (higher Z-values are on top of lower Z-values)
	Field psName$
	
	Method New() 
		If Not glElements Then glElements = CreateList() 
		glElements.AddLast(Self) 
	End Method
	
	Method Kill() 
'none of these functions work because they all use Compare() to find the proper link :(
'		RemoveLink(ListFindLink(glElements, Self)) 
'		ListRemove(glElements, Self)
		glElements.Remove(Self) 
	End Method
		
   Function UpdateAll() 
      For Local e:TElement = EachIn glElements
'         e.update() 
      Next
   End Function
	
'	You must actively call this function in order to get all sprites sorted by Z-value (performance issue)
'	optional argment 'bAscending' can be used to sort the sprites reversed (highest Z-value first)  
	Function SortZ(bAscending% = True) 
		glElements.Sort(bAscending, CompareZ) 
	End Function
		
'	This function is used for sorting the glSprites list in Z-order (ascending)
	Function CompareZ:Int(o1:Object, o2:Object) 
		Local e1:TElement = TElement(o1) 
		Local e2:TElement = TElement(o2) 
		Return e1.piZ - e2.piZ
	End Function


'	Abstract Methods
	'Method Update() Abstract
	'Method Draw() Abstract

'	----------------
End Type

Local e:TElement = New TElement
e.piZ = 3
e.psName = "Three"

e = New TElement
e.piZ = 1
e.psName = "One"
'add another element with z = 1
Local e1:TElement = New TElement
e1.piZ = 1
e1.psName = "Second One"
e = New TElement
e.piZ = 5
e.psName = "Five"

DebugLog "Ascending..."
TElement.SortZ()

For e = EachIn TElement.glElements
	DebugLog e.piZ + " - "+e.psName
Next

DebugLog "Descending..."
TElement.SortZ(False)

For e = EachIn TElement.glElements
	DebugLog e.piZ + " - "+e.psName
Next

DebugLog "Kill an element"
e1.Kill()

For e = EachIn TElement.glElements
	DebugLog e.piZ + " - "+e.psName
Next




ooopsss.

Sorry the little bug :) Copy ... paste... ejem

Bye,
Paposo