Game Development Community

Adding adjustable Yaw to the RTS camera

by Martin "Founder" Hoover · in RTS Starter Kit · 11/15/2004 (6:34 pm) · 35 replies

Well, I'm not claiming this is right, only that it works. I have it setup so Alt + mouseWheel will rotate the camera (spin the Z axis)


First in RTSCamera.h, inside class RTSCamera: public ShapeBase:

find :

F32 mPrevAngle;

after it add:

F32 mTargetZAngle;
   F32 mCurrZAngle;
   F32 mPrevZAngle;

then in the public section find:

void setPitchAngle(F32 angle, bool updateNet, bool toInterpolate = true);

and after it paste:

F32 getYawAngle() { return mRadToDeg(mTargetZAngle); }
   void setYawAngle(F32 angle, bool updateNet, bool toInterpolate = true);
   void increaseYawAngle() { setYawAngle(getYawAngle() + mDataBlock->mAngleStep, true); }
   void decreaseYawAngle() { setYawAngle(getYawAngle() - mDataBlock->mAngleStep, true); }

Now I'm not really sure what the RTScameraUpdate setup is all about, but I figured I'd better add it there too, so in class RTSCameraUpdate : public NetEvent find:

F32 mPitchAngle;

and after it add:

bool mIsYawAngle;
   F32  mYawAngle;
   void setYawAngle(F32 angle);

Now on to RTSCamera.cc

Lets start in RTSCamera::RTSCamera() , add the following line in somewhere:

mCurrZAngle = mTargetZAngle = mPrevZAngle = mDegToRad(0.0f);

since theres no need to start out with the Yaw at any other angle except 0, we'll go down to void RTSCamera::setPitchAngle(F32 angle, bool updateNet, bool toInterpolate) :

we need to change:
zRot.set(EulerF(0, 0, 0));

to:
zRot.set(EulerF(0, 0, mCurrZAngle));

now, below that function we can add this new function:
void RTSCamera::setYawAngle(F32 angle, bool updateNet, bool toInterpolate)
{
   RTSCameraData* data = (RTSCameraData*)mDataBlock;
   mTargetZAngle = mDegToRad(angle);
[i]edit...[/i]
   if(mTargetZAngle > M_2PI_F)
   {
      //lets just fake it into thinking it was a smaller angle to begin with :)
      mTargetZAngle -= M_2PI_F;
      mCurrZAngle -= M_2PI_F;
      mPrevZAngle -= M_2PI_F;
   }
   if(mTargetZAngle < -M_2PI_F)
   {
      mTargetZAngle += M_2PI_F;
      mCurrZAngle += M_2PI_F;
      mPrevZAngle += M_2PI_F;
   }
[i]edit...[/i]
   if (!toInterpolate)
   {
      mCurrZAngle = mTargetZAngle;
      MatrixF xRot, zRot;
      xRot.set(EulerF(mCurrAngle, 0, 0));
      zRot.set(EulerF(0, 0, mCurrZAngle));
      MatrixF temp;
      temp.mul(zRot, xRot);
      setTransform(temp);
   }

   if(updateNet)
   {
      // Send a net update
      GameConnection *conn = getControllingClient();
      if(!conn)
      {
         Con::warnf("This camera's not in control of anything!");
         return;
      }

      RTSCameraUpdate *rtsCamUpdate = new RTSCameraUpdate(this, !isClientObject());
[i]Edit...[/i]
       rtsCamUpdate->setYawAngle(angle);
[i]Edit...[/i]
      conn->postNetEvent(rtsCamUpdate);
   }
}

now into void RTSCamera::processTick(const Move* move)


Edit...
A couple lines down from the Parent:: call add this (near the other assignments)

mPrevZAngle = mCurrZAngle;

Edit...

after the code block(not inside of it) that starts with:

if (mTargetAngle != mCurrAngle)

we need to add another:

if (mTargetZAngle != mCurrZAngle)
   {
[i]edit...[/i]
      if (mCurrZAngle < mTargetZAngle)
[i]edit...[/i]
      {
         F32 step = gDegsPerTick;
         if (mCurrZAngle + step > mTargetZAngle)
            mCurrZAngle = mTargetZAngle;
         else
            mCurrZAngle += step;
      }
      else
      {
         F32 step = -gDegsPerTick;
         if (mCurrZAngle + step < mTargetZAngle)
            mCurrZAngle = mTargetZAngle;
         else
            mCurrZAngle += step;

      }
   }

then again change out
zRot.set(EulerF(0, 0, 0));

with
zRot.set(EulerF(0, 0, mPrevZAngle));
Page«First 1 2 Next»
#21
11/17/2004 (4:07 pm)
Okay, I finally figured out how to get it setup so the targetAngle value would get capped, and not mess up when you warped past zero. Turns out you need to do the same adjustments for prevZangle and curZangle. Seems obvious now doesn't it? I added the code into the above post, near the top of setYawAngle();

