Function Pointers I

It is a long time since i have written C++ code, i admit that it is too hard to leave this language and continue coding with C#, Java or Python, C++ has its own Magic 😉 😀

In this post, i am trying to refresh my C++ memory, and i think there is nothing better than playing with some Pointers 😀
I will talk about “Function Pointers”, actually we aren’t use them in projects or problem solving, but they are something that are worth to be mentioned when we talk about pointers.

We all know that pointer is a variable that points to another variable and holds its address, function pointer is the same but instead of pointing to a variable, it points to a function.

Function Pointer declaration


int (*func_ptr) (); // a function pointer that takes no arguments and returns an integer value

We declare a function pointer like that with parenthesis around func_ptr, because if we do that int *func_ptr() it will be treated as a function that returns a pointer to an interger.

Like variable pointers, function pointers can point to other data types functions …


long (*func_ptr_long) (); // function pointer that points to a long function

double (*func_ptr_doub) (); // function pointer that points to a double function

Declaring a function pointer depends on the function that it points to it and the number of arguments that that function has ..


int (*func_ptr) (); // a function pointer that points to function that has no arguments

int (*func_ptr1) (int); // a function pointer that points to a function that has 1 argument which is an integer variable

int (*func_ptr2) (int, int); // a function pointer that points to a function that has 2 arguments which are integer variables

Assigning a function to a function pointer


#include <stdio.h>

int func () { }

int main() {
    int (*func_ptr) () = func; // Assigning the func to the func_ptr

    return 0;
}

Remember, when you declare a function pointer you should make sure that its data type andnumber of arguments are the same to the function which it will points to


#include <stdio.h>

int func () {}

int func2 (int x) {}

int main() {
    double (*func_ptr) () = func; // Error, the data types aren't the same
    int (*func_ptr2) () = func2; // Error, the number of arguments are different

    return 0;
}

Calling a function using a function pointer

There are two ways to call a function using a pointer

Explicit dereference


#include <stdio.h>

int func (int a) {}

int main() {
    int (*func_ptr) (int) = func; // Assigning
    (*func_ptr) (9); // Calling the function

    return 0;
}

Implicit dereference


#include <stdio.h>

int func (int a) {}

int main() {
    int (*func_ptr) (int) = func; // Assigning
    func_ptr(9); // Calling the function

    return 0;
}

Implicit dereference is like calling a normal function as you see.

Example on using a function pointer to call a function then print its returned value.


#include <stdio.h>

int Sum (int a, int b) {
    return a + b;
}

int main() {
    int (*func_ptr) (int, int) = Sum; // Assigning the Sum function to a pointer
    int Result = func_ptr(3, 4); // Storing the returned value when calling the Sum function
    printf("%d\n", Result) ; // output : 7

    return 0;
}

Function pointer and Overloading

Function pointers support overloading …


#include <stdio.h>

int func(int a) {
return a + 1;
}

int func(int a, int b) {
return a + b;
}

int main() {
int (*func_ptr1) (int);
int (*func_ptr2) (int, int);
func_ptr1 = func; // func_ptr1 points to func(int)
func_ptr2 = func; // func_ptr2 points to func(int, int)

return 0;
}

Function pointer in memory

Like a variable pointer, function pointer points into memory, but the only difference that variable points directly to an address which already has data, but function pointer points to memory after the execution of the function.

Why using function pointers ?

You can use function pointers when you implement a function that you could change its behavior during your implementation without writing an exhaustive code.

Here is an example of using a function pointer to change the behavior of Bubble sort algorithm easily …


#include <stdio.h>

int Arr[] = {2, 3, 1, 6, 2, 0, 0, 1};

void BubbleSort(int Length, bool (*func_ptr) (int, int)) {

for(int i = 0; i < Length - 1; i++) {
    for(int j = 0; j < Length - i - 1; j++) {
        if(func_ptr(Arr[j], Arr[j + 1]) == true) {
           int Tmp = Arr[j];
           Arr[j] = Arr[j + 1];
           Arr[j + 1] = Tmp;
        }
     }
   }
}

inline bool Increasing(int First, int Second) {
    return First > Second;
}

