Starsector API
Loading...
Searching...
No Matches
NegativeExplosionVisual.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat;
2
3import java.util.Arrays;
4import java.util.EnumSet;
5
6import java.awt.Color;
7
8import org.lwjgl.opengl.GL11;
9import org.lwjgl.util.vector.Vector2f;
10
11import com.fs.starfarer.api.Global;
12import com.fs.starfarer.api.combat.BaseCombatLayeredRenderingPlugin;
13import com.fs.starfarer.api.combat.CombatEngineAPI;
14import com.fs.starfarer.api.combat.CombatEngineLayers;
15import com.fs.starfarer.api.combat.CombatEntityAPI;
16import com.fs.starfarer.api.combat.ViewportAPI;
17import com.fs.starfarer.api.graphics.SpriteAPI;
18import com.fs.starfarer.api.util.FaderUtil;
19import com.fs.starfarer.api.util.Misc;
20import com.fs.starfarer.api.util.Noise;
21
23
24 public static class NEParams implements Cloneable {
25 //public float fadeIn = 0.25f;
26 public int numRiftsToSpawn = 2;
27 public float fadeIn = 0.1f;
28 public float fadeOut = 0.5f;
29 public float spawnHitGlowAt = 0f;
30 public float hitGlowSizeMult = 0.75f;
31 public float radius = 20f;
32 public float thickness = 25f;
33 public float noiseMag = 1f;
34 public float noiseMult = 1f;
35 public float noisePeriod = 0.1f;
36 public boolean withHitGlow = true;
37 public boolean withNegativeParticles = true;
38 public Color color = new Color(100,100,255);
39 public Color underglow = RiftCascadeEffect.EXPLOSION_UNDERCOLOR;
40 public Color blackColor = Color.black;
41 public Color invertForDarkening = null;
42 public boolean additiveBlend = false;
43
44 public NEParams() {
45 }
46
47 public NEParams(float radius, float thickness, Color color) {
48 super();
49 this.radius = radius;
50 this.thickness = thickness;
51 this.color = color;
52 }
53
54 @Override
55 protected NEParams clone() {
56 try {
57 return (NEParams) super.clone();
58 } catch (CloneNotSupportedException e) {
59 return null; // should never happen
60 }
61 }
62
63 }
64
65 protected FaderUtil fader;
67
68 protected float [] noise;
69 protected float [] noise1;
70 protected float [] noise2;
71
72// protected float radius;
73// protected float thickness;
74// protected Color color;
75// protected float noiseMag;
76// protected float noisePeriod;
77
78 protected NEParams p;
79
80 protected int segments;
81 protected float noiseElapsed = 0f;
82
83 protected boolean spawnedHitGlow = false;
84
85 public NegativeExplosionVisual(NEParams p) {
86 this.p = p;
87 }
88
89 public float getRenderRadius() {
90 return p.radius + 500f;
91 }
92
93
94 @Override
95 public EnumSet<CombatEngineLayers> getActiveLayers() {
97 }
98
99 public void advance(float amount) {
100 if (Global.getCombatEngine().isPaused()) return;
101
102 fader.advance(amount);
103
104 if (p.noiseMag > 0) {
105 noiseElapsed += amount;
106 if (noiseElapsed > p.noisePeriod) {
107 noiseElapsed = 0;
108 noise1 = Arrays.copyOf(noise2, noise2.length);
109 noise2 = Noise.genNoise(segments, p.noiseMag);
110 }
111 float f = noiseElapsed / p.noisePeriod;
112 for (int i = 0; i < noise.length; i++) {
113 float n1 = noise1[i];
114 float n2 = noise2[i];
115 noise[i] = n1 + (n2 - n1) * f;
116 }
117 }
118
119 if (!p.withHitGlow) return;
120
121 float glowSpawnAt = 1f;
122 if (!spawnedHitGlow && (!fader.isFadingIn() || fader.getBrightness() >= p.spawnHitGlowAt)) {
123 float size = Math.min(p.radius * 7f, p.radius + 150f);
124 float coreSize = Math.max(size, p.radius * 4f);
125 if (coreSize > size) size = coreSize;
126
127 size *= p.hitGlowSizeMult;
128 coreSize *= p.hitGlowSizeMult;
129
131 Vector2f point = entity.getLocation();
132 Vector2f vel = entity.getVelocity();
133 float dur = fader.getDurationOut() * glowSpawnAt;
134 engine.addHitParticle(point, vel, size * 3f, 1f, dur, p.color);
135 //engine.addHitParticle(point, vel, size * 3.0f, 1f, dur, p.color);
136 engine.addHitParticle(point, vel, coreSize * 1.5f, 1f, dur, Color.white);
137 //engine.addHitParticle(point, vel, coreSize * 1f, 1f, dur, Color.white);
138
139 Color invert = p.color;
140 if (p.invertForDarkening != null) invert = p.invertForDarkening;
141 Color c = new Color(255 - invert.getRed(),
142 255 - invert.getGreen(),
143 255 - invert.getBlue(), 127);
144 c = Misc.interpolateColor(c, Color.white, 0.4f);
145 //c = Misc.setAlpha(c, 80);
146 //c = Misc.scaleAlpha(c, 0.5f);
147 float durMult = 1f;
148 for (int i = 0; i < 7 && p.withNegativeParticles; i++) {
149 dur = 4f + 4f * (float) Math.random();
150 //dur = p.fadeIn + p.fadeOut + 3f + (float) Math.random() * 2f;
151 dur *= durMult;
152 dur *= 0.5f;
153 //float nSize = size * (1f + 0.0f * (float) Math.random());
154 //float nSize = size * (0.75f + 0.5f * (float) Math.random());
155 float nSize = size * 1f;
156 Vector2f pt = Misc.getPointAtRadius(point, nSize * 0.5f);
157 Vector2f v = Misc.getUnitVectorAtDegreeAngle((float) Math.random() * 360f);
158 v.scale(nSize + nSize * (float) Math.random() * 0.5f);
159 v.scale(0.15f);
160 Vector2f.add(vel, v, v);
161
162// float maxSpeed = nSize * 1.5f * 0.2f;
163// float minSpeed = nSize * 1f * 0.2f;
164// float overMin = v.length() - minSpeed;
165// if (overMin > 0) {
166// float durMult2 = 1f - overMin / (maxSpeed - minSpeed);
167// if (durMult2 < 0.1f) durMult2 = 0.1f;
168// dur *= 0.5f + 0.5f * durMult2;
169// }
170 v = new Vector2f(entity.getVelocity());
171// engine.addNegativeParticle(pt, v, nSize * 1f, p.fadeIn / dur, dur, c);
172 engine.addNegativeNebulaParticle(pt, v, nSize * 1f, 2f,
173 p.fadeIn / dur, 0f, dur, c);
174 }
175
176 dur = p.fadeIn + p.fadeOut + 2f;
177 dur *= durMult;
178 float rampUp = (p.fadeIn + p.fadeOut) / dur;
179 rampUp = 0f;
180 //rampUp = rampUp + (1f - rampUp) * 0.25f;
181 //float sizeMult = p.hitGlowSizeMult;
182
183 c = p.underglow;
184 if (c != null) {
185 //c = Misc.setAlpha(c, 255);
186 for (int i = 0; i < 15; i++) {
187 //rampUp = (float) Math.random() * 0.05f + 0.05f;
188 Vector2f loc = new Vector2f(point);
189 loc = Misc.getPointWithinRadius(loc, size * 1f);
190 //loc = Misc.getPointAtRadius(loc, size * 1f);
191 float s = size * 3f * (0.25f + (float) Math.random() * 0.25f);
192 //s *= 0.5f;
193 // engine.addSmoothParticle(loc, entity.getVelocity(), s, 1f, rampUp, dur, c);
194 engine.addNebulaParticle(loc, entity.getVelocity(), s, 1.5f, rampUp, 0f, dur, c);
195 }
196 }
197 spawnedHitGlow = true;
198 }
199 }
200
202 super.init(entity);
203
204 fader = new FaderUtil(0f, p.fadeIn, p.fadeOut);
205 fader.setBounceDown(true);
206 fader.fadeIn();
207
208 atmosphereTex = Global.getSettings().getSprite("combat", "corona_hard");
209
210 float perSegment = 2f;
211 segments = (int) ((p.radius * 2f * 3.14f) / perSegment);
212 if (segments < 8) segments = 8;
213
214 noise1 = Noise.genNoise(segments, p.noiseMag);
215 noise2 = Noise.genNoise(segments, p.noiseMag);
216 noise = Arrays.copyOf(noise1, noise1.length);
217 }
218
219 public boolean isExpired() {
220 return fader.isFadedOut();
221 }
222
224 float x = entity.getLocation().x;
225 float y = entity.getLocation().y;
226
227 float f = fader.getBrightness();
228 float alphaMult = viewport.getAlphaMult();
229 if (f < 0.5f) {
230 alphaMult *= f * 2f;
231 }
232
233 float r = p.radius;
234 float tSmall = p.thickness;
235
236 if (fader.isFadingIn()) {
237 r *= 0.75f + Math.sqrt(f) * 0.25f;
238 } else {
239 r *= 0.1f + 0.9f * f;
240 tSmall = Math.min(r * 1f, p.thickness);
241 }
242
243// GL11.glPushMatrix();
244// GL11.glTranslatef(x, y, 0);
245// GL11.glScalef(6f, 6f, 1f);
246// x = y = 0;
247
248 //GL14.glBlendEquation(GL14.GL_FUNC_REVERSE_SUBTRACT);
250 float a = 1f;
251 renderAtmosphere(x, y, r, tSmall, alphaMult * a, segments, atmosphereTex, noise, p.color, true);
252 renderAtmosphere(x, y, r - 2f, tSmall, alphaMult * a, segments, atmosphereTex, noise, p.color, true);
254 float circleAlpha = 1f;
255 if (alphaMult < 0.5f) {
256 circleAlpha = alphaMult * 2f;
257 }
258 float tCircleBorder = 1f;
259 renderCircle(x, y, r, circleAlpha, segments, p.blackColor);
260 renderAtmosphere(x, y, r, tCircleBorder, circleAlpha, segments, atmosphereTex, noise, p.blackColor, p.additiveBlend);
261 }
262 //GL14.glBlendEquation(GL14.GL_FUNC_ADD);
263
264// GL11.glPopMatrix();
265 }
266
267
268 private void renderCircle(float x, float y, float radius, float alphaMult, int segments, Color color) {
269 if (fader.isFadingIn() && p.blackColor == Color.black) alphaMult = 1f;
270 //if (fader.isFadingIn()) alphaMult = 1f;
271
272 float startRad = (float) Math.toRadians(0);
273 float endRad = (float) Math.toRadians(360);
274 float spanRad = Misc.normalizeAngle(endRad - startRad);
275 float anglePerSegment = spanRad / segments;
276
277 GL11.glPushMatrix();
278 GL11.glTranslatef(x, y, 0);
279 GL11.glRotatef(0, 0, 0, 1);
280 GL11.glDisable(GL11.GL_TEXTURE_2D);
281
282 GL11.glEnable(GL11.GL_BLEND);
283 if (p.additiveBlend) {
284 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
285 } else {
286 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
287 }
288
289
290 GL11.glColor4ub((byte)color.getRed(),
291 (byte)color.getGreen(),
292 (byte)color.getBlue(),
293 (byte)((float) color.getAlpha() * alphaMult));
294
295 GL11.glBegin(GL11.GL_TRIANGLE_FAN);
296 GL11.glVertex2f(0, 0);
297 for (float i = 0; i < segments + 1; i++) {
298 boolean last = i == segments;
299 if (last) i = 0;
300 float theta = anglePerSegment * i;
301 float cos = (float) Math.cos(theta);
302 float sin = (float) Math.sin(theta);
303
304 float m1 = 0.75f + 0.65f * noise[(int)i] * p.noiseMult;
305 if (p.noiseMag <= 0) {
306 m1 = 1f;
307 }
308
309 float x1 = cos * radius * m1;
310 float y1 = sin * radius * m1;
311
312 GL11.glVertex2f(x1, y1);
313
314 if (last) break;
315 }
316
317
318 GL11.glEnd();
319 GL11.glPopMatrix();
320
321 }
322
323
324 private void renderAtmosphere(float x, float y, float radius, float thickness, float alphaMult, int segments, SpriteAPI tex, float [] noise, Color color, boolean additive) {
325
326 float startRad = (float) Math.toRadians(0);
327 float endRad = (float) Math.toRadians(360);
328 float spanRad = Misc.normalizeAngle(endRad - startRad);
329 float anglePerSegment = spanRad / segments;
330
331 GL11.glPushMatrix();
332 GL11.glTranslatef(x, y, 0);
333 GL11.glRotatef(0, 0, 0, 1);
334 GL11.glEnable(GL11.GL_TEXTURE_2D);
335
336 tex.bindTexture();
337
338 GL11.glEnable(GL11.GL_BLEND);
339 if (additive) {
340 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
341 } else {
342 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
343 }
344
345 GL11.glColor4ub((byte)color.getRed(),
346 (byte)color.getGreen(),
347 (byte)color.getBlue(),
348 (byte)((float) color.getAlpha() * alphaMult));
349 float texX = 0f;
350 float incr = 1f / segments;
351 GL11.glBegin(GL11.GL_QUAD_STRIP);
352 for (float i = 0; i < segments + 1; i++) {
353 boolean last = i == segments;
354 if (last) i = 0;
355 float theta = anglePerSegment * i;
356 float cos = (float) Math.cos(theta);
357 float sin = (float) Math.sin(theta);
358
359 float m1 = 0.75f + 0.65f * noise[(int)i] * p.noiseMult;
360 float m2 = m1;
361 if (p.noiseMag <= 0) {
362 m1 = 1f;
363 m2 = 1f;
364 }
365
366 float x1 = cos * radius * m1;
367 float y1 = sin * radius * m1;
368 float x2 = cos * (radius + thickness * m2);
369 float y2 = sin * (radius + thickness * m2);
370
371 GL11.glTexCoord2f(0.5f, 0.05f);
372 GL11.glVertex2f(x1, y1);
373
374 GL11.glTexCoord2f(0.5f, 0.95f);
375 GL11.glVertex2f(x2, y2);
376
377 texX += incr;
378 if (last) break;
379 }
380
381 GL11.glEnd();
382 GL11.glPopMatrix();
383 }
384
386 return fader;
387 }
388
389}
390
391
static SettingsAPI getSettings()
Definition Global.java:57
static CombatEngineAPI getCombatEngine()
Definition Global.java:69
void render(CombatEngineLayers layer, ViewportAPI viewport)
void setBounceDown(boolean bounceDown)
static Vector2f getUnitVectorAtDegreeAngle(float degrees)
Definition Misc.java:1196
static float normalizeAngle(float angleDeg)
Definition Misc.java:1142
static Vector2f getPointAtRadius(Vector2f from, float r)
Definition Misc.java:697
static Color interpolateColor(Color from, Color to, float progress)
Definition Misc.java:1261
static Vector2f getPointWithinRadius(Vector2f from, float r)
Definition Misc.java:711
static float[] genNoise(int size, float spikes)
Definition Noise.java:9
SpriteAPI getSprite(String filename)
void addHitParticle(Vector2f loc, Vector2f vel, float size, float brightness, float duration, Color color)
void addNegativeNebulaParticle(Vector2f loc, Vector2f vel, float size, float endSizeMult, float rampUpFraction, float fullBrightnessFraction, float totalDuration, Color color)
void addNebulaParticle(Vector2f loc, Vector2f vel, float size, float endSizeMult, float rampUpFraction, float fullBrightnessFraction, float totalDuration, Color color)