Also there was a lil typo I didn't catch that resulted in jerky movement when turning a particular yaw direction. it was in processTick() in the new If I added. It was: if(mCurrAngle < mTargetAngle)
and of course should be:

if(mCurrZAngle < mTargetZAngle)

Along with Benoit's tastey lil morsel for moving the camera in the proper direction, I think this pretty well tightens up this camera mod.
#22
11/18/2004 (2:12 pm)
Nice work, guys. I've put this in as well. Works great!
#23
11/18/2004 (2:30 pm)
Thats great news.
#24
03/30/2005 (11:38 am)
Minor fix, which only matters if you use the RTSCamera::setYawAngle(F32 angle, bool updateNet, bool toInterpolate) call. (or the script stub of the same name)

Inside the "if(updateNet)" block, change

rtsCamUpdate->setPitchAngle(angle);
to
rtsCamUpdate->setYawAngle(angle);
#25
03/30/2005 (2:21 pm)
See? That's what happens when you copy and paste a function to use as a template, then don't go and check every line!
Thanks for catching that Andrew, I edited the post to include it. :)
#26
09/26/2008 (12:31 pm)
Well i am giving this a try to see if I can get it working in the 5.21 version of torque. Should work without too much trouble. I hope. Is thier a more recent resource that does this sort of thing

EDIT: Oh seems somewhere along the line they added some code for Yaw Control. Last i played with the RTS starter kit it had just come out and since it did not demonstrate any form of Yaw control in the example demo of the old or new one i just assumed it still did not have any Yaw functionality.
#27
09/26/2008 (4:25 pm)
Hi Wesley. Indeed, since the first release, some things have changed a bit, be sure to play with the kit for a while before modifying any code :)
Oh, and take a look at this, for a list of some issues covered on the last version as well.
#28
09/27/2008 (7:41 am)
I have run into a bit of a snag when trying to copy script over from the RTS starter kit to my project. As near as i can figure i have all the line pertaining to the RTS camera including the key map bindings and function for it but i cannot for the life of me get the camera to Yaw. It pitchs just fine in fact the decreaseYawangle and increaseYawangle functions even seem to be changing the pitch. Is thier some function or variable that needs to be enabled for the Yaw to function?

Looking through the RTS starter kit code i so far cannot find anything and i had a peek at the .cc file earlier and do not rember seeing anything like that.

Basicly the weird thing is that after i have imported the script my rts camera seems to pitch when i call
the increasepitchangle(), decreasepitchangle() and increaseyawangle(), decreaseyawangle


any help would be great i have been banging my head in cicles over this. even tried swaping the exe's with the RTS starter kit to see if it makes any difference and so far no. The RTS kit's camera works just fine though so thier has to be some difference i am missing here.

Key bindings

function updateOrbitDistance(%val)
{
if( %val > 0 )
$RTSCamera.decreaseOrbitDistance();
else if( %val < 0 )
$RTSCamera.increaseOrbitDistance();
}

function updateViewPitch(%val)
{
echo("Pitch = " @ %Val);

if( %val < 0 )
{
$RTSCamera.decreasePitchAngle();
}
else if( %val > 0 )
{
$RTSCamera.increasePitchAngle();
}

}

function updateViewYaw(%val)
{
echo("Yaw = " @ %Val);

echo("val = " @ %Val);
if( %val < 0 )
{
echo("decrease");
$RTSCamera.decreaseYawAngle();
}
else if( %val > 0 )
{
echo("increase");
$RTSCamera.increaseYawAngle();
}

}

RtsMap.Bind(keyboard, w, GoAhead);
RtsMap.Bind(keyboard, a, GoLeft);
RtsMap.Bind(keyboard, d, GoRight);
RtsMap.Bind(keyboard, s, BackUp);
RtsMap.bind( mouse, "alt zaxis", updateViewYaw);
RtsMap.bind( mouse, "ctrl zaxis", updateViewPitch);

$Map = RtsMap.getID();
//Echo("Map = " @ $Map);
RtsMap.push();

Datablock:

datablock RTSCameraData(RTSObserverData)
{
mode = "Observer";
movementSpeed = 40.0;
pitchAngle = 60.0;
maxHeight = 50.0;
minHeight = 5.0;
zoomSpeed = 7;
orbitStep = 8;
maxAngle = 90;
minAngle = 20;
};


contents of GameConnection::onClientEnterGame

exec("./misc/camera.cs");
$Client = %this;
// Every client get's a camera object.
%this.advCamera = new AdvancedCamera() {
dataBlock = AdvCameraData;
};
%this.rtsCam = new RTSCamera()
{
dataBlock = RTSObserverData;
};
%this.camera = new Camera() {
dataBlock = Observer;
};
$RtsCamera = %this.rtscam;
$CameraID = %this.camera;
$ADVCamera = %this.advCamera;
MissionCleanup.add( %this.camera );
MissionCleanup.add(%this.advCamera);
MissionCleanup.add(%this.rtsCam);
%this.advcamera.scopeToClient(%this);
%this.camera.scopeToClient(%this);
%this.rtsCam.scopeToClient(%this);
// Create a player object.
%spawnPoint = pickSpawnPoint();
//%this.createPlayer(%spawnPoint); //commented out because we are now starting with the RTS camera
%this.setControlObject(%this.rtsCam);
exec("./BattleSystem/StatInput.cs");//Starts the battlesystem code
exec("./KeyMap.cs");


