from direct.interval.IntervalGlobal import * from direct.particles import ParticleEffect from direct.particles import Particles from direct.particles import ForceGroup from panda3d.core import * import random from FireworkGlobals import * colors = {WHITE: Vec4(1, 1, 1, 1), RED: Vec4(1, 0.2, 0.2, 1), BLUE: Vec4(0.2, 0.2, 1, 1), YELLOW: Vec4(1, 1, 0.2, 1), GREEN: Vec4(0.2, 1, 0.2, 1), PINK: Vec4(1, 0.5, 0.5, 1), PEACH: Vec4(0.9, 0.6, 0.4, 1), PURPLE: Vec4(1, 0.1, 1, 1), CYAN: Vec4(0.2, 1, 1, 1)} textures = {SNOWFLAKE: 'phase_8/models/props/snowflake_treasure', MUSICNOTE: 'phase_6/models/props/music_treasure', FLOWER: 'phase_8/models/props/flower_treasure', ICECREAM: 'phase_4/models/props/icecream', STARFISH: 'phase_6/models/props/starfish_treasure', ZZZ: 'phase_8/models/props/zzz_treasure'} fireworkId = 0 def getNextSequenceName(name): global fireworkId fireworkId += 1 return '%s-%s' % (name, fireworkId) def getColor(colorIndex): return colors.get(colorIndex) def getTexture(textureIndex): return loader.loadModel(textures.get(textureIndex)) def shootFirework(style, x = 0, y = 0, z = 0, colorIndex1 = 0, colorIndex2 = 0, amp = 10): func = style2shootFunc.get(style) color1 = getColor(colorIndex1) if style is CIRCLESPRITE: color2 = getTexture(colorIndex2) else: color2 = getColor(colorIndex2) if func and color1 and color2: return func(x, y, z, color1, color2, amp) def shootFireworkRing(x, y, z, color1, color2, amp): f = ParticleEffect.ParticleEffect() p0 = Particles.Particles('particles-1') p0.setFactory('PointParticleFactory') p0.setRenderer('SparkleParticleRenderer') p0.setEmitter('RingEmitter') p0.setPoolSize(100) p0.setBirthRate(0.01) p0.setLitterSize(100) p0.setLitterSpread(0) p0.factory.setLifespanBase(1.5) p0.factory.setLifespanSpread(0.5) p0.factory.setMassBase(1.0) p0.factory.setMassSpread(0.0) p0.factory.setTerminalVelocityBase(20.0) p0.factory.setTerminalVelocitySpread(2.0) p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT) p0.renderer.setUserAlpha(1.0) p0.renderer.setCenterColor(color1) p0.renderer.setEdgeColor(color2) p0.renderer.setBirthRadius(0.3) p0.renderer.setDeathRadius(0.3) p0.renderer.setLifeScale(SparkleParticleRenderer.SPNOSCALE) p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE) p0.emitter.setAmplitude(0) p0.emitter.setAmplitudeSpread(0) f0 = ForceGroup.ForceGroup('gravity') force0 = LinearSourceForce(Point3(x, y, z), LinearDistanceForce.FTONEOVERR, 0.1, 1.1 * amp, 1) force0.setActive(1) f0.addForce(force0) force1 = LinearSinkForce(Point3(x, y, z), LinearDistanceForce.FTONEOVERR, 0.5, 2.0 * amp, 1) force1.setActive(1) f0.addForce(force1) f.addForceGroup(f0) p0.emitter.setRadius(4.0) f.addParticles(p0) f.setPos(x, y, z) f.setHpr(0, random.random() * 180, random.random() * 180) sfx = loader.loadSfx('phase_4/audio/sfx/firework_distance_03.ogg') sfx.setVolume(0.7) t = Sequence(Func(f.start, render, render), Func(sfx.play), Wait(0.5), Func(p0.setBirthRate, 3), Wait(1.5), Func(f.cleanup), name=getNextSequenceName('shootFireworkRing')) t.start() def shootFireworkRocket(x, y, z, color1, color2, amp): f = ParticleEffect.ParticleEffect() p0 = Particles.Particles('particles-1') p0.setFactory('PointParticleFactory') p0.setRenderer('SparkleParticleRenderer') p0.setEmitter('SphereVolumeEmitter') p0.setPoolSize(110) p0.setBirthRate(0.01) p0.setLitterSize(2) p0.setLitterSpread(0) p0.factory.setLifespanBase(0.4) p0.factory.setLifespanSpread(0.1) p0.factory.setMassBase(1.0) p0.factory.setMassSpread(0.0) p0.factory.setTerminalVelocityBase(400.0) p0.factory.setTerminalVelocitySpread(0.0) p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT) p0.renderer.setUserAlpha(1.0) p0.renderer.setCenterColor(color1) p0.renderer.setEdgeColor(color2) p0.renderer.setBirthRadius(0.6) p0.renderer.setDeathRadius(0.6) p0.renderer.setLifeScale(SparkleParticleRenderer.SPNOSCALE) p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE) p0.emitter.setAmplitude(amp) p0.emitter.setAmplitudeSpread(0.0) p0.emitter.setRadius(0.3) f.addParticles(p0) gravityForceGroup = ForceGroup.ForceGroup('gravity') force0 = LinearVectorForce(Vec3(0.0, 0.0, -10.0), 1.0, 0) force0.setActive(1) gravityForceGroup.addForce(force0) f.addForceGroup(gravityForceGroup) f.setPos(x, y, z) sfxName = random.choice(('phase_4/audio/sfx/firework_whistle_01.ogg', 'phase_4/audio/sfx/firework_whistle_02.ogg')) sfx = loader.loadSfx(sfxName) sfx.setVolume(0.4) t = Sequence(Func(f.start, render, render), Func(sfx.play), LerpPosInterval(f, 2.0, Vec3(x, y, z + 20 * amp), blendType='easeInOut'), Func(p0.setBirthRate, 3), Wait(0.5), Func(f.cleanup), name=getNextSequenceName('shootFirework')) t.start() def shootPop(x, y, z, color1, color2, amp): sfxName = random.choice(('phase_4/audio/sfx/firework_distance_01.ogg', 'phase_4/audio/sfx/firework_distance_02.ogg', 'phase_4/audio/sfx/firework_distance_03.ogg')) sfx = loader.loadSfx(sfxName) t = Sequence(Func(sfx.play), Wait(3), name=getNextSequenceName('shootFireworkRocket')) t.start() def shootFireworkCircle(x, y, z, color1, color2, amp): return shootFireworkCircleGeneric(x, y, z, color1, color2, amp, 100) def shootFireworkCircleLarge(x, y, z, color1, color2, amp): return shootFireworkCircleGeneric(x, y, z, color1, color2, amp * 1.5, 200) def shootFireworkCircleSmall(x, y, z, color1, color2, amp): return shootFireworkCircleGeneric(x, y, z, color1, color2, amp * 0.5, 50) def shootFireworkCircleGeneric(x, y, z, color1, color2, amp, poolSize): f = ParticleEffect.ParticleEffect() p0 = Particles.Particles('particles-1') p0.setFactory('PointParticleFactory') p0.setRenderer('SparkleParticleRenderer') p0.setEmitter('SphereVolumeEmitter') p0.setPoolSize(poolSize) p0.setBirthRate(0.01) p0.setLitterSize(poolSize) p0.factory.setLifespanBase(2.0) p0.factory.setLifespanSpread(0.5) p0.factory.setTerminalVelocityBase(400.0) p0.factory.setTerminalVelocitySpread(40.0) p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAOUT) p0.renderer.setUserAlpha(1.0) p0.renderer.setCenterColor(color1) p0.renderer.setEdgeColor(color1) p0.renderer.setBirthRadius(0.4) p0.renderer.setDeathRadius(0.6) p0.renderer.setLifeScale(SparkleParticleRenderer.SPSCALE) p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE) p0.emitter.setAmplitudeSpread(0.1) p0.emitter.setAmplitude(amp) p0.emitter.setRadius(0.1) f.addParticles(p0) circleForceGroup = ForceGroup.ForceGroup('gravity') force1 = LinearSinkForce(Point3(x, y, z - 100), LinearDistanceForce.FTONEOVERRSQUARED, 2.0, 0.3 * amp * 0.1, 1) force1.setActive(1) circleForceGroup.addForce(force1) f.addForceGroup(circleForceGroup) f.setPos(x, y, z) sfxName = random.choice(('phase_4/audio/sfx/firework_explosion_01.ogg', 'phase_4/audio/sfx/firework_explosion_02.ogg', 'phase_4/audio/sfx/firework_explosion_03.ogg')) sfx = loader.loadSfx(sfxName) sfx.setVolume(0.7) t = Sequence(Func(f.start, render, render), Func(sfx.play), Wait(0.5), Func(p0.setBirthRate, 3), Wait(0.5), Func(p0.renderer.setCenterColor, color2), Func(p0.renderer.setEdgeColor, color2), Wait(1.5), Func(f.cleanup), name=getNextSequenceName('shootFireworkCircle')) t.start() def shootFireworkCircleSprite(x, y, z, color, texture, amp): f = ParticleEffect.ParticleEffect() p0 = Particles.Particles('particles-1') p0.setFactory('PointParticleFactory') p0.setRenderer('SpriteParticleRenderer') p0.setEmitter('SphereVolumeEmitter') p0.setPoolSize(100) p0.setBirthRate(0.01) p0.setLitterSize(100) p0.factory.setLifespanBase(2.0) p0.factory.setLifespanSpread(0.5) p0.factory.setTerminalVelocityBase(400.0) p0.factory.setTerminalVelocitySpread(40.0) p0.renderer.setAlphaMode(BaseParticleRenderer.PRALPHAUSER) p0.renderer.setUserAlpha(1.0) p0.renderer.setFromNode(texture) p0.renderer.setColor(color) p0.renderer.setXScaleFlag(1) p0.renderer.setYScaleFlag(1) p0.renderer.setInitialXScale(0.12) p0.renderer.setFinalXScale(0.48) p0.renderer.setInitialYScale(0.12) p0.renderer.setFinalYScale(0.48) p0.emitter.setEmissionType(BaseParticleEmitter.ETRADIATE) p0.emitter.setAmplitudeSpread(0.1) p0.emitter.setAmplitude(amp) p0.emitter.setRadius(0.1) f.addParticles(p0) circleForceGroup = ForceGroup.ForceGroup('gravity') force1 = LinearSinkForce(Point3(x, y, z - 100), LinearDistanceForce.FTONEOVERRSQUARED, 2.0, 0.3 * amp * 0.1, 1) force1.setActive(1) circleForceGroup.addForce(force1) f.addForceGroup(circleForceGroup) f.setPos(x, y, z) sfxName = random.choice(('phase_4/audio/sfx/firework_explosion_01.ogg', 'phase_4/audio/sfx/firework_explosion_02.ogg', 'phase_4/audio/sfx/firework_explosion_03.ogg')) sfx = loader.loadSfx(sfxName) sfx.setVolume(0.7) t = Sequence(Func(f.start, render, render), Func(sfx.play), Wait(0.5), Func(p0.setBirthRate, 3), Wait(2.0), Func(f.cleanup), name=getNextSequenceName('shootFireworkSprite')) t.start() style2shootFunc = {CIRCLE: shootFireworkCircle, CIRCLELARGE: shootFireworkCircleLarge, CIRCLESMALL: shootFireworkCircleSmall, CIRCLESPRITE: shootFireworkCircleSprite, ROCKET: shootFireworkRocket, RING: shootFireworkRing, POP: shootPop}