Starsector API
Loading...
Searching...
No Matches
CombatEntityPluginWithParticles.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.combat;
2
3import java.awt.Color;
4import java.util.ArrayList;
5import java.util.EnumSet;
6import java.util.List;
7
8import org.lwjgl.opengl.GL14;
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.CombatEngineLayers;
14import com.fs.starfarer.api.combat.CombatEntityAPI;
15import com.fs.starfarer.api.combat.DamagingProjectileAPI;
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;
20
21public class CombatEntityPluginWithParticles extends BaseCombatLayeredRenderingPlugin {
22
23 public static class ParticleData {
24 public SpriteAPI sprite;
25 public Vector2f offset = new Vector2f();
26 public Vector2f vel = new Vector2f();
27 public float scale = 1f;
28 public float scaleIncreaseRate = 1f;
29 public float turnDir = 1f;
30 public float angle = 1f;
31
32 public float maxDur;
33 public FaderUtil fader;
34 public float elapsed = 0f;
35 public float baseSize;
36 protected Color color;
37
38 public ParticleData(float baseSize, float durIn, float durOut, float endSizeMult, float maxDriftVel, float maxAngVel, Color color, String spriteSheetKey) {
39 this.color = color;
40 if (spriteSheetKey == null) {
41 spriteSheetKey = "nebula_particles";
42 }
43 sprite = Global.getSettings().getSprite("misc", spriteSheetKey);
44 //sprite = Global.getSettings().getSprite("misc", "dust_particles");
45 float i = Misc.random.nextInt(4);
46 float j = Misc.random.nextInt(4);
47 sprite.setTexWidth(0.25f);
48 sprite.setTexHeight(0.25f);
49 sprite.setTexX(i * 0.25f);
50 sprite.setTexY(j * 0.25f);
51 sprite.setAdditiveBlend();
52
53 angle = (float) Math.random() * 360f;
54
55 this.maxDur = durIn + durOut;
56 scaleIncreaseRate = endSizeMult / maxDur;
57 if (endSizeMult < 1f) {
58 scaleIncreaseRate = -1f * endSizeMult;
59 }
60 scale = 1f;
61
62 this.baseSize = baseSize;
63 turnDir = Math.signum((float) Math.random() - 0.5f) * maxAngVel * (float) Math.random();
64 //turnDir = 0f;
65
66 float driftDir = (float) Math.random() * 360f;
67 vel = Misc.getUnitVectorAtDegreeAngle(driftDir);
68 //vel.scale(proj.getProjectileSpec().getLength() / maxDur * (0f + (float) Math.random() * 3f));
69 vel.scale(maxDriftVel * (0.5f + (float) Math.random() * 0.5f));
70
71 fader = new FaderUtil(0f, durIn, durOut);
72 fader.setBounceDown(true);
73 fader.forceOut();
74 fader.fadeIn();
75 }
76
77 public void advance(float amount) {
78 scale += scaleIncreaseRate * amount;
79
80 offset.x += vel.x * amount;
81 offset.y += vel.y * amount;
82
83 angle += turnDir * amount;
84
85 elapsed += amount;
86// if (maxDur - elapsed <= fader.getDurationOut() + 0.1f) {
87// fader.fadeOut();
88// }
89 fader.advance(amount);
90 }
91 }
92
93 protected List<ParticleData> particles = new ArrayList<ParticleData>();
94 protected List<ParticleData> darkParticles = new ArrayList<ParticleData>();
95 protected EnumSet<CombatEngineLayers> layers = EnumSet.of(CombatEngineLayers.ABOVE_SHIPS_AND_MISSILES_LAYER);
96 protected CombatEngineLayers normalLayer;
97 protected CombatEngineLayers darkLayer;
98
100 this(CombatEngineLayers.ABOVE_PARTICLES_LOWER, CombatEngineLayers.ABOVE_PARTICLES);
101 }
102 public CombatEntityPluginWithParticles(CombatEngineLayers normalLayer, CombatEngineLayers darkLayer) {
103 this.normalLayer = normalLayer;
104 this.darkLayer = darkLayer;
105 layers = EnumSet.of(normalLayer, darkLayer);
106 }
107
108 public void init(CombatEntityAPI entity) {
109 super.init(entity);
110 }
111
112 @Override
113 public EnumSet<CombatEngineLayers> getActiveLayers() {
114 return layers;
115 }
116
117 protected ParticleData prev;
118
119 protected String spriteSheetKey;
120 protected String darkSpriteSheetKey;
121 public String getSpriteSheetKey() {
122 return spriteSheetKey;
123 }
124 public void setSpriteSheetKey(String spriteSheetKey) {
125 this.spriteSheetKey = spriteSheetKey;
126 }
127 public String getDarkSpriteSheetKey() {
128 return darkSpriteSheetKey;
129 }
131 this.darkSpriteSheetKey = darkSpriteSheetKey;
132 }
133
134 public ParticleData addParticle(float baseSize, float durIn, float durOut, float endSizeMult, float maxDriftVel, float maxAngVel, Color color) {
135 ParticleData p = new ParticleData(baseSize, durIn, durOut, endSizeMult, maxDriftVel, maxAngVel, color, spriteSheetKey);
136 particles.add(p);
137 prev = p;
138 return p;
139 }
140 public ParticleData addDarkParticle(float baseSize, float durIn, float durOut, float endSizeMult, float maxDriftVel, float maxAngVel, Color color) {
141 ParticleData p = new ParticleData(baseSize, durIn, durOut, endSizeMult, maxDriftVel, maxAngVel, color, darkSpriteSheetKey);
142 darkParticles.add(p);
143 prev = p;
144 return p;
145 }
146
147 public void randomizePrevParticleLocation(float maxOffset) {
148 Vector2f loc = Misc.getPointWithinRadius(prev.offset, maxOffset);
149 prev.offset.set(loc);
150 }
151
152 public void advance(float amount) {
153 if (Global.getCombatEngine().isPaused()) return;
154
155 List<ParticleData> remove = new ArrayList<ParticleData>();
156 for (ParticleData p : particles) {
157 p.advance(amount);
158 if (p.elapsed >= p.maxDur) {
159 remove.add(p);
160 }
161 }
162 particles.removeAll(remove);
163
164 remove = new ArrayList<ParticleData>();
165 for (ParticleData p : darkParticles) {
166 p.advance(amount);
167 if (p.elapsed >= p.maxDur) {
168 remove.add(p);
169 }
170 }
171 darkParticles.removeAll(remove);
172 }
173
174
175 public boolean isExpired() {
176 return particles.isEmpty() && darkParticles.isEmpty();
177 }
178
179 protected float getGlobalAlphaMult() {
180 return 1f;
181 }
182
183 protected Float baseFacing = null;
184 public void render(CombatEngineLayers layer, ViewportAPI viewport) {
185 render(layer, viewport, null);
186 }
187
188 public void render(CombatEngineLayers layer, ViewportAPI viewport, DamagingProjectileAPI proj) {
189 float x = entity.getLocation().x;
190 float y = entity.getLocation().y;
191
192 float b = viewport.getAlphaMult();
193
194 if (proj != null && baseFacing == null) {
195 baseFacing = proj.getFacing();
196 }
197
198 if (layer == normalLayer) {
199 for (ParticleData p : particles) {
200 float size = p.baseSize * p.scale;
201
202 Vector2f offset = p.offset;
203 float diff = 0f;
204 if (baseFacing != null && proj != null) {
205 diff = Misc.getAngleDiff(baseFacing, proj.getFacing());
206 if (Math.abs(diff) > 0.1f) {
207 offset = Misc.rotateAroundOrigin(offset, diff);
208 }
209 }
210 Vector2f loc = new Vector2f(x + offset.x, y + offset.y);
211
212 float alphaMult = getGlobalAlphaMult();
213
214 p.sprite.setAngle(p.angle);
215 p.sprite.setSize(size, size);
216 p.sprite.setAlphaMult(b * alphaMult * p.fader.getBrightness());
217 p.sprite.setColor(p.color);
218 p.sprite.renderAtCenter(loc.x, loc.y);
219 }
220 } else if (layer == darkLayer) {
221 GL14.glBlendEquation(GL14.GL_FUNC_REVERSE_SUBTRACT);
222
223 for (ParticleData p : darkParticles) {
224 //float size = proj.getProjectileSpec().getWidth() * 0.6f;
225 float size = p.baseSize * p.scale;
226
227 Vector2f offset = p.offset;
228 float diff = 0f;
229 if (baseFacing != null && proj != null) {
230 diff = Misc.getAngleDiff(baseFacing, proj.getFacing());
231 if (Math.abs(diff) > 0.1f) {
232 offset = Misc.rotateAroundOrigin(offset, diff);
233 }
234 }
235 Vector2f loc = new Vector2f(x + offset.x, y + offset.y);
236
237 float alphaMult = getGlobalAlphaMult();
238
239 p.sprite.setAngle(p.angle);
240 p.sprite.setSize(size, size);
241 p.sprite.setAlphaMult(b * alphaMult * p.fader.getBrightness());
242 p.sprite.setColor(p.color);
243 p.sprite.renderAtCenter(loc.x, loc.y);
244 }
245
246 GL14.glBlendEquation(GL14.GL_FUNC_ADD);
247 }
248 }
249
250}
251
252
253
254
static SettingsAPI getSettings()
Definition Global.java:51
static CombatEngineAPI getCombatEngine()
Definition Global.java:63
void render(CombatEngineLayers layer, ViewportAPI viewport, DamagingProjectileAPI proj)
CombatEntityPluginWithParticles(CombatEngineLayers normalLayer, CombatEngineLayers darkLayer)
ParticleData addDarkParticle(float baseSize, float durIn, float durOut, float endSizeMult, float maxDriftVel, float maxAngVel, Color color)
ParticleData addParticle(float baseSize, float durIn, float durOut, float endSizeMult, float maxDriftVel, float maxAngVel, Color color)
SpriteAPI getSprite(String filename)