001package com.fs.starfarer.api.impl.campaign.velfield; 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.Global; 012import com.fs.starfarer.api.campaign.CampaignEngineLayers; 013import com.fs.starfarer.api.campaign.CampaignFleetAPI; 014import com.fs.starfarer.api.campaign.SectorEntityToken; 015import com.fs.starfarer.api.combat.ViewportAPI; 016import com.fs.starfarer.api.fleet.FleetMemberViewAPI; 017import com.fs.starfarer.api.graphics.SpriteAPI; 018import com.fs.starfarer.api.impl.campaign.BaseCustomEntityPlugin; 019import com.fs.starfarer.api.util.FaderUtil; 020import com.fs.starfarer.api.util.Misc; 021 022public class SlipstreamEntityPlugin extends BaseCustomEntityPlugin { 023 024 public static float MAX_PARTICLES_ADD_PER_FRAME = 100; 025 026 public static float RAD_PER_DEG = 0.01745329251f; 027 public static Vector2f rotateAroundOrigin(Vector2f v, float cos, float sin) { 028 Vector2f r = new Vector2f(); 029 r.x = v.x * cos - v.y * sin; 030 r.y = v.x * sin + v.y * cos; 031 return r; 032 } 033 034 public static class SlipstreamParticle { 035 Vector2f loc = new Vector2f(); 036 Vector2f vel = new Vector2f(); 037 Color color; 038 float remaining; 039 float elapsed; 040 } 041 042 public static class SlipstreamParams { 043 public String spriteKey1 = "slipstream1"; 044 public Color spriteColor1 = new Color(0.3f, 0.5f, 1f, 0.67f); 045 public float width; 046 public float length; 047 public int numParticles; 048 public float minSpeed; 049 public float maxSpeed; 050 public float maxSpeedForTex; 051 public int burnLevel = 30; 052 public Color minColor; 053 public Color maxColor; 054 public float minDur = 0f; 055 public float maxDur = 4f; 056 public float lineLengthFractionOfSpeed = 0.5f; 057 } 058 059 protected SlipstreamParams params = new SlipstreamParams(); 060 061 protected float texelsPerPixel = 1f; 062 protected transient List<SlipstreamParticle> particles = new ArrayList<SlipstreamParticle>(); 063 064 public SlipstreamEntityPlugin() { 065 } 066 067 public void init(SectorEntityToken entity, Object pluginParams) { 068 super.init(entity, pluginParams); 069 this.params = (SlipstreamParams) pluginParams; 070 fader.fadeIn(); 071 texProgress1 = (float) Math.random(); 072 texProgress2 = (float) Math.random(); 073 texProgress3 = (float) Math.random(); 074 readResolve(); 075 } 076 077 public float getRenderRange() { 078 return Math.max(params.width, params.length) * 1.5f; 079 } 080 081 Object readResolve() { 082 if (particles == null) { 083 particles = new ArrayList<SlipstreamParticle>(); 084 } 085 return this; 086 } 087 088 public void advance(float amount) { 089 if (!entity.isInCurrentLocation()) return; 090 091 applyEffectToFleets(amount); 092 093 fader.advance(amount); 094 095 096 entity.getLocation().x += Misc.getSpeedForBurnLevel(params.burnLevel) * amount; 097 entity.setFacing(0f); 098// entity.getLocation().set(Global.getSector().getPlayerFleet().getLocation().x + 500, 099// Global.getSector().getPlayerFleet().getLocation().y + 1000f); 100// entity.getLocation().set(Global.getSector().getPlayerFleet().getLocation()); 101 102 params.minColor = new Color(0.5f, 0.3f, 0.75f, 0.85f); 103 params.maxColor = new Color(0.5f, 0.6f, 1f, 1f); 104 params.spriteColor1 = new Color(0.3f, 0.5f, 1f, 0.67f); 105 params.minDur = 1f; 106 params.maxDur = 4f; 107 params.minSpeed = 700f; 108 params.maxSpeed = 1500f; 109 params.minSpeed = Misc.getSpeedForBurnLevel(25f); 110 params.maxSpeed = Misc.getSpeedForBurnLevel(35f); 111 params.maxSpeedForTex = Misc.getSpeedForBurnLevel(15f); 112 params.lineLengthFractionOfSpeed = 0.25f; 113 //params.lineLengthFractionOfSpeed = 0.5f; 114 //params.lineLengthFractionOfSpeed = 1f; 115 //params.lineLengthFractionOfSpeed = 0.15f; 116 params.burnLevel = 30; 117 params.numParticles = 1000; 118 params.width = 512f; 119 params.length = 10000f; 120 params.minColor = new Color(0.5f, 0.3f, 0.75f, 0.1f); 121 params.maxColor = new Color(0.5f, 0.6f, 1f, 0.5f); 122 params.maxDur = 6f; 123// params.minSpeed = Misc.getSpeedForBurnLevel(16f); 124// params.maxSpeed = Misc.getSpeedForBurnLevel(16f); 125// params.numParticles = 0; 126 //params.spriteKey1 = "graphics/fx/beam_weave_core.png"; 127 128 SpriteAPI sprite = Global.getSettings().getSprite("misc", params.spriteKey1); 129 texelsPerPixel = sprite.getHeight() / params.width; 130 131 132 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(entity.getFacing()); 133 float cos = dir.x; 134 float sin = dir.y; 135// cos = (float) Math.cos(entity.getFacing() * RAD_PER_DEG); 136// sin = (float) Math.sin(entity.getFacing() * RAD_PER_DEG); 137 138 float x = entity.getLocation().x; 139 float y = entity.getLocation().y; 140 141 int added = 0; 142 //MAX_PARTICLES_ADD_PER_FRAME = 2000; 143 while (particles.size() < params.numParticles && added < MAX_PARTICLES_ADD_PER_FRAME) { 144 added++; 145 146 SlipstreamParticle p = new SlipstreamParticle(); 147 float fLength = (float) Math.random() * 0.8f; 148 float sign = Math.signum((float) Math.random() - 0.5f); 149 //fWidth = 0.5f + sign * fWidth * fWidth; 150 float r = (float) Math.random() * 0.7f; 151 float fWidth = 0.5f + sign * (1f - (float)Math.sqrt(r)) * fLength * 0.5f; 152 //fWidth = r; 153 fWidth = 0.5f + sign * r * (0.5f + 0.5f * fLength) * 0.5f; 154 fWidth = (float) Math.random() * 0.8f + 0.1f; 155 //fLength *= fLength * fLength * fLength; 156 //fLength *= fLength; 157 float speed = params.minSpeed + (params.maxSpeed - params.minSpeed) * (float) Math.random(); 158 //speed *= 0.5f; 159 float dur = params.minDur + (params.maxDur - params.minDur) * (float) Math.random(); 160 //float minDistFromSource = speed * dur; 161 float minDistFromSource = speed * dur * 0.25f; 162 p.loc.set(-fLength * (params.length - minDistFromSource) - minDistFromSource, 163 fWidth * params.width - params.width / 2f); 164 p.loc = rotateAroundOrigin(p.loc, cos, sin); 165 p.loc.x += x; 166 p.loc.y += y; 167 168 169 float angleToEntity = Misc.getAngleInDegrees(p.loc, entity.getLocation()); 170 float turnDir = Misc.getClosestTurnDirection(entity.getFacing(), angleToEntity); 171 float diff = Math.min(30f, Misc.getAngleDiff(angleToEntity, entity.getFacing()) * 0.5f); 172 diff = 0f; 173 //p.vel.set(dir); 174 p.vel.set(Misc.getUnitVectorAtDegreeAngle(entity.getFacing() + turnDir * diff)); 175 p.vel.scale(speed); 176 177 p.remaining = dur; 178 p.color = getRandomColor(); 179 180 particles.add(p); 181 } 182 183 Iterator<SlipstreamParticle> iter = particles.iterator(); 184 while (iter.hasNext()) { 185 SlipstreamParticle p = iter.next(); 186 p.remaining -= amount; 187 p.elapsed += amount; 188 if (p.remaining <= 0) { 189 iter.remove(); 190 continue; 191 } 192 193 boolean shouldFadeOut = false; 194 Vector2f toEntity = Vector2f.sub(entity.getLocation(), p.loc, new Vector2f()); 195 shouldFadeOut = Vector2f.dot(toEntity, p.vel) < 0f; 196 if (shouldFadeOut) { 197 if (p.elapsed > 1f) { 198 p.remaining = Math.min(p.remaining, 0.5f); 199 } 200 } 201 202 p.loc.x += p.vel.x * amount; 203 p.loc.y += p.vel.y * amount; 204 } 205 206// float texSpeed = params.maxSpeedForTex; 207// texSpeed = 100f; 208 float texSpeed = Misc.getSpeedForBurnLevel(params.burnLevel); 209// texSpeed = 100f; 210 //texSpeed = Misc.getSpeedForBurnLevel(7); 211 212 float unitsPerOneTexIter = sprite.getWidth(); 213 float texUnitsPerSecondForSpeed = texSpeed / unitsPerOneTexIter * texelsPerPixel; 214 texProgress1 -= texUnitsPerSecondForSpeed * amount; 215 texProgress2 += texUnitsPerSecondForSpeed * amount * 1.9f; 216 texProgress3 += texUnitsPerSecondForSpeed * amount * 0.7f; 217 } 218 219 public void render(CampaignEngineLayers layer, ViewportAPI viewport) { 220 221 SpriteAPI sprite = Global.getSettings().getSprite("misc", params.spriteKey1); 222 //sprite.setAdditiveBlend(); 223 sprite.setNormalBlend(); 224 sprite.setColor(params.spriteColor1); 225 //sprite.setColor(Misc.setAlpha(params.spriteColor1, 255)); 226 //sprite.setColor(Color.blue); 227 renderLayer(sprite, texProgress1, viewport.getAlphaMult()); 228 //sprite.setColor(Color.red); 229 //renderLayer(sprite, texProgress2, viewport.getAlphaMult()); 230 //sprite.setColor(Color.green); 231 //renderLayer(sprite, texProgress3, viewport.getAlphaMult()); 232 233 GL11.glDisable(GL11.GL_TEXTURE_2D); 234 GL11.glEnable(GL11.GL_BLEND); 235 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); 236 237 float zoom = Global.getSector().getViewport().getViewMult(); 238 239 //GL11.glLineWidth(2f); 240 //GL11.glLineWidth(Math.max(1f, 2f/zoom)); 241 GL11.glLineWidth(Math.max(1f, Math.min(2f, 2f/zoom))); 242 //GL11.glLineWidth(1.5f); 243 GL11.glEnable(GL11.GL_LINE_SMOOTH); 244 GL11.glBegin(GL11.GL_LINES); 245 for (SlipstreamParticle p : particles) { 246 //if (true) break; 247 if (!viewport.isNearViewport(p.loc, 500)) continue; 248 float a = viewport.getAlphaMult(); 249 if (p.remaining <= 0.5f) { 250 a = p.remaining / 0.5f; 251 } else if (p.elapsed < 1f) { 252 a = p.elapsed / 1f; 253 } 254 255 //a *= 0.5f; 256 //a *= 0.1f; 257 258 Vector2f start = new Vector2f(p.loc); 259 Vector2f end = new Vector2f(p.loc); 260 start.x += p.vel.x * params.lineLengthFractionOfSpeed * 0.1f; 261 start.y += p.vel.y * params.lineLengthFractionOfSpeed * 0.1f; 262 end.x -= p.vel.x * params.lineLengthFractionOfSpeed * 0.9f; 263 end.y -= p.vel.y * params.lineLengthFractionOfSpeed * 0.9f; 264 265 Misc.setColor(p.color, 0f); 266 GL11.glVertex2f(start.x, start.y); 267 Misc.setColor(p.color, a); 268 GL11.glVertex2f(p.loc.x, p.loc.y); 269 GL11.glVertex2f(p.loc.x, p.loc.y); 270 Misc.setColor(p.color, 0f); 271 GL11.glVertex2f(end.x, end.y); 272 273// a *= 0.5f; 274// float spacing = 0.67f; 275// Vector2f perp = Misc.getUnitVectorAtDegreeAngle(Misc.getAngleInDegrees(p.vel) + 90f); 276// perp.scale(spacing); 277// Misc.setColor(p.color, 0f); 278// GL11.glVertex2f(start.x + perp.x, start.y + perp.y); 279// Misc.setColor(p.color, a); 280// GL11.glVertex2f(p.loc.x + perp.x, p.loc.y + perp.y); 281// GL11.glVertex2f(p.loc.x + perp.x, p.loc.y + perp.y); 282// Misc.setColor(p.color, 0f); 283// GL11.glVertex2f(end.x + perp.x, end.y + perp.y); 284// 285// perp.negate(); 286// Misc.setColor(p.color, 0f); 287// GL11.glVertex2f(start.x + perp.x, start.y + perp.y); 288// Misc.setColor(p.color, a); 289// GL11.glVertex2f(p.loc.x + perp.x, p.loc.y + perp.y); 290// GL11.glVertex2f(p.loc.x + perp.x, p.loc.y + perp.y); 291// Misc.setColor(p.color, 0f); 292// GL11.glVertex2f(end.x + perp.x, end.y + perp.y); 293 294 } 295 GL11.glEnd(); 296 } 297 298 299 protected float texProgress1 = 0f; 300 protected float texProgress2 = 0f; 301 protected float texProgress3 = 0f; 302 protected FaderUtil fader = new FaderUtil(0f, 0.5f, 0.5f); 303 304 public void renderLayer(SpriteAPI sprite, float texProgress, float alpha) { 305 Vector2f from = new Vector2f(entity.getLocation()); 306 Vector2f to = Misc.getUnitVectorAtDegreeAngle(entity.getFacing()); 307 to.scale(-params.length); 308 Vector2f.add(to, from, to); 309 310 float length1 = 500f; 311 length1 = Math.min(length1, Misc.getDistance(from, to)); 312 length1 = Misc.getDistance(from, to); 313 float length2 = params.width / 2f; 314 if (length1 < length2) length1 = length2; 315 length1 += length2; 316 317 //length1 = params.width; 318 //length1 = params.length * 0.05f; 319 length1 = params.length * 0.15f; 320 length2 = params.length - length1; 321 322 float w1 = length2 * 0.3f; 323 float w2 = length2 * 1.5f; 324 float w3 = length2 * 2.5f; 325 float wMult = 0.33f; 326 wMult = 1f; 327 w1 *= wMult; 328 w2 *= wMult; 329 w3 *= wMult; 330 //w1 = w2 = 400; 331 332 w1 = w2 = w3 = params.width; 333 334 float widthMult = 0.3f; 335 w1 = params.width * widthMult; 336 w2 = params.width * (1f - (1f - widthMult) * (length2 / (length1 + length2))); 337 w3 = params.width * 1f; 338 339 w1 = w2 = w3 = params.width; 340 341 float angle = entity.getFacing() + 180f; 342 343 Vector2f dest = new Vector2f(to); 344 Vector2f src = new Vector2f(from); 345 346 Vector2f dir = Misc.getUnitVectorAtDegreeAngle(angle); 347 Vector2f dest1 = new Vector2f(dir); 348 dest1.scale(length1); 349 Vector2f.add(dest1, src, dest1); 350 Vector2f dest2 = new Vector2f(dir); 351 dest2.scale(length1 + length2); 352 Vector2f.add(dest2, src, dest2); 353 354 355 Vector2f perp = Misc.getUnitVectorAtDegreeAngle(angle + 90); 356 357 GL11.glEnable(GL11.GL_TEXTURE_2D); 358 //GL11.glDisable(GL11.GL_TEXTURE_2D); 359 sprite.bindTexture(); 360 GL11.glEnable(GL11.GL_BLEND); 361 //GL11.glDisable(GL11.GL_BLEND); 362 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); 363 364 Color color = sprite.getColor(); 365 366 boolean wireframe = false; 367 //wireframe = true; 368 if (wireframe) { 369 GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE); 370 GL11.glDisable(GL11.GL_TEXTURE_2D); 371 //GL11.glDisable(GL11.GL_BLEND); 372 } 373 374// float texScale = sprite.getWidth() / (length1 + length2); 375// float tx1 = length1 / (length1 + length2) * texScale; 376 float tx1 = length1 / sprite.getWidth() * texelsPerPixel; 377 378// alpha *= Math.sqrt(fader.getBrightness()); 379// alpha *= 0.5f; 380// alpha *= (0.5f + Math.min(0.5f, 0.5f * w2 / 360f)); 381 GL11.glBegin(GL11.GL_TRIANGLE_FAN); 382 Misc.setColor(color, alpha * 1f); 383 GL11.glTexCoord2f(tx1 * 0.5f + texProgress, 0.5f); 384 GL11.glVertex2f((src.x + dest1.x)/2f, (src.y + dest1.y)/2f); 385 386 Misc.setColor(color, alpha * 0f); 387 GL11.glTexCoord2f(0f + texProgress, 0f); 388 GL11.glVertex2f(src.x + perp.x * w1/2f, src.y + perp.y * w1/2f); 389 GL11.glTexCoord2f(0f + texProgress, 1f); 390 GL11.glVertex2f(src.x - perp.x * w1/2f, src.y - perp.y * w1/2f); 391 392 Misc.setColor(color, alpha * 1f); 393 GL11.glTexCoord2f(tx1 + texProgress, 1f); 394 GL11.glVertex2f(dest1.x - perp.x * w2/2f, dest1.y - perp.y * w2/2f); 395 GL11.glTexCoord2f(tx1 + texProgress, 0f); 396 GL11.glVertex2f(dest1.x + perp.x * w2/2f, dest1.y + perp.y * w2/2f); 397 398 Misc.setColor(color, alpha * 0f); 399 GL11.glTexCoord2f(0f + texProgress, 0f); 400 GL11.glVertex2f(src.x + perp.x * w1/2f, src.y + perp.y * w1/2f); 401 GL11.glEnd(); 402 403 //float th = length2 / length1; 404 float th = tx1 * length2 / length1; 405 //th *= texScale; 406 //th = 0.5f; 407 408 GL11.glBegin(GL11.GL_TRIANGLE_FAN); 409 Misc.setColor(color, alpha * 1f); 410 GL11.glTexCoord2f(tx1 + texProgress + th * 0.5f, 0.5f); 411 GL11.glVertex2f((dest1.x + dest2.x)/2f, (dest1.y + dest2.y)/2f); 412 413 Misc.setColor(color, alpha * 1f); 414 GL11.glTexCoord2f(tx1 + texProgress, 0f); 415 GL11.glVertex2f(dest1.x + perp.x * w2/2f, dest1.y + perp.y * w2/2f); 416 GL11.glTexCoord2f(tx1 + texProgress, 1f); 417 GL11.glVertex2f(dest1.x - perp.x * w2/2f, dest1.y - perp.y * w2/2f); 418 419 Misc.setColor(color, alpha * 0f); 420 GL11.glTexCoord2f(tx1 + texProgress + th, 1f); 421 GL11.glVertex2f(dest2.x - perp.x * w3/2f, dest2.y - perp.y * w3/2f); 422 GL11.glTexCoord2f(tx1 + texProgress + th, 0f); 423 GL11.glVertex2f(dest2.x + perp.x * w3/2f, dest2.y + perp.y * w3/2f); 424 425 Misc.setColor(color, alpha * 1f); 426 GL11.glTexCoord2f(tx1 + texProgress, 0f); 427 GL11.glVertex2f(dest1.x + perp.x * w2/2f, dest1.y + perp.y * w2/2f); 428 GL11.glEnd(); 429 430 if (wireframe) GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); 431 } 432 433 434 435 436 437 public Color getRandomColor() { 438 return Misc.interpolateColor(params.minColor, params.maxColor, (float) Math.random()); 439 } 440 441 442 /** 443 * result[0] = along the length of the field, 0 = at start, 1 = at tail 444 * result[1] = along the width of the field, 0 = on center, 1 = on edge, no directional information 445 * null if outside stream 446 * Assumes rectangular, non-tapered stream 447 * @param loc 448 * @return 449 */ 450 public float [] getLengthAndWidthFractionWithinStream(Vector2f loc) { 451 float dist = Misc.getDistance(loc, entity.getLocation()); 452 if (dist > getRenderRange()) return null; 453 454 Vector2f p3 = new Vector2f(loc); 455 Vector2f p1 = new Vector2f(entity.getLocation()); 456 Vector2f p2 = Misc.getUnitVectorAtDegreeAngle(entity.getFacing() + 180f); 457 p2.scale(params.length); 458 Vector2f.add(p2, p1, p2); 459 460 float u = (p3.x - p1.x) * (p2.x - p1.x) + (p3.y - p1.y) * (p2.y - p1.y); 461 float denom = Vector2f.sub(p2, p1, new Vector2f()).length(); 462 denom *= denom; 463 if (denom == 0) return null; 464 u /= denom; 465 466 if (u >= 0 && u <= 1) { // intersection is between p1 and p2 467 Vector2f intersect = new Vector2f(); 468 intersect.x = p1.x + u * (p2.x - p1.x); 469 intersect.y = p1.y + u * (p2.y - p1.y); 470 float distFromLine = Vector2f.sub(intersect, p3, new Vector2f()).length(); 471 //float distAlongLine = u * params.length; 472 if (distFromLine >= params.width/2f) return null; 473 474 float [] result = new float[2]; 475 result[0] = u; 476 result[1] = distFromLine / (params.width / 2f); 477 return result; 478 } 479 return null; 480 } 481 482 public void applyEffectToFleets(float amount) { 483 float days = Global.getSector().getClock().convertToDays(amount); 484 for (CampaignFleetAPI fleet : entity.getContainingLocation().getFleets()) { 485 applyEffect(fleet, days); 486 } 487 } 488 489 protected boolean playerWasInSlipstream = false; 490 public void applyEffect(SectorEntityToken other, float days) { 491 if (other instanceof CampaignFleetAPI) { 492 CampaignFleetAPI fleet = (CampaignFleetAPI) other; 493 494// if (fleet.isPlayerFleet()) { 495// System.out.println("efwefwef"); 496// } 497 498 float [] offset = getLengthAndWidthFractionWithinStream(fleet.getLocation()); 499 if (offset == null) { 500 if (fleet.isPlayerFleet()) { 501 playerWasInSlipstream = false; 502 } 503 return; 504 } 505 506 float burnBonus = fleet.getFleetData().getBurnLevel() - fleet.getFleetData().getMinBurnLevelUnmodified(); 507 if (burnBonus < 0) burnBonus = 0; 508 float maxSpeedWithWind = Misc.getSpeedForBurnLevel(params.burnLevel + burnBonus + 1.2f); 509 if (fleet.getVelocity().length() >= maxSpeedWithWind) { 510 return; 511 } 512 513 float fL = offset[0]; 514 float fW = offset[1]; 515 516 float intensity = 1f; 517 if (fL > 0.75f) { 518 intensity = (1f - fL) / 0.25f; 519 } else if (fL < 0.5f) { 520 intensity = fL / 0.5f; 521 } 522 if (fW > 0.5f) { 523 intensity *= (1f - fW) / 0.5f; 524 } 525 //intensity *= intensity; 526 527 if (intensity <= 0) { 528 if (fleet.isPlayerFleet()) { 529 playerWasInSlipstream = false; 530 } 531 return; 532 } 533 534 if (fleet.isPlayerFleet()) { 535 if (!playerWasInSlipstream) { 536 playerWasInSlipstream = true; 537 fleet.addFloatingText("Entering slipstream", Misc.setAlpha(fleet.getIndicatorColor(), 255), 0.5f); 538 } 539 } 540 541 //System.out.println("Intensity: " + intensity); 542 543 // "wind" effect - adjust velocity 544 float maxFleetBurn = fleet.getFleetData().getBurnLevel(); 545 float currFleetBurn = fleet.getCurrBurnLevel(); 546 547 float maxWindBurn = params.burnLevel * 2f; 548 549 float currWindBurn = intensity * maxWindBurn; 550 float maxFleetBurnIntoWind = maxFleetBurn - Math.abs(currWindBurn); 551 float seconds = days * Global.getSector().getClock().getSecondsPerDay(); 552 553// float angle = Misc.getAngleInDegreesStrict(this.entity.getLocation(), fleet.getLocation()) + 180f; 554// Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(angle); 555 Vector2f windDir = Misc.getUnitVectorAtDegreeAngle(entity.getFacing()); 556 if (currWindBurn < 0) { 557 windDir.negate(); 558 } 559 Vector2f velDir = Misc.normalise(new Vector2f(fleet.getVelocity())); 560 velDir.scale(currFleetBurn); 561 562 float fleetBurnAgainstWind = -1f * Vector2f.dot(windDir, velDir); 563 564 float accelMult = 0.5f; 565// if (fleetBurnAgainstWind > maxFleetBurnIntoWind) { 566// accelMult += 0.75f + 0.25f * (fleetBurnAgainstWind - maxFleetBurnIntoWind); 567// } 568 accelMult *= 2f; 569 570 571 572 float windSpeed = Misc.getSpeedForBurnLevel(currWindBurn); 573 //float fleetSpeed = fleet.getTravelSpeed(); 574 Vector2f windVector = new Vector2f(windDir); 575 windVector.scale(windSpeed); 576 577 Vector2f vel = fleet.getVelocity(); 578 Vector2f diff = Vector2f.sub(windVector, vel, new Vector2f()); 579 //windDir.scale(seconds * fleet.getAcceleration()); 580 float max = diff.length(); 581 diff = Misc.normalise(diff); 582 //diff.scale(Math.max(windSpeed * seconds, fleet.getAcceleration() * 1f * seconds)); 583 diff.scale(fleet.getAcceleration() * 3f * seconds); 584 //diff.scale(fleet.getTravelSpeed() * 5f * seconds); 585 //diff.scale(accelMult); 586 if (diff.length() > max) { 587 diff.scale(max / diff.length()); 588 } 589 //System.out.println("Applying diff: " + diff); 590 //fleet.setVelocity(vel.x + diff.x, vel.y + diff.y); 591 592 593// Vector2f velDir = Misc.normalise(new Vector2f(fleet.getVelocity())); 594// velDir.scale(currFleetBurn); 595// 596// float fleetBurnAgainstWind = -1f * Vector2f.dot(windDir, velDir); 597// 598 accelMult = 0.5f; 599 if (fleetBurnAgainstWind > maxFleetBurnIntoWind) { 600 accelMult += 0.75f + 0.25f * (fleetBurnAgainstWind - maxFleetBurnIntoWind); 601 } 602 603 //Vector2f vel = fleet.getVelocity(); 604 //windDir.scale(seconds * fleet.getAcceleration() * accelMult); 605 windDir.scale(seconds * Math.max(fleet.getTravelSpeed(), fleet.getAcceleration()) * accelMult); 606 fleet.setVelocity(vel.x + windDir.x, vel.y + windDir.y); 607 608 609 Color glowColor = params.spriteColor1; 610 int alpha = glowColor.getAlpha(); 611 if (alpha < 75) { 612 glowColor = Misc.setAlpha(glowColor, 75); 613 } 614 // visual effects - glow, tail 615 616 float fleetSpeedAlongWind = Vector2f.dot(windDir, fleet.getVelocity()); 617 float fleetSpeed = fleet.getVelocity().length(); 618 619 float matchingWindFraction = fleetSpeedAlongWind/windSpeed; 620 float effectMag = 1f - matchingWindFraction * 0.5f; 621 if (effectMag > 0f) effectMag = 0f; 622 if (effectMag < 0.5f) effectMag = 0.5f; 623 624 String modId = "slipstream_" + entity.getId(); 625 float durIn = 1f; 626 float durOut = 3f; 627 Misc.normalise(windDir); 628 float sizeNormal = 10f + 25f * intensity * effectMag; 629 for (FleetMemberViewAPI view : fleet.getViews()) { 630 view.getWindEffectDirX().shift(modId, windDir.x * sizeNormal, durIn, durOut, 1f); 631 view.getWindEffectDirY().shift(modId, windDir.y * sizeNormal, durIn, durOut, 1f); 632 view.getWindEffectColor().shift(modId, glowColor, durIn, durOut, intensity); 633 } 634 } 635 } 636} 637 638 639 640 641