Starsector API
Loading...
Searching...
No Matches
VelocityField.java
Go to the documentation of this file.
1package com.fs.starfarer.api.impl.campaign.velfield;
2
3import java.util.Random;
4
5import org.lwjgl.util.vector.Vector2f;
6
7import com.fs.starfarer.api.Global;
8import com.fs.starfarer.api.campaign.CampaignFleetAPI;
9import com.fs.starfarer.api.campaign.CampaignTerrainAPI;
10import com.fs.starfarer.api.impl.campaign.ids.Terrain;
11import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamBuilder.StreamType;
12import com.fs.starfarer.api.impl.campaign.velfield.SlipstreamTerrainPlugin2.SlipstreamParams2;
13import com.fs.starfarer.api.util.Misc;
14
27public class VelocityField {
28
29 public static float RAD_PER_DEG = 0.01745329251f;
30 public static Vector2f rotateAroundOrigin(Vector2f v, float cos, float sin) {
31 Vector2f r = new Vector2f();
32 r.x = v.x * cos - v.y * sin;
33 r.y = v.x * sin + v.y * cos;
34 return r;
35 }
36
37 protected Vector2f[][] field;
38 protected float cellSize;
39
40 public VelocityField(int width, int height, float cellSize) {
41 field = new Vector2f[width][height];
42 this.cellSize = cellSize;
43
44 for (int i = 0; i < field.length; i++) {
45 for (int j = 0; j < field[0].length; j++) {
46 field[i][j] = new Vector2f();
47 }
48 }
49 }
50
51 public Vector2f[][] getField() {
52 return field;
53 }
54
55 public Vector2f getCell(int i, int j) {
56// if (i < 0 || j < 0) return new Vector2f();
57// if (i >= field.length || j >= field[0].length) return new Vector2f();
58 if (i < 0) i = 0;
59 if (j < 0) j = 0;
60 if (i >= field.length) i = field.length - 1;
61 if (j >= field[0].length) j = field[0].length - 1;
62 return field[i][j];
63 }
64
65 public boolean isInsideField(float x, float y, Vector2f bottomLeft, float angle) {
67
68 x -= bottomLeft.x;
69 y -= bottomLeft.y;
70 Vector2f temp = new Vector2f(x, y);
71 temp = rotateAroundOrigin(temp, cachedCos, -cachedSin);
72 x = temp.x;
73 y = temp.y;
74
75 if (x < 0) return false;
76 if (y < 0) return false;
77
78 float w = cellSize * (field.length - 1f);
79 if (x > w) return false;
80 float h = cellSize * (field[0].length - 1f);
81 if (y > h) return false;
82 return true;
83 }
84
85 transient float cacheKeyAngle;
86 transient float cachedSin;
87 transient float cachedCos;
88 public void updateCacheIfNeeded(float angle) {
89 if (cacheKeyAngle != angle) {
90 cacheKeyAngle = angle;
91 cachedCos = (float) Math.cos(angle * RAD_PER_DEG);
92 cachedSin = (float) Math.sin(angle * RAD_PER_DEG);
93 }
94 }
95
96 public Vector2f getVelocity(float x, float y, Vector2f bottomLeft, float angle) {
98
99 x -= bottomLeft.x;
100 y -= bottomLeft.y;
101 Vector2f temp = new Vector2f(x, y);
102 temp = rotateAroundOrigin(temp, cachedCos, -cachedSin);
103 x = temp.x;
104 y = temp.y;
105
106 int cellX1 = (int) (x / cellSize);
107 int cellY1 = (int) (y / cellSize);
108 if (x < 0) cellX1 = (int) (-1f * Math.abs(x) / cellSize) - 1;
109 if (y < 0) cellY1 = (int) (-1f * Math.abs(y) / cellSize) - 1;
110
111 int cellX2 = cellX1 + 1;
112 int cellY2 = cellY1 + 1;
113
114 float px = (x / cellSize) - (float) cellX1;
115 float py = (y / cellSize) - (float) cellY1;
116
117 // px, py describe where the point (x, y) is in the cell between the vertices of the cell that has
118 // cellX, cellY as its bottom left corner
119
120 //System.out.println(cellX1 + "," + cellY1 + " from x, cellSize: " + x + "," + cellSize);
121
122 Vector2f bl = getCell(cellX1, cellY1);
123 Vector2f br = getCell(cellX2, cellY1);
124 Vector2f tl = getCell(cellX1, cellY2);
125 Vector2f tr = getCell(cellX2, cellY2);
126
127 Vector2f result = new Vector2f();
128 result.x = (1f - py) * (bl.x * (1f - px) + br.x * px) + py * (tl.x * (1f - px) + tr.x * px);
129 result.y = (1f - px) * (bl.y * (1f - py) + tl.y * py) + px * (br.y * (1f - py) + tr.y * py);
130 result = rotateAroundOrigin(result, cachedCos, cachedSin);
131 return result;
132 }
133
134
135// public Vector2f getVelocityOld(float x, float y, Vector2f bottomLeft, float angle) {
136// x -= bottomLeft.x;
137// y -= bottomLeft.y;
138// Vector2f temp = new Vector2f(x, y);
139// temp = rotateAroundOrigin(temp, -angle);
140// x = temp.x;
141// y = temp.y;
142//
143//
144// int cellX1 = (int) (x / cellSize);
145// int cellY1 = (int) (y / cellSize);
146// if (x < 0) cellX1 = (int) (-1f * Math.abs(x) / cellSize) - 1;
147// if (y < 0) cellY1 = (int) (-1f * Math.abs(y) / cellSize) - 1;
148//
149// int cellX2 = cellX1 + 1;
150// int cellY2 = cellY1 + 1;
151//
152// float px = (x / cellSize) - (float) cellX1;
153// float py = (y / cellSize) - (float) cellY1;
154//
155// // px, py describe where the point (x, y) is in the cell between the vertices of the cell that has
156// // cellX, cellY as its bottom left corner
157//
158// //System.out.println(cellX1 + "," + cellY1 + " from x, cellSize: " + x + "," + cellSize);
159//
160// Vector2f bl = getCell(cellX1, cellY1);
161// Vector2f br = getCell(cellX2, cellY1);
162// Vector2f tl = getCell(cellX1, cellY2);
163// Vector2f tr = getCell(cellX2, cellY2);
164//
165// Vector2f result = new Vector2f();
166// result.x = (1f - py) * (bl.x * (1f - px) + br.x * px) + py * (tl.x * (1f - px) + tr.x * px);
167// result.y = (1f - px) * (bl.y * (1f - py) + tl.y * py) + px * (br.y * (1f - py) + tr.y * py);
168// result = rotateAroundOrigin(result, angle);
169// return result;
170// }
171
172
173 public float getCellSize() {
174 return cellSize;
175 }
176
177 public void shiftDown() {
178 for (int i = 0; i < field.length; i++) {
179 for (int j = 0; j < field[0].length - 1; j++) {
180 field[i][j] = field[i][j + 1];
181 }
182 }
183
184 for (int i = 0; i < field.length; i++) {
185 field[i][field[0].length - 1] = new Vector2f();
186 }
187 }
188
189 public static void spawnTest() {
190 CampaignFleetAPI pf = Global.getSector().getPlayerFleet();
191 SlipstreamParams2 params = new SlipstreamParams2();
192
193 params.burnLevel = 30;
194 params.minSpeed = Misc.getSpeedForBurnLevel(params.burnLevel - 5);
195 params.maxSpeed = Misc.getSpeedForBurnLevel(params.burnLevel + 5);
196 params.lineLengthFractionOfSpeed = 0.25f * Math.max(0.25f, Math.min(1f, 30f / (float) params.burnLevel));
197
198// params.minColor = new Color(0.5f, 0.3f, 0.75f, 0.1f);
199// params.maxColor = new Color(0.5f, 0.6f, 1f, 0.3f);
200
201 //params.slowDownInWiderSections = true;
202
203// params.baseWidth = 1025f;
204// params.widthForMaxSpeed = 768f;
205
206// float width = 512;
207// params.widthForMaxSpeed = width;
208
209 //params.numParticles = 500;
210// CustomCampaignEntityAPI e =
211// Global.getSector().getCurrentLocation().addCustomEntity(null, null, "slipstream2", Factions.NEUTRAL, params);
212// e.setLocation(pf.getLocation().x + 200f, pf.getLocation().y + 200f);
213
214
215 CampaignTerrainAPI slipstream = (CampaignTerrainAPI) Global.getSector().getCurrentLocation().addTerrain(Terrain.SLIPSTREAM, params);
216 slipstream.setLocation(pf.getLocation().x + 200f, pf.getLocation().y + 200f);
217
218 SlipstreamTerrainPlugin2 plugin = (SlipstreamTerrainPlugin2) slipstream.getPlugin();
219 float spacing = 200f;
220
221 long seed = 23895464576452L + 4384357483229348234L;
222 seed = 1181783497276652981L ^ seed;
223 seed *= 27;
224 Random random = new Random(seed);
225 //random = Misc.random;
226 SlipstreamBuilder builder = new SlipstreamBuilder(slipstream.getLocation(), plugin, StreamType.WIDE, random);
227 //builder.buildTest();
228 Vector2f to = new Vector2f(slipstream.getLocation());
229 to.x += 20000;
230 to.y += 20000;
231// to.x += 160000;
232// to.y += 100000;
233 //builder.buildToDestination(to);
234 Vector2f control = new Vector2f(slipstream.getLocation());
235 control.x += 10000f;
236 //control.x += 160000f;
237 builder.buildToDestination(control, to);
238 //builder.buildToDestination(to);
239
240 //new SlipstreamManager().checkIntersectionsAndFadeSections(plugin);
241
242 //plugin.despawn(5f);
243
244// int iter = 100;
245// for (int i = 0; i < iter; i++) {
246// float yOff = (float) Math.sin(i * 0.05f);
247// float w = width + i * 10f;
248// //float currSpacing = Math.max(spacing, width / 2f);
249// float currSpacing = spacing;
250// plugin.addSegment(new Vector2f(slipstream.getLocation().x + i * currSpacing,
251// //addSegment(new Vector2f(entity.getLocation().x + i * (spacing + (50 - i) * 5),
252// slipstream.getLocation().y + yOff * 2000f),
253// //width);
254// //width * (0.7f + (float) Math.random() * 0.7f));
255// w);
256// }
257
258
259 //SlipstreamEntityPlugin plugin = (SlipstreamEntityPlugin) e.getCustomPlugin();
260 //TurbulenceEntityPlugin plugin = (TurbulenceEntityPlugin) e.getCustomPlugin();
261
262// VelocityField f = new VelocityField(11, 31, 100f);
263// plugin.setField(f);
264
265
266
267 }
268
269
270}
271
272
273
static SectorAPI getSector()
Definition Global.java:59
void buildToDestination(Vector2f control, Vector2f control2, Vector2f to)
static Vector2f rotateAroundOrigin(Vector2f v, float cos, float sin)
VelocityField(int width, int height, float cellSize)
boolean isInsideField(float x, float y, Vector2f bottomLeft, float angle)
Vector2f getVelocity(float x, float y, Vector2f bottomLeft, float angle)