inline bool Decreasing(int First, int Second) {
    return First < Second;
}

int main() {
    BubbleSort(8, Increasing);
    for(int i = 0; i < 8; i++) {
        printf("%d\n", Arr[i]);
    }
    puts("----");
    BubbleSort(8, Decreasing);
    for(int i = 0; i < 8; i++) {
        printf("%d\n", Arr[i]);
  }

 return 0;
}

Well, Hope Function pointers now becomes clear enough and i know that you can use Virtual functions and Polymorphism to do the same job, maybe next topic we will discuss something that similar to function pointers in C++11 Lambda Functions.

Steering Behaviors

Well, what are the Steering Behaviors ?
They are collection of techniques that helps the autonomous characters move in realistic manner, by using some forces that are combined together to produce a normal and natural movement.
This technique contains many behaviors, but i will explain the following:-

  • Seek.
  • Flee And Arrival.
  • Wandering.
  • Pursuit and Evade.

Seek
test

The direction of the velocity controls where the plane is heading or going to while its length controls how much it will move every frame, so, the greater of the length, the faster the plane moves.
To measure the wanted velocity vector that help the plane to reach to its target calculated as follows

Vector3  Normal = Vector3.Normalize(GameObject.Position - TargetPosition);
Vector3 DesiredVelocity = Normal * MaxVelocity;

This for only for calculating the velocity that the Enemy plane should use to reach the player, but without the steering the Plane will go in “Straight” Routes, which won’t be realistic, so we should add a “Steering force” that  makes the plane smoothly adjust its velocity, avoiding sudden path change , when the player plane changes its direction, the enemy “Gradually” changes its velocity vector to reach the player’s new position.

test

Those forces calculated as follows :-

Vector3  Normal = Vector3.Normalize(TargetPosition - GameObject.Position);
Vector3 DesiredVelocity = Normal * MaxVelocity;
return (DesiredVelocity - GameObject.LinearVelocity);

After adding all these forces, there will be a path that leads the enemy to the player positions every time.

Flee

This behavior uses the same forces that help the enemy plane seeking the Player, but it differs that it helps the enemy to Run Away from the player.

test

The desired velocity that helps the enemy to run away is calculated by subtracting the enemy’s position from the player’s position which produces a New vector that goes from the Player’s vector  towards the enemy.

Vector3  Normal = Vector3.Normalize(GameObject.Position - TargetPosition);
Vector3 DesiredVelocity = Normal * MaxVelocity;
return (DesiredVelocity - GameObject.LinearVelocity);

It is obvious that Flee Steering  =  -Seek Steering.

Now we should add these forces to create a “Fleeing Path” …
test

Arrival

This technique prevents the enemy from moving through the player, by slowing down its velocity when it reaches a specific area until it stops at the player .

This behavior consists of 2 phases or cases,

  • ⦁ When the enemy is outside the player area
  • ⦁ When it is in that area

The First phase is like the “Seeking behavior”, move to the player position with a capable velocity, the second phase when it reaches the player’s area.

test

When the enemy enters the slowing area its velocity is decreased linearly to ZERO, and this achieved by adding “Arrival Steering” , this addition reduces the enemy’s velocity till it stops.
but we should make sure that the enemy’s velocity will turn ZERO immediately , it should be decreased gradually.
to calculate the desired velocity and the distance to player :-

Vector3 DesiredVelocity  = TargetPosition - GameObject.Position;
float Distance = DesiredVelocity.Length();

Then we should check if the Enemy is in far from the Player or not(Distance to target  > 0), else we will return a new vector3()  :-

if(Distance > 0)
{
float Speed = (Distance / DeclerationVelocity * .3f);
     Speed = TruncateFloat(Speed, MaxVelocity);
     Vector3 DesiredVelocity = DistanceToTarget * Speed / Distance;
     return (DesiredVelocity - GameObject.LinearVelocity);
}
else
{
     return new Vector3();
}

P.S: the enemy’s original vector doesn’t change , but the addition vector affects to it that turns it to NULL, but when it is outside the Slowing area it will use its original velocity.

Wandering

The wandering steering help the enemy to act a realistic movement , which will make the player know that there is an enemy around and should take care about it.

