Particle Problem: Not removed completly

Hi,

I have got a Problem. I have got an ExplosionClass which shall be completly removed from the game after the animation.

I don’t realy know why the Effect is still processed, so the game slows down after 10-15 Explosions ( which are not at the same time, but every 10 secs, so it is not just a temporal problem. It is constant )

The Explosion itself consists of 3 Fireballs and a Smoke ParticleSystem

The FireBall

class FireBall(DirectObject):
    def __init__(self):
        self.addTask(self.updateTask,"updateExplosionTask")
	self.dummy = render.attachNewNode("dummy")

	base.enableParticles()
        self.p = ParticleEffect()
	self.p.loadConfig(Filename("particles/fire_stream.ptf"))
	
	self.particleRenderNode = render.attachNewNode("expNode")

	self.effectTime = 500
	

	self.vec = Vec3(0,0,0)

	self.p.start(self.dummy, self.particleRenderNode)
   
    def setDirection(self,x,y,z):
	self.vec.setX(x)
 	self.vec.setY(y)
	self.vec.setZ(z)

    def setPos(self, obj):
	self.dummy.setPos(obj)
	self.dummy.setZ(self.dummy.getZ()+10)

    def updateTask(self, task):
	elapsed = globalClock.getDt()
	self.effectTime -= elapsed*50
	

	self.vec.setZ(self.vec.getZ()-elapsed*10)

	self.dummy.setPos(self.dummy.getPos()+self.vec)

	if self.effectTime <= 0:
		self.p.softStop()
		self.p.remove()
		self.ignoreAll()
		
		return Task.done	

	return Task.cont

The Explosion

class Explosion2(DirectObject):
    def __init__(self):
	self.file = ""
	print dir(self)	
	self.audio3d = None

	self.expSound = None

        self.addTask(self.updateTask,"updateExplosionTask")
 
	self.cTrav = CollisionTraverser()

        self.expSphere = CollisionSphere(0,0,0,1)
        self.expCol = CollisionNode('explosionSphere')
        self.expCol.addSolid(self.expSphere)
        self.expCol.setFromCollideMask(BitMask32.bit(1))
        self.expCol.setIntoCollideMask(BitMask32.allOff())
        self.expColNp = render.attachNewNode(self.expCol)
	self.expColNp.setPythonTag("object", self)
 	self.expHandler = CollisionHandlerQueue()
        self.cTrav.addCollider(self.expColNp, self.expHandler)
	print dir(self.cTrav)

	self.effectTime = 50
	self.expTime = 10
	self.damage = 100
	self.looseFac = 0
	self.size= 100


	self.load_file(self.file)
   	
 	self.p4 = ParticleEffect()
	self.p4.loadConfig(Filename("particles/explo_dust.ptf"))
	self.particleRenderNode = render.attachNewNode("expNode")
	self.p4.start(self.expColNp, self.particleRenderNode)

	self.p = FireBall()
	self.p.dummy.reparentTo(self.expColNp)
	self.p.setDirection(random.randint(0,5)-2.5,random.randint(0,5)-2.5,random.randint(0,5))

	self.p2 = FireBall()
	self.p2.dummy.reparentTo(self.expColNp)
	self.p2.setDirection(random.randint(0,5)-2.5,random.randint(0,5)-2.5,random.randint(0,5))

	self.p3 = FireBall()
	self.p3.dummy.reparentTo(self.expColNp)
	self.p3.setDirection(random.randint(0,5)-2.5,random.randint(0,5)-2.5,random.randint(0,5))



    def setPos(self, obj):
	self.expColNp.setPos(obj)

    def load_file(self, filename):


	if filename:
		self.file = filename
		f = file(filename)
		buffer = f.readlines()
		
		
		if self.audio3d:
			self.expSound = self.audio3d.loadSfx(buffer[0][:-1])
			self.audio3d.attachSoundToObject(self.expSound, NodePath(self.model))

		for i in buffer[1:]:
			l = i.split(" ")
			setattr(self, l[0], float(l[1]))


    def calcDamage(self):
	return self.damage / self.expSphere.getRadius()

    def updateTask(self, task):
	elapsed = globalClock.getDt()
	self.expSphere.setRadius(self.expSphere.getRadius()+elapsed*self.size)
	self.effectTime -= elapsed*50
	self.expTime -= elapsed*50

	self.cTrav.traverse(render)
	
	entries = []
	for i in range(self.expHandler.getNumEntries()):
	    entry = self.expHandler.getEntry(i)
	    entries.append(entry)
	entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
			     x.getSurfacePoint(render).getZ()))
	
	if len(entries) > 0:
		obj = entries[0].getIntoNode()
		what = entries[0].getIntoNode().getName()
		if obj :
			if what == "playerSphereTrigger":
				obj.getPythonTag("player").hit(self.calcDamage(), "Explosion", "Explosion")
	
	if self.expTime <= 0:
		self.cTrav.removeCollider(self.expColNp)
		self.expColNp.remove()

	if self.effectTime <= 0:
		self.ignoreAll()
		self.p4.softStop()
		self.p4.remove()
		return Task.done	

	return Task.cont

I realy need help for this else I can just have around 5 Explosions in the whole game. :frowning:

Thanks in advance

blenderkid

You need to clean up your ParticleEffect objects with p.cleanup() when you are done with them.

David

Cool now it works :smiley:

I had three attempts to make a good-looking explosion of a granade or a rocket… all failed :blush: :cry:

First problem I have:

My Explosion consists of ( now ) 6 Particle-Systems (PS) which play at one time. That runs fluidly, but the transparent parts of one PS overlapps the Particles of the others, so you can always see just the particles of one PS, although they should be all visible, because they are all transparent. So when two Particles of two different PS overlapp, just that one in the front is visible and it looks like there is nothing behind it.

Here is a picture of it http://filip.hasecke.com/stuff/particle-junk/image_view_fullscreen
( The level in the background is not finished yet )

  1. problem is:

My Explosion looks ugly. Do anyone tried to make an Explosion and has a good-looking one for me :slight_smile: :blush:

TIA

blenderkid

You’ll need to set some options on that particle render node in order to get transparency sorting to work right.

For example, I add my particles to a fixed render bin, and disable depth-writing. This guarantees that they are rendered after everything else, and with depth writing off I don’t have to worry about the order I render them.

You might can get away with just adding them to the back-to-front sort order bin, but I haven’t tested this.

        self.particles = render.attachNewNode ('particleRenderParents')
        self.particles.setLightOff()
        self.particles.setTransparency(TransparencyAttrib.MAlpha)
        self.particles.setBin ('fixed', 0)
        self.particles.setDepthWrite (False)
        self.particles.setShaderOff()

            particleParent = self.particles.attachNewNode('particleParent')
            particleParent.setPos (hitpos)
            
            dustParticleEffect = ParticleEffect()
            dustParticleEffect.loadConfig('data/particles/smallspark1.ptf')
            dustParticleEffect.start (particleParent, self.particles)

Hmm… Just a quick caveat: I think that Fenrir’s suggestion of using a fixed draw order doesn’t work properly for “normal” transparency, in which I think that the order of draws matters. While you may well get away with it for some effects, I’m not sure that you will for all.

It should be quite fine for additive transparency, I believe, however (one reason, as I recall, that I’ve in the past tended to try to stick to additive particles).