001package com.fs.starfarer.api.util; 002 003import org.lwjgl.util.vector.Vector2f; 004 005import com.fs.starfarer.api.campaign.SectorEntityToken; 006 007public class CampaignEntityMovementUtil { 008 009 public static interface EngineGlowControls { 010 void showAccelerating(); 011 void showIdling(); 012 void showSuppressed(); 013 void showOtherAction(); 014 } 015 016 public static float DIRECTION_UNSET = Float.MAX_VALUE; 017 018 protected SectorEntityToken entity; 019 protected SmoothFacingUtil facingUtil; 020 protected SmoothMovementUtil movementUtil; 021 protected boolean turnThenAccelerate = true; 022 protected boolean faceInOppositeDirection = false; 023 protected float moveDir; 024 protected float desiredFacing = DIRECTION_UNSET; 025 protected Vector2f moveDest; 026 protected EngineGlowControls engineGlow; 027 028 public CampaignEntityMovementUtil(SectorEntityToken entity, 029 float turnAccel, float maxTurnRate, float accel, float maxSpeed) { 030 this.entity = entity; 031 032 facingUtil = new SmoothFacingUtil(turnAccel, maxTurnRate); 033 movementUtil = new SmoothMovementUtil(); 034 035 movementUtil.setAcceleration(accel); 036 movementUtil.setMaxSpeed(maxSpeed); 037 038 moveDir = DIRECTION_UNSET; 039 moveDest = null; 040 } 041 042 public boolean isFaceInOppositeDirection() { 043 return faceInOppositeDirection; 044 } 045 046 public void setFaceInOppositeDirection(boolean faceInOppositeDirection) { 047 this.faceInOppositeDirection = faceInOppositeDirection; 048 } 049 050 public boolean isTurnThenAccelerate() { 051 return turnThenAccelerate; 052 } 053 054 public void setTurnThenAccelerate(boolean turnThenAccelerate) { 055 this.turnThenAccelerate = turnThenAccelerate; 056 } 057 058 public SmoothFacingUtil getFacingUtil() { 059 return facingUtil; 060 } 061 062 public SmoothMovementUtil getMovementUtil() { 063 return movementUtil; 064 } 065 066 public void moveInDirection(float dir) { 067 moveDir = dir; 068 moveDest = null; 069 leaveOrbit(); 070 } 071 public void moveToLocation(Vector2f loc) { 072 moveDir = DIRECTION_UNSET; 073 moveDest = loc; 074 leaveOrbit(); 075 } 076 077 public void stop() { 078 moveDir = DIRECTION_UNSET; 079 moveDest = new Vector2f(entity.getLocation()); 080 leaveOrbit(); 081 } 082 083 public void leaveOrbit() { 084 if (entity.getOrbit() != null) { 085 setFacing(entity.getFacing()); 086 setLocation(entity.getLocation()); 087 setVelocity(entity.getVelocity()); 088 entity.setOrbit(null); 089 } 090 } 091 092 protected Vector2f getPointInDirectionOppositeToVelocity() { 093 Vector2f p = new Vector2f(entity.getLocation()); 094 if (entity.getVelocity().length() > 0) { 095 Vector2f back = new Vector2f(entity.getVelocity()); 096 Misc.normalise(back); 097 back.negate(); 098 back.scale(10f); 099 Vector2f.add(back, entity.getLocation(), back); 100 p = back; 101 } 102 return p; 103 } 104 105 public void advance(float amount) { 106 //movementUtil.setAcceleration(20f); 107 if (entity.getOrbit() == null) { 108 Vector2f dest; 109 110 if (moveDir != DIRECTION_UNSET) { 111 dest = Misc.getUnitVectorAtDegreeAngle(moveDir); 112 dest.scale(100000000f); 113 Vector2f.add(dest, entity.getLocation(), dest); 114 desiredFacing = moveDir; 115 } else if (moveDest != null) { 116 desiredFacing = Misc.getAngleInDegrees(entity.getLocation(), moveDest); 117 dest = moveDest; 118 } else { 119 desiredFacing = entity.getFacing(); 120 dest = getPointInDirectionOppositeToVelocity(); 121 } 122 123 if (faceInOppositeDirection) desiredFacing += 180f; 124 125 float angleDiff = Misc.getAngleDiff(entity.getFacing(), desiredFacing); 126 boolean turnOnly = turnThenAccelerate && angleDiff > 2f; 127 if (turnOnly) { 128 dest = getPointInDirectionOppositeToVelocity(); 129 } 130 131 movementUtil.setDest(dest, new Vector2f()); 132 movementUtil.advance(amount); 133 facingUtil.advance(desiredFacing, amount); 134 135 entity.setFacing(facingUtil.getFacing()); 136 entity.getLocation().set(movementUtil.getLocation()); 137 entity.getVelocity().set(movementUtil.getVelocity()); 138 139 if (engineGlow != null) { 140 if (turnOnly || angleDiff > 30f) { 141 engineGlow.showOtherAction(); 142 } else { 143 engineGlow.showAccelerating(); 144 } 145 } 146 147 } else { 148 if (engineGlow != null) { 149 engineGlow.showIdling(); 150 } 151 desiredFacing = DIRECTION_UNSET; 152 } 153 } 154 155 public boolean isDesiredFacingSet() { 156 return desiredFacing != DIRECTION_UNSET; 157 } 158 159 public float getDesiredFacing() { 160 return desiredFacing; 161 } 162 163 164 public SectorEntityToken getEntity() { 165 return entity; 166 } 167 168 public void setFacing(float facing) { 169 facingUtil.setFacing(facing); 170 entity.setFacing(facing); 171 } 172 173 public void setLocation(Vector2f loc) { 174 movementUtil.getLocation().set(loc); 175 entity.getLocation().set(movementUtil.getLocation()); 176 } 177 public void setVelocity(Vector2f vel) { 178 movementUtil.getVelocity().set(vel); 179 entity.getVelocity().set(movementUtil.getVelocity()); 180 } 181 182 public EngineGlowControls getEngineGlow() { 183 return engineGlow; 184 } 185 186 public void setEngineGlow(EngineGlowControls engineGlow) { 187 this.engineGlow = engineGlow; 188 } 189 190} 191 192 193 194 195 196 197