As my first post, i will show the code i use to dynamically control a character(not kinematic control). Currently, it's use the mouse to move the orientation(just on the X axis) and the keyboard to move on Y and X axis. No jump action for now.
I basically use a capsule collision to represent the character. I use Ogre 3D as my render engine, so i'll try to be the more general as possible. This code is based on some part of the Character Control Demo.
Units are: (meter * 10) for size and (kilogram * 10) for weight (i hope i'm not to confusing, i'm not really good with english
/*...*/ = i removed useless code. Like Ogre or project related thing
character.h :
Code: Select all
class Character
{
public:
Character(/*...*/btDiscreteDynamicsWorld * _mWorld, btVector3 _pos);
void move(bool front, bool back, bool left, bool right); // each boolean indicate if the character move to this direction
void rotation(int axisX); // axisX = the number of pixel the mouse moved since last frame
private:
btDiscreteDynamicsWorld * mWorld;
btRigidBody * body;
btVector3 frontSpeed, sideSpeed;
btScalar angleY;
btScalar sensibility; // from 1 to 200 as %.
// Really often used variables
btTransform xform;
btVector3 walkDirection;
};Code: Select all
Character::Character(/*...*/btDiscreteDynamicsWorld * _mWorld, btVector3 _pos)
: /*...*/mWorld(_mWorld), frontSpeed(btVector3(0.0, 0.0, 5.0)), sideSpeed(btVector3(3.0, 0.0, 0.0)), angleY(0.0), sensibility(60.0)
{
xform.setIdentity();
xform.setOrigin(_pos);
// this function creates and add a btRigidBody to the world. Just check the demo for the code of this function.
body = makeRigidBody(400.0f, transform, new btCapsuleShape(btScalar(2.0), btScalar(8.482)), mWorld);
body->setSleepingThresholds(0.0, 0.0);
body->setAngularFactor(0.0);
}
void Joueur::move(bool front, bool back, bool left, bool right)
{
body->getMotionState()->getWorldTransform(xform);
walkDirection = btVector3(0.0, 0.0, 0.0);
if (left)
walkDirection -= sideSpeed;
if (right)
walkDirection += sideSpeed;
if (front)
walkDirection -= frontSpeed;
if (back)
walkDirection += frontSpeed;
if (!front && !back&& !left&& !right)
body->setLinearVelocity(btVector3(0.0, 0.0, 0.0));
else
body->setLinearVelocity(QmV3(walkDirection, xform.getRotation())); // QmV3 will be displayed in the next code section.
body->getMotionState()->setWorldTransform(xform);
body->setCenterOfMassTransform(xform);
}
void Joueur::rotation(int axisX)
{
if (axisX != 0)
{
body->getMotionState()->getWorldTransform(xform);
// Here is a part that i can't do without Ogre.
// Basically, it transforms the "int" to Ogre::Degree. Then, it transforms again to Ogre::Radian(so, in radian) and it takes the value to float. Finally, it multiplies it by the %.
angleY -= Ogre::Radian(Ogre::Degree(axeX)).valueRadians() * sensibilite / 100;
xform.setRotation(btQuaternion(btVector3(0.0, 1.0, 0.0), angleY));
body->getMotionState()->setWorldTransform(xform);
}
}Code: Select all
static btVector3 QmV3(const btVector3 & v, const btQuaternion & q)
{
btVector3 qv(q.x(), q.y(), q.z());
btVector3 uv = qv.cross(v);
btVector3 uuv = qv.cross(uv);
uv *= (2.0 * q.w());
uuv *= 2.0;
return v + uv + uuv;
}Code: Select all
// This part of code must be modified to correctly work for you according with your input system(i use OIS).
//"me" is a Character
me->rotation(mMouse->getMouseState().X.rel);
me->deplacement(mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W), mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S), mKeyboard->isKeyDown(OIS::KC_LEFT) || mKeyboard->isKeyDown(OIS::KC_A), mKeyboard->isKeyDown(OIS::KC_RIGHT) || mKeyboard->isKeyDown(OIS::KC_D));