001package com.fs.starfarer.api.impl.campaign.eventide;
002
003import java.awt.Color;
004import java.util.ArrayList;
005import java.util.Iterator;
006import java.util.List;
007
008import org.lwjgl.opengl.GL11;
009import org.lwjgl.util.vector.Vector2f;
010
011import com.fs.starfarer.api.util.Misc;
012
013public class QuadParticles {
014        
015        public static class QuadParticleData {
016                public Vector2f loc = new Vector2f();
017                public Vector2f vel = new Vector2f();
018                public Color color;
019                public float size;
020                public float elapsed;
021                public float maxDur;
022                public float fadeTime;
023                public float floorMod = 0;
024        }
025        
026        public List<QuadParticleData> particles = new ArrayList<QuadParticleData>();
027        public float gravity = 0f;
028        public float floor = -10000000f;
029        public float maxFloorMod = 0f;
030        public float floorFriction = 1f; // fraction of speed lost per second
031        public boolean additiveBlend = false;
032        
033        public Color minColor = null;
034        public Color maxColor = null;
035        public float minDur, maxDur;
036        public float minSize, maxSize;
037        public float fadeTime = 0.5f;
038        
039        public void addParticle(float x, float y, float dx, float dy) {
040                float size = (float) Math.random() * (maxSize - minSize) + minSize;
041                addParticle(x, y, dx, dy, size);
042        }
043        public void addParticle(float x, float y, float dx, float dy, float size) {
044                float r1 = (float) Math.random();
045                int r = (int) Math.round(Misc.interpolate(minColor.getRed(), maxColor.getRed(), r1));
046                if (r < 0) r = 0;
047                if (r > 255) r = 255;
048                
049                r1 = (float) Math.random();
050                int g = (int) Math.round(Misc.interpolate(minColor.getGreen(), maxColor.getGreen(), r1));
051                if (g < 0) g = 0;
052                if (g > 255) g = 255;
053                
054                r1 = (float) Math.random();
055                int b = (int) Math.round(Misc.interpolate(minColor.getBlue(), maxColor.getBlue(), r1));
056                if (b < 0) b = 0;
057                if (b > 255) b = 255;
058                
059                r1 = (float) Math.random();
060                int a = (int) Math.round(Misc.interpolate(minColor.getAlpha(), maxColor.getAlpha(), r1));
061                if (a < 0) a = 0;
062                if (a > 255) a = 255;
063                
064                addParticle(x, y, dx, dy, size, new Color(r, g, b, a));
065        }
066        
067        public void addParticle(float x, float y, float dx, float dy, float size, Color color) {
068                float dur = (float) Math.random() * (maxDur - minDur) + minDur;
069                addParticle(x, y, dx, dy, size, color, dur, fadeTime);
070        }
071        public void addParticle(float x, float y, float dx, float dy, float size, Color color, float maxDur) {
072                addParticle(x, y, dx, dy, size, color, maxDur, fadeTime);
073        }
074        public void addParticle(float x, float y, float dx, float dy, float size, Color color, float maxDur, float fadeTime) {
075                QuadParticleData p = new QuadParticleData();
076                p.loc.x = x;
077                p.loc.y = y;
078                p.vel.x = dx;
079                p.vel.y = dy;
080                p.size = size;
081                p.color = color;
082                p.maxDur = maxDur;
083                p.fadeTime = fadeTime;
084                p.floorMod = (float) Math.random() * maxFloorMod;
085                particles.add(p);
086        }
087        
088        public boolean isParticleOnFloor(QuadParticleData curr) {
089                return curr.loc.y <= floor + curr.floorMod;
090        }
091        
092        public void advance(float amount) {
093                Iterator<QuadParticleData> iter = particles.iterator();
094                while (iter.hasNext()) {
095                        QuadParticleData curr = iter.next();
096                        curr.elapsed += amount;
097                        
098                        if (gravity > 0) {
099                                curr.vel.y -= gravity * amount;
100                        }
101                        
102                        curr.loc.x += curr.vel.x * amount;
103                        curr.loc.y += curr.vel.y * amount;
104                        if (curr.loc.y < floor + curr.floorMod) {
105                                curr.loc.y = floor + curr.floorMod;
106                                
107                                if (floorFriction > 0) {
108                                        curr.vel.scale(Math.max(0, (1f - floorFriction * amount)));
109                                }
110                        }
111                        
112                        if (curr.elapsed > curr.maxDur) {
113                                iter.remove();
114                        }
115                }
116        }
117        
118        public void render(float alphaMult, boolean onFloor) {
119                GL11.glDisable(GL11.GL_TEXTURE_2D);
120                GL11.glEnable(GL11.GL_BLEND);
121                
122                if (additiveBlend) {
123                        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
124                } else {
125                        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
126                }
127                
128                for (QuadParticleData p : particles) {
129                        if (isParticleOnFloor(p) != onFloor) continue;
130                        
131                        float a = alphaMult;
132                        float left = p.maxDur - p.elapsed;
133                        if (left < 0) left = 0;
134                        if (left < p.fadeTime) {
135                                a *= left / p.fadeTime;
136                        }
137                        Misc.renderQuad(p.loc.x - p.size/2f, p.loc.y - p.size/2f, p.size, p.size, p.color, a);
138                }
139        }
140        
141
142        public boolean isDone() {
143                return particles.isEmpty();
144        }
145        
146
147}
148
149
150
151
152
153
154
155
156
157
158
159
160
161