I am probably violating some structure here and thier but it is test code to try things out get everything working.(dang forums ripped out my spacing)
#29
09/27/2008 (1:57 pm)
UpdateViewYaw() seems to be just fine, do you actually see the "increase" and "decrease" output in the console when trying to Yaw the camera? If that so, you will have to debug the C++ code, as increaseYawAngle and decreaseYawAngle are console methods, there isnt really much more to do in script if those functions are called properly.
#30
09/28/2008 (2:07 pm)
Yeah i am getting the increase and decrease displayed correctly when i try to yaw. I have considered it being a c++ bug but it is quite frustrating to try and draw a clear difference between the RTS starter kit's code and the code i have written.

Of course that is why it is so frustrating. I am really not looking forward to trying to debug this. If you are sure i have it setup right i guess i should start by seeing if anyone else has run across this problem and if thier is already a solution posted.

At the least maybe i can figure somthing out with the get and set functions for yaw. Pretty hackish but hey what works, works.

Thx for the help.

EDIT:
does not seem to be any threads on this problem.
Noticing that the getyaw function is returning changes in yaw even though it changes pitch. It is not changing the value returned by the get pitch value. The get Pitch is only returning changes in pitch when i try and pitch.

That is good i guess because it means the functions are not intermixing it is just pitching when it should be yawing.
#31
09/28/2008 (5:30 pm)
Just had a thought could the Connection being used have anything to do with my problem here. When i went to import the RTS code i just changed my ServerConnection to a RTSConnection was all i did. Maybe it is how that is connecting. Though it is a single player game so should not have a problem.
#32
09/29/2008 (9:03 am)
A couple of other things you could try:

In game, pull down the console and type
$RTSCamera.increaseYawAngle();
a few times - what happens? If it yaws, then you've got something crossed up in your scripts. If it doesn't, then you've changed something in the engine that's messing with the rtsCamera.

I notice that you're also using the advancedcamera resource. It's quite possible that this is affecting something somewhere.

Also, try adding the RTSCamera to a fresh TGE install, it works fine for me if I do it.
#33
09/29/2008 (11:56 am)
Well i went digging around in the code of the RTSCamera::setYawAngle and RTSCamera::setPitchAngle
Noticed that for the netupdate for both of them they are both doing this

if(updateNet)
{
// Send a net update
GameConnection *conn = getControllingClient();
if(!conn)
{
Con::warnf("This camera's not in control of anything!");
return;
}

RTSCameraUpdate *rtsCamUpdate = new RTSCameraUpdate(this, !isClientObject());
rtsCamUpdate->setPitchAngle(angle);

conn->postNetEvent(rtsCamUpdate);
}

That would probably be correct for the set pitch function but should'nt the setYawfunction have
rtsCamUpdate->setYawAngle(angle);
instead of of setpitch.

It almost seems obvious to me but i have not played around with the inner workings of the engine that much. So i am not really sure. Also it in no way explains why i could take the exe from the RTSkit example code. That works 100% perfectly with the example code and get the exact same problem with my own project.

The problem i am seeing is just somthing that seems like it should not work at all for Yawing without exception.
#34
09/29/2008 (1:43 pm)
Setting the pitch for the camera update when the yaw has changed certainly looks like another bug.

However, this shouldn't result in the effects you're describing.

The RTScamera is controlled client-side. The RTSCameraUpdates are sent from the client to the server in order for the server to be able to determine what is in scope for the client.
#35
09/29/2008 (4:07 pm)
Well seems that line of code i found is part of the code for the RTS Starter Kit so it is not somthing i messed around with. Which makes me wonder if it was intentional because i doubt it could have gone this far without being noticed and being reported i would think well i guess i could try and see what my code does once i change it.

Even still i really do not understand why it is what it is.

EDIT:
After changing it and recompiling it now works perfectly.
@Allard No idea why as you say it should not, but then again i am making a single player game which has a nonstandard file tree the difference between my client and server are somewhat hard to define. In that case i suppose in hindsight it would not be completly unexpected.

I will make a post in the bug section in case someone else runs into this problem even if it is a simple bug and probably rare to run into if you do things the way your supposed to.

Thx for all your help on this. I am not all that confident really with messing with the engines code. I have heard it is quite easy to mess up if you do not know what your doing.

Even got the camera to schroll properly with the mouse. That was somthing i found i could not get to work with the RTS starter kit.
Though it is kinda clunky working. I am doing a right click and hold to schroll it works better than i would expect but it could be alot smoother.
Page«First 1 2 Next»