The idea of implementing the wandering behaviors is producing a small random and apply to enemy’s current direction vector, these small displacement prevents the enemy’s plane to change its direction and rout immediately by changing its angle in every frame when the plane go right or left.

Now, we can use a circle in front of the enemy’s plane like that :-

test

The displacement force will interfere with the enemy’s plane route to calculate the Wander Force .
First of all we should determine the position of the Circle which will be in front of the Plane, and that can be done by make a copy of the velocity vector which mean that the center of the circle will in the same direction of the velocity vector, then it is normalized and multiplied by a scalar value.
Second, we should determine the displacement force , we can use a 2D vector instead of 3D, because the wandering is about moving the plane Right or left , it is known that greater of the circle radius the stronger the Wandering steering.
By implementing this behavior the plane could move randomly in the space.

WanderTarget = new Vector2(RandomClambed() * WanderJitter, RandomClambed() * WanderJitter);
WanderTarget.Normalize();
WanderTarget *= WanderRadius;
Vector2 DesiredLocalTarget = WanderTarget + new Vector2(WanderDistance, 0);

Pursuit and Evade

A pursuit is a process of following a target to catch it, but it differs from Seeking that pursuit is predicting where the target will be in the future, by implementing this technique it is possible to adjust current trajectory to avoid unnecessary paths.

test

The pursuit is like seeking behavior, the only difference that the pursuer won’t seek the target itself, but its future position, so the implementation won’t be very different, the following figure shows what we want to do :-

test

To know the future position of the target , we will use “Euler Integration” :

Position = Position + Velocity;

But we want to know the position in the future, so we will give the equation a factor of Number Game Updates (N), So this is the final equation :

Position = Position + Velocity * N;

If the value of N is high, this will lead to a good prediction, if N is close to Zero this means that the pursuer enemy won’t get the player position in the future.
After that we call the Seeking technique to get the path to future position.

return Seek(((TargetPosition + Target.LinearVelocity) * LookAheadTime));

LookAheadtime is a variable that has the value of Number of game updates.
the full implementation is as follow :-


Vector3 targetPos = aTarget.Position;
 //Check if face to face;
 Vector3 DistanceToVectorTarget = targetPos - GameObject.Position);
 double MyHeading = Vector3.Dot(Heading, aTarget.Heading);
 double TargetHeading = Vector3.Dot(aTarget.Heading, Heading);
 if((TargetHeading > 0) && (MyHeading < -0.95))
 {
return Seek(aTarget.Position);
 }
 float Speed = Magnitude(GameObject.LinearVelocity);
 //Predict the Direction to the target and head to it
 float LookAheadTime = (DistanceToVectorTarget.Length() / (aTarget.SteeringBehaviors.MaxVelocityFunction + Speed));
 LookAheadTime += TurnAroundTheTime(targetPos);

return Seek(((targetPos + aTarget.LinearVelocity) * LookAheadTime));

Evade

The opposite of the pursuit behavior , the enemy should flee away of the future position of the player.

test

 

To implement this behavior, we will do the same as Pursuit behavior, but this time we will call the Flee Function :-
The implementation is as follow :-


 Vector3 targetPos = aTarget.Position;
 //Check if face to face;
 Vector3 DistanceToVectorTarget = targetPos - GameObject.Position);
 double MyHeading = Vector3.Dot(Heading, aTarget.Heading);
 double TargetHeading = Vector3.Dot(aTarget.Heading, Heading);
 if((TargetHeading > 0) && (MyHeading < -0.95))
 {
     return Seek(aTarget.Position);
 }
 float Speed = Magnitude(GameObject.LinearVelocity);
 //Predict the Direction to the target and head to it
 float LookAheadTime = (DistanceToVectorTarget.Length() / (aTarget.SteeringBehaviors.MaxVelocityFunction + Speed));
 LookAheadTime += TurnAroundTheTime(targetPos);

return Flee(((targetPos + aTarget.LinearVelocity) * LookAheadTime));

There are other techniques in steering behaviors, but implementing the behaviors that I explained in this topic will be enough to generate a good realistic movement for the opponent units.

References :

http://www.red3d.com/cwr/steer/gdc99/