Hi, I am writing a game in which an object at a PointF travelling at a current velocity (Vector2) is trying to reach a destination PointF (which can change between movement steps)

At each step of movement I need to decide the acceleration vector that will get to the point the fastest.

So the result should be the ship adjusts its current velocity so that it always moves towards the target point at stead acceleration unless doing so would mean there isn't enough time to slow down before reaching it in which case it should begin decelerating.

This has been doing my head in a bit and the code I have at the moment seems to just make the ships orbit the point:

Vector2 v_target   = new Vector2(target.X,target.Y);
            Vector2 v_currentLocation = new Vector2(this.Location.X,this.Location.Y);
            Vector2 v_currentVelocity = new Vector2(f_velocityX, f_velocityY);

            //calculate vector in direction of target of length f_accelleration
//this line here is fundamentally flawed it can't just acclerate towards the target it has to take into account the current velocity direction somehow (which might not be in the direction of the current target)
            Vector2 v_acceleration = new Vector2(target.X - Location.X, target.Y - Location.Y);
            v_acceleration.Normalize();
            v_acceleration.Multiply(f_acceleration);

            //if we keep decelerating from current velocity
            int i_shouldDecelerate = VectorShouldDecelerate(v_target, v_currentLocation, v_currentVelocity, v_acceleration);

            if (i_shouldDecelerate ==-1)
            {
                f_velocityX += v_acceleration.X;
                f_velocityY += v_acceleration.Y;
            }
            else
            if (i_shouldDecelerate == 1)
            {
                f_velocityX -= v_acceleration.X;
                f_velocityY -= v_acceleration.Y;
            }

            this.Location = new PointF(this.Location.X + f_velocityX, this.Location.Y + f_velocityY);
}

private int VectorShouldDecelerate(Vector2 in_target, Vector2 in_location, Vector2 in_currentVelocity, Vector2 in_acceleration)
        {
            if (in_location.Equals(in_target))
                return 0;

            //if we start decelerating now, will we overshoot
            Vector2 velocityWhenDecelerating = in_currentVelocity;
            Vector2 stoppingPoint = in_location;
            float f_previousLength = velocityWhenDecelerating.Length();
            while (velocityWhenDecelerating.Length() < in_acceleration.Length())
            {
                
                //reduce velocity
                velocityWhenDecelerating.Subtract(in_acceleration);
                //calculate stopping point
                stoppingPoint.Add(velocityWhenDecelerating);
                f_previousLength = velocityWhenDecelerating.Length();
            }

            //if we have arrived
            stoppingPoint.Subtract(in_target);
            if (stoppingPoint.Length() < in_acceleration.Length())
                return 1;

            else return -1;
          
        }

Well I've eventually worked out the following (after talking to a friend of mine), It does a good job at flying from any fixed point to the target using appropriate accelleration/deceleration and is able to compensate fairlly when the you wave the target point around and they can usually get back to the point with only a couple of tight concentric orbits.

Feel free to use the code in your own programs if you ever need to:

//get targets location
            PointF target = Squad.Formation.ApplyFormation(i_unitPositionInSquad, this.Squad.Location);
            //get the velocity we are currently travelling at
            Vector2 v_currentVelocity = new Vector2(f_velocityX, f_velocityY);
            //this is a vector directly to the target, it will be the direction we would idealy be going
            Vector2 v_idealVelocity = new Vector2(target.X - Location.X, target.Y - Location.Y);

            //dont bother moving if its less than 1 pixel awat to prevent dithering
            if (v_idealVelocity.Length() <= 1)
                return;

            //because our ideal vector goes all the way to the point we don't leave any time to slow down so
            //we will run a loop to calculate a new better idealVelocity vector
            
            //this is the velocity we would be travelling at if we slowed down next step
            Vector2 v_iterationVelocity = v_idealVelocity;
            v_iterationVelocity.Normalize();
            v_iterationVelocity.Multiply(v_currentVelocity.Length());

            //this is the vector that represents 1 slowdown of length f_accelleration down the ideal vector
            Vector2 v_slowdownEachStep = v_idealVelocity;
            v_slowdownEachStep.Normalize();
            v_slowdownEachStep.Multiply(f_acceleration);

            //while we have not reached the subsequent step where we would be stopped
            while (v_iterationVelocity.Length() > 1)
            {
                //reduce this steps velocity by the deceleration vector
                v_iterationVelocity.Subtract(v_slowdownEachStep);
                
                //move our ACTUAL ideal velocty vector closer to us by a distance equal to this slowdown step,
                //This will adjust our ideal vector which originally went all the way to the target closer so as
                //to allow time to slow down
                v_idealVelocity.Subtract(v_iterationVelocity);
            }

            //to find our new acceleration vector that we will be applying get the difference
            //between our ideal vector and our current vector and accelerate down it.
            Vector2 v_stefansVector = v_idealVelocity;
            v_stefansVector.Subtract(v_currentVelocity);
            v_stefansVector.Normalize();
            v_stefansVector.Multiply(f_acceleration);

            f_velocityX += v_stefansVector.X;
            f_velocityY += v_stefansVector.Y;
            
            //adjust our coordinates
            this.Location = new PointF(this.Location.X + f_velocityX, this.Location.Y + f_velocityY);
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.