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