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