001package com.fs.starfarer.api.util;
002
003import org.lwjgl.util.vector.ReadableVector2f;
004import org.lwjgl.util.vector.Vector2f;
005
006public class SmoothMovementUtil {
007
008        protected Vector2f vel = new Vector2f();
009        protected Vector2f loc = new Vector2f();
010        protected Vector2f accel = new Vector2f();
011        
012        protected Vector2f dest = new Vector2f();
013        protected Vector2f destVel = new Vector2f();
014        
015        protected float acceleration, maxSpeed;
016        protected boolean smoothCap = false;
017
018        protected float hardSpeedLimit = -1f;
019        
020        public float getHardSpeedLimit() {
021                return hardSpeedLimit;
022        }
023
024        public void setHardSpeedLimit(float hardSpeedLimit) {
025                this.hardSpeedLimit = hardSpeedLimit;
026        }
027
028        public SmoothMovementUtil() {
029                acceleration = 1f;
030                maxSpeed = 1f;
031                smoothCap = true;
032        }
033
034        public void setDest(Vector2f dest, Vector2f destVel) {
035                if (dest == null) {
036                        this.dest.set(0, 0);
037                } else {
038                        this.dest.set(dest);
039                }
040                if (destVel == null) {
041                        float dir = Misc.getAngleInDegrees(loc, this.dest);
042                        this.destVel = Misc.getUnitVectorAtDegreeAngle(dir);
043                        this.destVel.scale(10000f);
044                } else {
045                        this.destVel.set(destVel);
046                }
047        }
048        
049        public void advance(float amount) {
050                
051                if (amount * amount == 0 || amount <= 0) {
052                        return;
053                }
054                
055                float effectiveMaxSpeed = maxSpeed;
056                float accelMult = 1f;
057//              if (true && fleet != null) {
058//                      accelMult = 1f - Math.max(0, (fleet.getRadius() - 22f) / (100 - 22f));
059//                      accelMult = 0.25f + accelMult * 0.75f;
060//              }
061//              if (fleet != null && fleet.isPlayerFleet()) {
062//                      System.out.println("fwefwefe");
063//              }
064                        
065                float speed = vel.length();
066                float acc = acceleration;
067//              if (speed > effectiveMaxSpeed) {
068//                      acc = Math.max(speed, 200f) + fleet.getAcceleration();
069//              }
070                
071                float effectiveAccel = acc * accelMult;
072                
073                if (effectiveAccel <= 0f) {
074                        accel.set(0, 0);
075                        return;
076                }
077                //amount *= 20f;
078                
079                Vector2f toDest = Vector2f.sub(dest, loc, new Vector2f());
080                Vector2f velDiff = Vector2f.sub(destVel, vel, new Vector2f());
081                
082                //toDest.scale(3f);
083                
084                //Vector2f dir = Vector2f.sub(dest, loc, new Vector2f());
085                //Utils.normalise(dir);
086                
087                // positive means away from loc
088                //float relativeSpeed = Vector2f.dot(dir, destVel);
089                //float dist = Utils.getDistance(loc, dest);
090//              if (delegate == CampaignEngine.getInstance().getPlayerFleet()) {
091//                      System.out.println("23rsd1sdfew");
092//              }
093                float timeToMatchVel = velDiff.length() / effectiveAccel;
094                //toDest.scale(timeToMatchVel + 2f);
095                velDiff.scale(timeToMatchVel + 0.75f);
096                //velDiff.scale(0.5f * timeToMatchVel);
097                
098//              if (relativeSpeed > 0) {
099//                      velDiff.scale(dist / relativeSpeed);
100//              } else {
101//                      velDiff.scale(timeToMatchVel);
102//              }
103                
104                // this is the vector we want to negate (reduce to zero) in order to match
105                // location and speed. Units are distance.
106                Vector2f negate = (Vector2f) Vector2f.add(toDest, velDiff, new Vector2f()).negate();
107                //if (negate.lengthSquared() < 0.25f) negate.set(0, 0);
108                
109//              if (delegate == CampaignEngine.getInstance().getPlayerFleet()) {
110//                      System.out.println(toDest);
111//              }
112                
113                float maxAccel = negate.length() / (amount * amount);
114                if (maxAccel > effectiveAccel) maxAccel = effectiveAccel;
115                //maxAccel = 280f;
116                //maxAccel = acceleration;
117                if (maxAccel > 0) {
118                        accel = (Vector2f) Misc.normalise(negate).scale(-maxAccel);
119                } else {
120                        accel = (Vector2f) negate.negate();
121                }
122//              accel = (Vector2f) Utils.normalise(negate).scale(-maxAccel);
123//              if (delegate == CampaignEngine.getInstance().getPlayerFleet()) {
124//                      System.out.println("Max: " + maxAccel);
125//              }
126                
127//              float speedPre = vel.length();
128//              if (delegate == CampaignEngine.getInstance().getPlayerFleet()) {
129//                      System.out.println("Speed pre: " + vel.length());
130//              }
131                vel.x += accel.x * amount;
132                vel.y += accel.y * amount;
133                
134                speed = vel.length();
135//              float speedPost = vel.length();
136//              if (delegate == CampaignEngine.getInstance().getPlayerFleet()) {
137//                      System.out.println("Speed post: " + vel.length());
138//                      System.out.println("");
139//              }
140//              if (delegate == CampaignEngine.getInstance().getPlayerFleet()) {
141//                      if (speedPre < speedPost) {
142//                              System.out.println(accel);
143//                      }
144//              }
145                
146                //float speed = vel.length();
147                if (speed >= effectiveMaxSpeed && speed > 0) {
148                        if (smoothCap) {
149//                              if (delegate == CampaignEngine.getInstance().getPlayerFleet()) {
150//                                      System.out.println("23refwef");
151//                              }
152                                Vector2f cap = new Vector2f(vel);
153                                cap.negate();
154                                Misc.normalise(cap);
155                                //float mag = 1f;
156                                //if (maxAccel * 2f > 1) {
157                                        //mag = maxAccel * 2f;
158                                //}
159                                //if (mag < 1000) mag = 1000;
160                                float mag = speed - effectiveMaxSpeed;
161                                if (mag < 50f) mag = 50f;
162                                
163                                float minMag = maxAccel * 2f;
164                                if (mag < minMag) mag = minMag;
165                                
166                                if (mag * amount > (speed - effectiveMaxSpeed) && amount > 0) {
167                                        mag = (speed - effectiveMaxSpeed) / amount;
168                                }
169                                cap.scale(mag);
170                                vel.x += cap.x * amount;
171                                vel.y += cap.y * amount;
172                        } else {
173                                vel.scale(effectiveMaxSpeed / speed);
174                        }
175                }
176                
177                if (hardSpeedLimit >= 0 && speed > 0) {
178                        vel.scale(hardSpeedLimit / speed);
179                }
180                
181                loc.x += vel.x * amount;
182                loc.y += vel.y * amount;
183                
184        }
185        
186        
187        public ReadableVector2f getAccelVector() {
188                return accel;
189        }
190
191        public float getAcceleration() {
192                return acceleration;
193        }
194
195        public void setAcceleration(float acceleration) {
196                this.acceleration = acceleration;
197        }
198
199        public float getMaxSpeed() {
200                return maxSpeed;
201        }
202        
203        public void setMaxSpeed(float maxSpeed) {
204                this.maxSpeed = maxSpeed;
205        }
206
207        public Vector2f getVelocity() {
208                return vel;
209        }
210
211        public Vector2f getLocation() {
212                return loc;
213        }
214
215        public Vector2f getDest() {
216                return dest;
217        }
218        
219}
220
221
222
223