unit typeParticleManager; interface uses SDL, typeParticle, typeParticleEmitter; type TParticleManager = class(TObject) private FParticles: DArray; FEmitters: DArray; FLastFrame: int64; protected function EmittParticlesInjector(const CurrentFrame, AEmitter : DObject) : DObject; function ProcessParticleInjector(const Frame, AParticle: DObject): DObject; procedure RemoveDeadParticles(const CurrentFrame: int64); procedure EmittNewParticles(FrameDelta: int64); procedure ProcessParticles(Frame: int64); public constructor Create; destructor Destroy; override; procedure AddEmitter(Emitter: TParticleEmitter); procedure ProcessFrame(Frame: int64); property Particles: DArray read FPArticles; end; implementation uses Windows; { TParticleManager } procedure TParticleManager.AddEmitter(Emitter: TParticleEmitter); begin FEmitters.pushBack([Emitter]); end; constructor TParticleManager.Create; begin FParticles := DArray.Create; FEmitters := DArray.Create; FLastFrame := 0; end; destructor TParticleManager.Destroy; begin FreeAndClear(FEmitters); FreeAndClear(FParticles); inherited; end; procedure TParticleManager.EmittNewParticles(FrameDelta: int64); begin inject(FEmitters, [FrameDelta], EmittParticlesInjector); end; function TParticleManager.EmittParticlesInjector(const CurrentFrame, AEmitter: DObject): DObject; var Emitter: TParticleEmitter; begin Emitter := asObject(AEmitter) as TParticleEmitter; Emitter.EmittParticles(asInt64(CurrentFrame), FParticles); result := CurrentFrame; end; procedure TParticleManager.ProcessFrame(Frame: int64); begin ProcessParticles(Frame); RemoveDeadParticles(Frame); EmittNewParticles(Frame); FLastFrame := Frame; end; function TParticleManager.ProcessParticleInjector(const Frame, AParticle: DObject): DObject; var particle: TParticle; begin particle := asObject(AParticle) as TParticle; particle.Update(asInt64(Frame)); result := make([asInt64(Frame)]); end; procedure TParticleManager.ProcessParticles(Frame: int64); begin inject(FPArticles, [Frame], ProcessParticleInjector); end; procedure TParticleManager.RemoveDeadParticles(const CurrentFrame: int64); var i: integer; particle: TParticle; begin i := 0; while (i < FParticles.size) do begin particle := FParticles.atAsObject(i) as TParticle; if particle.IsDead(CurrentFrame) then begin FParticles.removeAt(i); particle.free; end else inc(i); end; end; end.