Mem leack in my particle emittor code.

BlitzMax Forums/BlitzMax Beginners Area/Mem leack in my particle emittor code.

Amon_old(Posted 2005) [#1]
Strict

Graphics 1024,768,16,0

Global particle_count:Int = 0
Global maxparticles:Int = 100
Global direction:Int = Rand(0,360)
Global mx:Int, my:Int

SeedRnd MilliSecs()

SetMaskColor 255,0,255

AutoMidHandle True

Global particles:TImage = LoadImage("particle.png",MASKEDIMAGE)

SetImageFont Null


Global particle_list:TList = CreateList()

Type particle

	Field x:Int, y:Int, d:Int, s:Int
	
		Function create()
		
			If MouseDown(	KEY_MOUSELEFT)
			
				Local p:particle = New particle
				p.x = mx
				p.y = my
				p.d = Rand(0,360)
				p.s = Rand(4,20)
				ListAddLast particle_list,(p)
			
			EndIf
			
		End Function
		
		Method draw()
		
			For Local p:particle = EachIn particle_list
			
				DrawImage particles,p.x,p.y,0
				
			Next
			
		End Method
		
		Function update()
			
						
			For Local p:particle = EachIn particle_list
			
				p.x = Sin(p.d) * p.s + p.x
				p.y = Cos(p.d) * p.s + p.y
				
			Next
			
		End Function
		
		Function destroy()
		
			For Local p:particle = EachIn particle_list
			
				If p.x > 1030 Or p.x < -2
				
					p = Null
					
				EndIf
				
				If p.y > 780 Or p.y < -2
				
					p = Null
					
				EndIf
				
			Next
				
		End Function
							
End Type

		

Repeat

	Cls
		
		mx = MouseX()
		my = MouseY()
		
		particle.create()
	
			For Local p:particle = EachIn particle_list
			
				p.draw()
			
			Next
		
		particle.update()
		particle.destroy()
				
	FlushMem
	
	Flip
	
	
		
Until KeyHit(KEY_ESCAPE)


I have a destroy function in my type. I call it then call flushmem but it still seems that it doesnt release the or destroy instances.

Any ideas?


Bot Builder(Posted 2005) [#2]
I dont think you are understanding how the garbage collector works. Yes, setting the programs only reference to a tpe to null will free it - but you must lose all methods of accessing the particle. The problem is that you are getting a reference from another source and then nullifying it. this does nothing. There is still a reference within the linked list to it.

Solution is to replace the code in destroy with:

particle_list.clear


you could nullify the list, flushmem and recreate but this is way cleaner


Ryan Moody(Posted 2005) [#3]
Because particle.update() and particle.destroy() should be in the For ... EachIn loop you defined above - in the code's current state, you don't know what "particle" is referring to.

By the way, there's some bad programming practice you've got there! I feel there should be no tests or loops in your type's functions - those should be handled in your main loop. I can't see how your code's managing to create the particles in the first place - you're calling the create method on an object called 'particle' which hasn't been instantiated. Funny that!

Ryan


Amon_old(Posted 2005) [#4]
Hi Bot Builder.

I've already tried particle.clear in my destroy function but all this does is remove all instances even if they have not left the screen borders. i.e. if one particle leaves the screen they all get cleared then the list begins again. This is not what I want to happen.

If one leaves the screen I want just that one particle to be removed and flushed. Not all of them.

How can I fix my code to allow this?


Amon_old(Posted 2005) [#5]
Hi Ryan. I'll try what you said.
Thanks :)


tonyg(Posted 2005) [#6]
Amon, this works...
Strict

Graphics 1024,768,16,0

Global particle_count:Int = 0
Global maxparticles:Int = 100
Global direction:Int = Rand(0,360)
Global mx:Int, my:Int

SeedRnd MilliSecs()

SetMaskColor 255,0,255

AutoMidHandle True

Global particles:TImage = LoadImage("particle.png",MASKEDIMAGE)

SetImageFont Null



Type particle
     Global particle_list:TList
	Field x:Int, y:Int, d:Int, s:Int
	
		Function create()
		     If particle_list = Null particle_list = CreateList()
			If MouseDown(	KEY_MOUSELEFT)
			
				Local p:particle = New particle
				p.x = mx
				p.y = my
				p.d = Rand(0,360)
				p.s = Rand(4,20)
				ListAddLast particle_list,(p)
			
			EndIf
			
		End Function
		
		Method draw()
		
			For Local p:particle = EachIn particle_list
			
				DrawImage particles,p.x,p.y,0
				
			Next
			
		End Method
		
		Function update()
			
						
			For Local p:particle = EachIn particle_list
			
				p.x = Sin(p.d) * p.s + p.x
				p.y = Cos(p.d) * p.s + p.y
				
			Next
			
		End function
		
		Method destroy()
					
       			If  x > 1030 Or x < -2 Or y > 780 Or y < -2
				
				   ListRemove(particle_list,Self)					
				EndIf
Rem				
				If p.y > 780 Or p.y < -2
				
					p = Null
					
				EndIf
End Rem				
				
		End Method
							
End Type

		

Repeat

	Cls
		
		mx = MouseX()
		my = MouseY()
		
		particle.create()
        If particle.particle_list
	
		For Local p:particle = EachIn particle.particle_list
			
			p.draw()
			
		Next
		EndIf
		particle.update()
     If particle.particle_list
		For Local p:particle = EachIn particle.particle_list
 		  p.destroy()	
   	 	Next
    EndIf			
	FlushMem
	DrawText MemAlloced(),0,0
	
	Flip
	
	
		
Until KeyHit(KEY_ESCAPE)


You have to remove the particle from the list rather than making the type instance null. I changed the code to have the loop in the mainloop which, I think, is better. I didn't change any of the others though.
<edit> I also changed the coord check to one line as I was getting errors.


Curtastic(Posted 2005) [#7]
instead of "p=null"
do "ListRemove particle_list,p"

The list contains a pointer to the particle. That is what keeps it alive


Amon_old(Posted 2005) [#8]
It works now.

Thanks Coorae and all :)