How to : Character move at constant speed ?

wilsonwing

11-08-2008 04:58:01

Hi, I've search the form and found about 2 or 3 methods to do it.
The problem I am facing is the ground( I use simple_terrain.mesh ).
It is somewhere high and somewhere low.
When my character climb to the high position, its speed slows down a lot.

I found a method said that I should adjust my force when going upward.
For example, when climbing up( forward )I have to do this:

Ogre::Vector3 force(0,0,10);
force* degree(or orient) of the ground;
addLocalForce(force);


I tried to get orientation of the ground by cast ray.
But I can only get the rotation of the simple_terrain.mesh .
What I need is the orientation of the small piece
(the triangle when press F3)



How do I impliment this?
Or is there easier way to do it :?

majc

23-08-2008 19:52:15

Instead of addLocalForce to move your character try to use setVelocity.

pra

24-08-2008 00:23:28

no, setVelocity for character movement is evil.
It will make you be able to climb any wall what has less than 90° to the ground.
Somewhere in one of the many character movement threads there is a formula to calculate the force to reach a certain velocity. you should use it and then check if this force is not too big, setting it to a defined max value if it is.

majc

25-08-2008 02:33:07

Yes you right about that i will have to find that formula too.

pra

25-08-2008 13:29:12

I looked it up in my code:
movAccel = (-currentVelocity + movDirAbs*maxSpeed) / mWorld->getTimeStep();
movDirAbs is a normalized vector that points in the desired movement direction, currentVelocity is mBody->getVelocity(), maxSpeed is the velocity you want your char to move with.
the result is an acceleration, means you have to multiply it with the mass to get the force.

wilsonwing

26-08-2008 04:55:44

I looked it up in my code:
movAccel = (-currentVelocity + movDirAbs*maxSpeed) / mWorld->getTimeStep();
movDirAbs is a normalized vector that points in the desired movement direction, currentVelocity is mBody->getVelocity(), maxSpeed is the velocity you want your char to move with.
the result is an acceleration, means you have to multiply it with the mass to get the force.

Thanks for this.
I will try it and reply if I still has question.

micken

26-08-2008 17:50:07

I believe what you might be looking for is the normal vector for the face your character is moving on. In order to get this you may need to access the face attributes in your contactcallback. I am unable to retrieve this information for you right now but definately take a look at the faceattribute in your contactcallback.

Another way to temporarily solve this kind of problem is to use an oval or upside-down pyramid for your character's collision so that only a small point is actually in contact with the ground when you add the force to minimize the amount of resistance it will encounter.

wilsonwing

09-09-2008 03:24:24

Will, it finally works.
But I done it different way.
Because I can't make this movAccel = (-currentVelocity + movDirAbs*maxSpeed) / mWorld->getTimeStep(); work.
I use addLocalForce, and can't make it work to covert to addGlobalForce.

This is the way I make it move at constant speed:
I setVelocity to Vector3(0,0,0) each time before I add force to character.
And it moves at constant speed.....

-------------------------------------------------------------------------------------
now I meet a new problem.
My character rotate when it's climbing up or down.
I 've already set the friction between character and floor to zero.
And I am using up vector.
m_pUpVector= new OgreNewt::BasicJoints::UpVector( world, m_pNewtonBody, Ogre::Vector3(Ogre::Vector3::UNIT_Y) );

This is the way I rotate my character:

void Character::forceCallback(OgreNewt::Body* m_pNewtonBody)
m_TorqueForce *= * m_Mass;
m_TorqueForce -= m_pNewtonBody->getOmega().y;
m_pNewtonBody->setOmega(Ogre::Vector3(0,0,0));
m_pNewtonBody->addTorque( m_TorqueForce );


When I move my mouse, code will go to this section:
(OgreNewtonFrameListener)
if(e.state.X.rel>2)
{
mPlayer->setRotation(RotateLeft, e.state.X.rel );
}
else if(e.state.X.rel<-2)
{
mPlayer->setRotation(RotateRight, -e.state.X.rel );
}else
{
if( mPlayer->getCharacterRotationState() != NoRotate )
mPlayer->setStopRotation();
}



void Character::setRotation(CharacterRotationState
vCharacterRotationState, Ogre::Real RotateRate)
{

m_CharacterRotationState = vCharacterRotationState;
switch(m_CharacterRotationState)
{
case RotateLeft:
m_TorqueForce = Ogre::Vector3( 0, -CharacterRotateSpeed * RotateRate , 0 );
break;
case RotateRight:
m_TorqueForce = Ogre::Vector3( 0, CharacterRotateSpeed * RotateRate , 0 );
break;
}

}



I've searched the forum and tried some ways to turn my character back to desire direction, but none of them works.
Any help my be appriciate. ^^