The tutorial shows how to do it.
Oops, I did the tutorial a while ago, and missed it I guess. Thank you.
This sounds questionable to me... So, how did you end up with a polymorphic function that needs to take completely different arguments in certain derived classes?
I know this forum isn't for general C++, but you asked, so here it is. The code you will see is probably the worst system I have ever written, but I can't come up with anything better, which is why I'm asking you if you know of a better way.
I am making a game, and have previously used Source SDK, which has a really nice and easy Input Output system between unrelated objects in the game. If you follow this link, and skip down to Outputs, you can read about how an output/input works, more or less. It's pretty short.
https://developer.valvesoftware.com/wiki/Inputs_and_OutputsMore importantly though:
http://gamedev.stackexchange.com/questions/32722/interactions-between-game-objectsThe way I interpreted the stack overflow post initially, I thought of this:
class IOBase
{
virtual void input(sf::packet packet);
};
class Bomb : public IOBase
{
void stop();
void explode();
void move(sf::Vector2f coordinates);
void input(sf::packet message)
{
message >> string inputFunc;
if(inputFunc == "stop")
stop();
else if(inputFunc == "move")
{
message >> parameter;
move(parameter);
}
ect...
}
};
class Door : public IOBase
{
void open();
void close();
void setSpeed(float speed);
//do the same thing, but for our functions
};
But then I thought, that might be slow if there are a lot of possible if statements to check. What if I could make it figure out what function to call while the game is loading.
That can be done using function pointers. Each Command object, when loaded, will figure out what function pointer to choose.
struct Command
{
sf::packet message;
FunctionPointer funcP;
};
//when the Command is loaded, there is an if block to determine what function pointer to use based on what was loaded from file, so we do the checks here instead of on the fly
//so later in code sometime after we have found target
(target.*funcP)(message);
class IOBase
{
virtual void input1(sf::packet parameters);
virtual void input2(sf::packet parameters);
virtual void input3(sf::packet parameters);
};
class Bomb : public IOBase
{
void stop();
virtual void input1(sf::packet parameters)
{
stop();//now we don't have to go through a big if block, we know input1 is associated with stop();
}
void explode();
virtual void input2(sf::packet parameters);//and this explode
void move(sf::Vector2f coordinates);
virtual void input3(sf::packet parameters);//and this move
};
class Door : public IOBase
{
void open();
virtual void input1(sf::packet parameters);
void close();
virtual void input2(sf::packet parameters);
void setSpeed(float speed);
virtual void input3(sf::packet parameters);
void kill()//note, for example these cannot be called in the IO system
void reset()
};
Keep in mind, there wouldn't be an input function for every possible function, just certain game play related ones, like to open a door, disable a trigger, or play a sound, but not kill, or reset in this case;
There are other problems now though:
1. The minimum number of functions IOBase has is determined by the class with the most callable functions.
2. If two classes have a function called "enable", then I have to make sure that they all use the same IOBase input function, which wouldn't be too hard, but it's sort of like book keeping, and that is just stupid.
3. You can accidentally send a message to a function that doesn't make any sense, like input3 to a door, but with a parameter of sf::Vector2f, which expects a float.
But this isn't actually a problem, because when you are creating a map for the game, if you send a door a vector when it has been stated that you should send a float, that is obviously the map creators fault, aka me. When the sf::packet fails to extract the float, it could be logged as an error during runtime, and indicate what function went wrong, and the name of the object that received the packet that was incorrect. So then the mapper could fix it.
First option is simple but pretty crude, and possibly slow.
Second option is... weird, and bad.
There is another way I thought of, but I can't say it's much better than these.
Please just tell me i'm stupid and direct me to a better solution, if there is one.