1 /**
2     Particle    
3 
4     Copyright: (c) Enalye 2017
5     License: Zlib
6     Authors: Enalye
7 */
8 
9 module atelier.core.particle;
10 
11 import std.random;
12 
13 import atelier.render;
14 
15 import atelier.core.vec2;
16 import atelier.core.color;
17 import atelier.core.stream;
18 import atelier.core.indexedarray;
19 import atelier.core.particlefilter;
20 
21 /+
22 class Particle {
23 	Vec2f position, velocity;
24 	float time, timeToLive;
25 	float scale, spriteAngle, spriteAngleSpeed;
26 	Color color;
27 }
28 
29 class ParticleSource {
30 	IndexedArray!(Particle, 5000u) particles;
31 	IndexedArray!(ParticleFilter, 20u) filters;
32 	Sprite sprite;
33 	Vec2f position = Vec2f.zero;
34 	
35 	private {
36 		float _timeUntilNextSpawn = 0f;
37 	}
38 
39 	float timeToLive = 1f, timeToLiveDelta = 0f;
40 	float spawnDelay = 1f, spawnDelayDelta = 0f;
41 	float scale = 1f, radius = 1f, angle = 0f, angleDelta = 0f, speed = 1f, speedDelta = 0f;
42 
43 	this() {
44 		particles = new IndexedArray!(Particle, 5000u);
45 		filters = new IndexedArray!(ParticleFilter, 20u);
46 	}
47 
48 	void update(float deltaTime) {
49 		foreach(Particle particle, uint index; particles) {
50 			particle.time += deltaTime;
51 			float t = particle.time / particle.timeToLive;
52 			if(t > 1f)
53 				particles.markInternalForRemoval(index);
54 			else {
55 				foreach(filter; filters) {
56 					filter.apply(particle, deltaTime);
57 				}
58 
59 				particle.position += particle.velocity * deltaTime;
60 				particle.spriteAngle += particle.spriteAngleSpeed * deltaTime;
61 			}
62 		}
63 
64 		float random(float step, float delta) {
65 			if(delta == 0f)
66 				return step;
67 			return uniform!"[]"((1f - delta) * step, (1f + delta) * step);
68 		}
69 
70 		float random2(float step, float delta) {
71 			if(delta == 0f)
72 				return step;
73 			return uniform!"[]"(step - delta / 2f, step + delta / 2f);
74 		}
75 
76 		particles.sweepMarkedData();
77 		_timeUntilNextSpawn -= deltaTime;
78 		if(_timeUntilNextSpawn < 0f) {
79 			_timeUntilNextSpawn = random(spawnDelay, spawnDelayDelta);
80 
81 			auto particle = new Particle;
82 			particle.position = position + Vec2f.angled(uniform(0f, 360f)) * (radius > 1f ? uniform(0f, radius) : 1f);
83 			particle.time = 0f;
84 			particle.timeToLive = random(timeToLive, timeToLiveDelta);
85 			if(particle.timeToLive == 0f)
86 				particle.timeToLive = 1f;
87 
88 			float angle = random2(angle, angleDelta);
89 			particle.velocity = Vec2f.angled(angle) * random(speed, speedDelta);
90 			particle.scale = scale;
91 
92 			particle.color = Color.white;
93 			particles.push(particle);
94 		}
95 	}
96 
97 	void draw() {
98 		if(sprite.texture is null) {
99 			foreach(Particle particle, uint index; particles) {
100 				float t = particle.time / particle.timeToLive;
101 				drawFilledRect(particle.position, Vec2f.one * particle.scale, particle.color);
102 				
103 			}
104 		}
105 		else {	
106 			foreach(Particle particle, uint index; particles) {
107 				float t = particle.time / particle.timeToLive;
108 				sprite.scale = Vec2f.one * particle.scale;
109 				//sprite.angle = particle.spriteAngle;
110 				sprite.color = particle.color;
111 				sprite.draw(particle.position);
112 			}
113 		}
114 	}
115 
116 	void save(OutStream stream) {
117 		stream.write!float(timeToLive);
118 		stream.write!float(timeToLiveDelta);
119 		stream.write!float(spawnDelay);
120 		stream.write!float(spawnDelayDelta);
121 		stream.write!float(scale);
122 		stream.write!float(radius);
123 		stream.write!float(angle);
124 		stream.write!float(angleDelta);
125 		stream.write!float(speed);
126 		stream.write!float(speedDelta);
127 	}
128 
129 	void load(InStream stream) {
130 		timeToLive = stream.read!float();
131 		timeToLiveDelta = stream.read!float();
132 		spawnDelay = stream.read!float();
133 		spawnDelayDelta = stream.read!float();
134 		scale = stream.read!float();
135 		radius = stream.read!float();
136 		angle = stream.read!float();
137 		angleDelta = stream.read!float();
138 		speed = stream.read!float();
139 		speedDelta = stream.read!float();
140 	}
141 }+/