Game Development Community

Advanced camera + crimsonland-type of control question

by Fyodor -bank- Osokin · in Torque Game Engine · 07/05/2007 (5:25 pm) · 0 replies

I need to make a camera and controls to act as in crimsonland game.
So, by pressing WASD - you control a player as usual, but the direction of player should be set by cursor.
The camera is in OrbitMode.
I've modded the GameTSCtrl, so it actualy catches cursor position and applies a value to moveManager->mYaw - the player rotates while you moving mouse around the screen and everything "seems" to be fine.. except a few "things". While you move around the movement sometimes gets a bit jerky. And, another problem is when you run for a long time without moving a mouse, player getting "lost".

Can someone help me to find a fix for it?? Setting damping = 0; in datablock helps a bit..
To get the feeling - here is a "tempMod" (extract to clean "example" folder).

Here is modified GameTSCtrl.cc (I'm using "object selection" resource additions to get 3d screen pos for mouse):
function GameTSCtrl::processMovement()
{
   GameConnection* conn = GameConnection::getConnectionToServer();
   ShapeBase* ctrl_obj = NULL;
   if (conn != NULL)
      ctrl_obj = conn->getControlObject();
   if (!ctrl_obj)
      return;
   ctrl_obj->disableCollision();

   Point3F mouseScaled = mMouse3DVec * 500.0f; // mMouse3DVec is set by onMouseMove()
   Point3F rangeEnd = mMouse3DPos + mouseScaled; // mMouse3DPos is set by onMouseMove()
   Point3F start = mMouse3DPos;
   Point3F end = rangeEnd;
   SceneObject* picked_obj = 0;
   RayInfo hit_info;
   Point3F hitPos(0,0,0);
   if (gClientContainer.castRay(start, end, mask, &hit_info))
   {
      picked_obj = dynamic_cast<SceneObject*>(hit_info.object);
      hitPos = hit_info.point;
   }
   ctrl_obj->enableCollision();
   if (!(picked_obj))
      return;
   
   // getting current vector
   MatrixF mat;
   ctrl_obj->getEyeTransform(&mat);
   VectorF eyeVec;
   mat.getColumn(1,&eyeVec);
   eyeVec *= 20.0f;
   // eyeVec - is player's current eye vector
   // getting current transform
   Point3F eyeTrans;
   mat.getColumn(3,&eyeTrans);
   // eyeTrans - is player's eye transform
   Point3F curHitPos = eyeVec + eyeTrans;
   Point3F curVec = curHitPos - ctrl_obj->getRenderPosition();
   curVec.normalize();

   hitPos.z = curHitPos.z;
   Point3F wishVec = hitPos - ctrl_obj->getRenderPosition();
   wishVec.normalize();
   // now the wishVec is our desired vector we need to look at, right?

   wishVec.z = 0;
   curVec.z = 0;

   Point3F newVec;
   newVec = mCross(wishVec, curVec);
   //Con::errorf("Angle2: %0.4f %0.4f %0.4f", newVec.x, newVec.y, newVec.z);
   F32 mYaw;
   if (newVec.z < 0)
      mYaw = -0.2f;
   else
      mYaw = 0.2f;
   if (fabs(newVec.z) < 0.5) mYaw *=0.1f;
   if (fabs(newVec.z) < 0.1) mYaw *=0.1f;
   MoveManager::mYaw = mYaw;
}

Or, may be someone knows another way of handling this? I know, I can pass cursor position to server (in moveManager?), and perform everything there... but for me it looks like not a solution.. Am I right?