Ok so I am working on a game and I'm in the process of developing my Player class. Anyways, what I have is a keyboard function that is called in my main function to make a shape move.
1 2 3 4 5 6 7 8 9 10 11 12 13
void myKeyboardFunction(unsignedchar key, int x, int y)
{
switch ( key )
{
case'd':
pointX += 0.2;
break;
case'a':
pointX -= 0.2;
break;
...blah blah blah more controls......
}
}
to call the function I have this in my main function and it works perfectly.
glutKeyboardFunc(myKeyboardFunc);
What I want to do is move myKeyboardFunc into my Player class, and this is what I have so far.
class Player
{
private:
GLfloat pointX;
GLfloat pointY;
public:
void playerControls(unsignedchar key, int x, int y);
} Player1, Player2, Player3, Player4;
void Player::playerControls( unsignedchar key, int x, int y)
{
switch ( key )
{
case'd':
pointX +=0.2;
break;
....more keys.......
}
}
But when I try to call it, trying to copy my previous method,
glutKeyboardFunc(Player1.playerControls);
I get an error
error C3867: 'Player::playerControls': function call missing argument list; use '&Player::playerControls' to create a pointer to member
I've tried messing around with this suggestion but then I get an error saying it can't convert parameters. I would just like to understand why the arguments become a problem when I make the function a member of my class, when the first method I used is so easy. Of course help on how to fix this would be nice.
I know it's probably simple as I'm sort of stepping outside of my boundaries with classes and functions in this project, but I figure I have to learn somehow.
The thing is that member functions have an implicit parameter (this pointer) that is passed to the functions. So, essentially, your member function has the following signature: void playerControls(Player* this, unsignedchar key, int x, int y). So to pass it in form of callback to glutKeyboardFunc, you need to wrap it so that the this pointer would be saved and passed to the member function. However, this is not so easy :)
#include <boost/function.hpp>
#include <boost/bind/bind.hpp>
#include <vector>
typedefint (*TCallback)(int x);
int user(TCallback f, int x)
{
return 2 * f(x);
}
int f1(int x)
{
return x + 1;
}
class T {
public:
int member(int x) { return x + 2; }
};
class Dispatcher {
public:
typedef boost::function<int (int)> TCallable;
staticvoid addListener(TCallable callable) { listeners.push_back(callable); }
staticint call(int f)
{
int x = 0;
for (int i = 0; i < listeners.size(); ++i) {
x += listeners[i](f);
}
return x;
}
private:
static std::vector<TCallable> listeners;
};
std::vector<Dispatcher::TCallable> Dispatcher::listeners;
void main()
{
T t;
user(f1, 3);
Dispatcher::addListener(f1);
Dispatcher::addListener(boost::bind(&T::member, boost::ref(t), _1));
user(&Dispatcher::call, 2);
}
Of course, you will need to adapt the function type to glutKeyboardFunc requirements, but this should give you the general idea. If you're confused with all the boost stuff - refer to its documentation - it's a good exercise anyway.