UNPKG

ecspresso

Version:

A minimal Entity-Component-System library for typescript and javascript.

5 lines (3 loc) 7.5 kB
var b=((k)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(k,{get:(A,F)=>(typeof require<"u"?require:A)[F]}):k)(function(k){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+k+'" is not supported')});import{definePlugin as E}from"ecspresso";function M(k){if(typeof k==="number")return k;let[A,F]=k;return A+Math.random()*(F-A)}function D(k,A,F){if(k===A)return k;let L=k>>16&255,j=k>>8&255,q=k&255,H=A>>16&255,$=A>>8&255,Z=A&255,Q=L+(H-L)*F|0,V=j+($-j)*F|0,J=q+(Z-q)*F|0;return Q<<16|V<<8|J}var O=Math.PI*2;function G(k){let A=k.startSize??1,F=k.startTint??16777215;return Object.freeze({maxParticles:k.maxParticles,texture:k.texture,spawnRate:k.spawnRate??10,burstCount:k.burstCount??0,duration:k.duration??-1,lifetime:k.lifetime??1,speed:k.speed??100,angle:k.angle??[0,O],emissionShape:k.emissionShape??"point",emissionRadius:k.emissionRadius??0,gravity:Object.freeze(k.gravity??{x:0,y:0}),startSize:A,endSize:k.endSize??A,startAlpha:k.startAlpha??1,endAlpha:k.endAlpha??0,startTint:F,endTint:k.endTint??F,startRotation:k.startRotation??0,rotationSpeed:k.rotationSpeed??0,blendMode:k.blendMode??"normal",worldSpace:k.worldSpace??!0})}function C(k,A){return{particleEmitter:{config:k,activeCount:0,spawnAccumulator:0,elapsed:0,playing:A?.playing??!0,pendingBurst:0,finished:!1,onComplete:A?.onComplete}}}function R(k,A,F){let L=k.getComponent(A,"particleEmitter");if(!L)return!1;return L.pendingBurst+=F??L.config.burstCount,k.markChanged(A,"particleEmitter"),!0}function w(k,A){let F=k.getComponent(A,"particleEmitter");if(!F)return!1;return F.playing=!1,!0}function v(k,A){let F=k.getComponent(A,"particleEmitter");if(!F)return!1;return F.playing=!0,!0}function W(k,A,F,L,j){k.active=!0;let q=M(A.lifetime);if(k.life=q,k.maxLife=q,A.emissionShape==="circle"&&A.emissionRadius>0){let Z=Math.random()*O,Q=Math.random()*A.emissionRadius;k.x=F+Math.cos(Z)*Q,k.y=L+Math.sin(Z)*Q}else k.x=F,k.y=L;let H=M(A.speed),$=M(A.angle)+j;k.vx=Math.cos($)*H,k.vy=Math.sin($)*H,k.startSize=M(A.startSize),k.endSize=M(A.endSize),k.size=k.startSize,k.startAlpha=M(A.startAlpha),k.endAlpha=M(A.endAlpha),k.alpha=k.startAlpha,k.tint=A.startTint,k.rotation=M(A.startRotation),k.rotationSpeed=M(A.rotationSpeed)}function X(k,A,F,L,j,q){let H=k.config;k.elapsed+=F;let $=H.duration>=0&&k.elapsed>=H.duration;if(k.playing&&!$&&H.spawnRate>0){k.spawnAccumulator+=H.spawnRate*F;let B=Math.floor(k.spawnAccumulator);k.spawnAccumulator-=B;for(let U=0;U<B;U++){if(k.activeCount>=H.maxParticles)break;let z=A.particles[k.activeCount];if(!z)break;W(z,H,L,j,q),k.activeCount++}}if(k.pendingBurst>0){let B=Math.min(k.pendingBurst,H.maxParticles-k.activeCount);for(let U=0;U<B;U++){let z=A.particles[k.activeCount];if(!z)break;W(z,H,L,j,q),k.activeCount++}k.pendingBurst-=B}let Q=H.gravity.x,V=H.gravity.y,J=Q!==0||V!==0,N=H.startTint!==H.endTint,K=0;while(K<k.activeCount){let B=A.particles[K];if(!B)break;if(B.life-=F,B.life<=0){if(k.activeCount--,K<k.activeCount){let z=A.particles[k.activeCount];if(z){A.particles[K]=z,A.particles[k.activeCount]=B;let h=A.pixiParticles[K];A.pixiParticles[K]=A.pixiParticles[k.activeCount],A.pixiParticles[k.activeCount]=h}}B.active=!1;continue}if(J)B.vx+=Q*F,B.vy+=V*F;B.x+=B.vx*F,B.y+=B.vy*F;let U=1-B.life/B.maxLife;if(B.size=B.startSize+(B.endSize-B.startSize)*U,B.alpha=B.startAlpha+(B.endAlpha-B.startAlpha)*U,N)B.tint=D(H.startTint,H.endTint,U);B.rotation+=B.rotationSpeed*F,K++}}function _(k){let A=Array(k);for(let F=0;F<k;F++)A[F]={active:!1,x:0,y:0,vx:0,vy:0,life:0,maxLife:0,size:0,startSize:0,endSize:0,alpha:0,startAlpha:0,endAlpha:0,tint:16777215,rotation:0,rotationSpeed:0};return A}var I={explosion(k,A){return G({maxParticles:50,texture:k,spawnRate:0,burstCount:30,duration:1,lifetime:[0.3,0.8],speed:[100,300],angle:[0,O],startSize:[0.5,1.5],endSize:[0.1,0.3],startAlpha:1,endAlpha:0,...A})},smoke(k,A){return G({maxParticles:60,texture:k,spawnRate:15,duration:-1,lifetime:[1,3],speed:[20,60],angle:[-Math.PI/2-0.3,-Math.PI/2+0.3],startSize:[0.3,0.6],endSize:[1,2],startAlpha:0.4,endAlpha:0,...A})},fire(k,A){return G({maxParticles:80,texture:k,spawnRate:30,duration:-1,lifetime:[0.3,1],speed:[40,120],angle:[-Math.PI/2-0.5,-Math.PI/2+0.5],startSize:[0.5,1],endSize:[0.1,0.3],startAlpha:1,endAlpha:0,startTint:16746496,endTint:16720384,blendMode:"add",...A})},sparkle(k,A){return G({maxParticles:30,texture:k,spawnRate:10,duration:-1,lifetime:[0.5,1.5],speed:[10,40],angle:[0,O],startSize:[0.2,0.8],endSize:[0.1,0.4],startAlpha:[0.5,1],endAlpha:0,...A})},trail(k,A){return G({maxParticles:40,texture:k,spawnRate:20,duration:-1,lifetime:[0.3,0.8],speed:0,startSize:[0.5,1],endSize:[0.05,0.2],startAlpha:0.8,endAlpha:0,...A})}};function P(k){let{systemGroup:A="particles",priority:F=0,phase:L="update"}=k??{},j=new Map;return E("particles").withComponentTypes().withLabels().withGroups().withReactiveQueryNames().requires().install((q)=>{q.registerRequired("particleEmitter","localTransform",()=>({x:0,y:0,rotation:0,scaleX:1,scaleY:1})),q.registerDispose("particleEmitter",({entityId:H})=>{let $=j.get(H);if($){let Z=$.pixiContainer;if(Z)Z.removeFromParent?.(),Z.destroy?.();j.delete(H)}}),q.addSystem("particle-update").setPriority(F).inPhase(L).inGroup(A).addQuery("emitters",{with:["particleEmitter"]}).setProcess(({queries:H,dt:$,ecs:Z})=>{for(let Q of H.emitters){let V=Q.components.particleEmitter,J=j.get(Q.id);if(!J)J={particles:_(V.config.maxParticles),pixiContainer:null,pixiParticles:[]},j.set(Q.id,J);let N=Z.getComponent(Q.id,"worldTransform"),K=N?.x??0,B=N?.y??0,U=N?.rotation??0;X(V,J,$,K,B,U);let z=V.config;if(z.duration>=0&&V.elapsed>=z.duration&&V.activeCount===0&&!V.finished){if(V.finished=!0,V.onComplete)V.onComplete({entityId:Q.id});Z.commands.removeComponent(Q.id,"particleEmitter")}}}),q.addSystem("particle-render-sync").setPriority(400).inPhase("render").inGroup(A).setOnInitialize(async(H)=>{let $=await import("pixi.js"),Z=$.ParticleContainer,Q=$.Particle,V=H.tryGetResource("rootContainer");H.addReactiveQuery("particle-emitters",{with:["particleEmitter"],onEnter:(J)=>{let K=J.components.particleEmitter.config,B=new Z({dynamicProperties:{position:!0,rotation:!0,color:!0,vertex:!0}});B.blendMode=K.blendMode;let U=[];for(let h=0;h<K.maxParticles;h++){let S=new Q({texture:K.texture});S.alpha=0,U.push(S),B.addParticle(S)}let z=_(K.maxParticles);if(V)if(H.getComponent(J.id,"renderLayer"))V.addChild(B);else V.addChild(B);j.set(J.id,{particles:z,pixiContainer:B,pixiParticles:U})},onExit:(J)=>{let N=j.get(J);if(N){let K=N.pixiContainer;if(K)K.removeFromParent?.(),K.destroy?.();j.delete(J)}}})}).setProcess(({ecs:H})=>{for(let[$,Z]of j){let Q=H.getComponent($,"particleEmitter");if(!Q)continue;let V=Q.config;if(!V.worldSpace){let J=H.getComponent($,"worldTransform");if(J){let N=Z.pixiContainer;N.position.set(J.x,J.y),N.rotation=J.rotation,N.scale.set(J.scaleX,J.scaleY)}}for(let J=0;J<Q.activeCount;J++){let N=Z.particles[J],K=Z.pixiParticles[J];if(!N||!K)continue;K.x=N.x,K.y=N.y,K.scaleX=N.size,K.scaleY=N.size,K.rotation=N.rotation,K.tint=N.tint,K.alpha=N.alpha}for(let J=Q.activeCount;J<V.maxParticles;J++){let N=Z.pixiParticles[J];if(N)N.alpha=0}}})})}function x(k,A){return k.get(A)}export{w as stopEmitter,M as sampleRange,v as resumeEmitter,I as particlePresets,D as lerpTint,x as getEmitterData,G as defineParticleEffect,P as createParticlePlugin,C as createParticleEmitter,R as burstParticles}; //# debugId=60D36D4494C6248064756E2164756E21 //# sourceMappingURL=particles.js.map