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