# C++ Passing Functions to Objects/Projectile system woes

I am new to C++ development and I am trying to create a more flexible projectile system.

In my current system I apply a equation to move the point down the bullet path.

class Bullet{
public:
float x;
float y;
float speed;
float angle;

void Update(){
x=(speed*cos(angle)) + x;
y=(speed*sin(angle)) + y;
};
}

This works fine for moving a bullet on an angle, however I would like to generate much more complex paths, without over complicating the bullet class.

My idea was to pass a function to the bullet class that would be used to move the object but I have not found any way to do this.

Example of what I want to do:

class Bullet{
public:
function dostuff();
float x;
float y;
float angle;

void Update(){
dostuff(x,y,angle,speed);
};
};

class Enemy{
public:
float x;
float y;
float speed;
float angle;

void shoot(){
Bullet bullet;

auto movangle = [](float x, float y, float angle,float speed)
{
x=(speed*cos(angle)) + x;
y=(speed*sin(angle)) + y;
};
bullet.dostuff = movangle;
bullet.Update();
};
};

If anyone knows of any ways to implement a system like this, or ideas on alternatives that could produce similar results It would be appreciated as I am somewhat stumped.

The specific feature you're looking for in C++ is std::function. I am not saying that this is the best way to implement the actual feature you've asked for (though it's a perfectly sufficient one for some games!), but it is the solution you've asked for help implementing. :)

class Bullet{
public:
std::function<void(float x, float y, float angle, float speed)> dostuff;
float x;
float y;
float angle;

void Update(){
dostuff(x,y,angle,speed);
};
};

For functions that are reused in many places, it can be handy to make a type alias for convenience:

using DoStuffFunction = std::function<void(float x, float y, float angle, float speed)>;

class Bullet{
public:
DoStuffFunction  dostuff;

...
};

Other approaches might include sub-classes and virtual as the other answer suggested, using an enum that controls different behaviors, or decomposing Bullet into different data structures (e.g. in an ECS architecture). Each of these have pros and cons.

• After fiddling around with this I realize my greatest issue now is passing a lambda to the function or something similar that would allow a function to be created and passed down to the bullet object to use. – Sam Boman Sep 25 '19 at 13:31

You could use a new class BulletPath (or something) which would handle all the movement angles and stuff of the bullets. It would be created by the object who fires and used in the class Bullet to control its movement. The advantage is that you could make a different path for any kind of Enemy. You'll just have to add it as a parameter in the Bullet class. Any Enemy could have its own BulletPath depending of what you want to do.

class BulletPath { // can be extended
float x;
float y;
// all the parameters you need
public void move(Bullet bullet)
{
// move it
}
// you could use BulletPath
// as an interface too to be even
//  even more flexible.
}

class Enemy {
private BulletPath path; //initialize it

public void shoot() {
path.move(new Bullet());
// do what you want
}
}

If you are a bit used to C++, you could also use functors, which principle and utilisation is explained here on StackOverflow. To sum it up, it allows you to have a class which also can be used as a function. You just call Bullet() when you need it to move and handle the movements in a function in Bullet (which will be a function overriding the operator ()).

• Although a BulletPath class might work, It still seems like I would still have to define every single different path type in the class, which I was trying to avoid. – Sam Boman Sep 24 '19 at 14:10
• You'd have to define every single path you want to create on the BulletPath class, and make it modify the direction of the bullet without overcomplicating the class Bullet. In terms of conception, I think it would be logical to have either the gun or the ennemy to decide what direction the bullet will have. I will edit my answer to show a more concrete example. – Badda Sep 24 '19 at 20:42