Game Development Community

dev|Pro Game Development Curriculum

Cycle between advanced camera modes and change controls for each mode

by Philip Engdahl · 01/18/2006 (5:10 pm) · 9 comments

Description

While Thomas "Man of Ice" Lund's Advanced Camera resource adds many new modes to the camera, it doesn't include an easy way to cycle through and experiment with all the modes. Also, some of the modes require different key bindings than others in order to work properly. In particular, the orbit camera ideally should have the mouse bound to moving the camera, while most of the other modes work better with the mouse adjusting the direction the character is facing.

This resource provides an easy way to cycle between the various modes of the advanced camera and first-person mode.

Change Log
December 20, 2005
Initial release
January 19, 2006
Added editor bindings so that the editor can still rotate the camera with the mouse.
Added switchToFirstPerson() function.
July 9, 2006
Fixed some typos in changes to default.bind.cs - some of the MoveMaps were incorrectly labelled as MoveMans.

How to add:
This resource requires that you have already incorporated the Advanced Camera into your project.

Engine Changes:
in advancedCamera.cc, add the following block of code after the console method for clearTargetObject:

ConsoleMethod( AdvancedCamera, getCameraMode, S32, 2, 2, "()"
              "Gets the mode of the camera.")
{
   AdvancedCamera *camObj = (AdvancedCamera *) object;
	return camObj? camObj->getCameraMode(): -1;
}

in advancedCamera.h, add the following line:

/// Method to switch the camera mode
	void setCameraMode(int mode);
	[b]// add this[/b]
	[b]int getCameraMode() { return mMode; }[/b]

Script Changes:
I made these changes to the "demo" provided by GG in torque 1.4. They should work for the starter.fps or the tutorial.base as well, with minor changes. In particular, the coordinates of the advCameraTarget should be changed to suit the mission.

in GameConnection::onClientEnterGame, I have the following:

// Create a new camera object.
   %this.camera = new Camera() {
      dataBlock = Observer;
   };
   MissionCleanup.add( %this.camera );
   %this.camera.scopeToClient(%this);
[b]
   // Advanced Camera
   // create advanced camera
   %this.advCamera = new AdvancedCamera() {
      dataBlock = AdvCameraData;
   };
   MissionCleanup.add(%this.advCamera);
   %this.advCamera.scopeToClient(%this);
   
   // set the global for advCamera so we can access it elsewhere
   $advCamera = %this.advCamera;

   // Create a target object for the Camera
   // this can be any object in the scene - just creating a spawn sphere here because it's easy
   %advCameraTarget = new SpawnSphere() {
      position = "335.0 120.0 174.0";
      rotation = "0 0 1 235.668";
      scale = "1 1 1";
      dataBlock = "SpawnSphereMarker";
      radius = "1";
      sphereWeight = "100";
      indoorWeight = "100";
      outdoorWeight = "100";
   };
   MissionCleanup.add(%advCameraTarget);
   %this.advCameraTarget = %advCameraTarget;
[/b]
   // Spawn the player
   // it's important to do this after creating the target object for the camera
   %this.score = 0;
   %this.spawnPlayer();

Here's GameConnection::onClientLeaveGame

if (isObject(%this.camera))
      %this.camera.delete();
   if (isObject(%this.player))
      %this.player.delete();
[b]
   // Advanced Camera
   if (isObject(%this.advCamera))
      %this.advCamera.delete();    
   if (isObject(%this.advCameraTarget))
      %this.advCameraTarget.delete();
[/b]

Add this to the bottom of GameConnection::createPlayer

// Advanced Camera
   // Set the player object
   %this.advCamera.setPlayerObject(%player);
   
   // target must be set for Third Person Target Mode
   %this.advCamera.setTargetObject(%this.advCameraTarget);
   
   // the track and static cameras are placed using this option
   %this.advCamera.setCameraPosition( "335.0 120.0 195.0" );

   %this.advCamera.setFollowTerrainMode(false);
   %this.advCamera.setVerticalFreedomMode(false);
   %this.setCameraObject(%this.advCamera);
   
   // Advanced Camera
   // Default camera mode
   %this.advCamera.setGodViewMode();

   // set to third person view
   $firstPerson = false;
   ServerConnection.setFirstPerson(false);

The following changes go in fpsGui.cs, playGui.cs, etc. depending on which is your active gui.

add this to the end of FpsGui::onWake, after the moveMap.push() line

if($firstperson) {
      firstpersonMoveMap.push();
   }
   else
   {
      %cameraMode = $advCamera.getCameraMode();
      switch(%cameraMode) {
         case 0: // TrackMode
            trackMoveMap.push();
         case 1: // GodViewMode
            godviewMoveMap.push();
         case 2: // ThirdPersonMode
            thirdpersonMoveMap.push();
         case 3: // ThirdPersonTargetMode
            thirdpersontargetMoveMap.push();
         case 4: // OrbitMode
            orbitMoveMap.push();
         case 5: // StaticMode
            staticMoveMap.push();
      }
   }

add this to the end of FpsGui::onSleep before the moveMap.pop() line

// Pop the keymaps
   if($firstperson) {
      firstpersonMoveMap.pop();
   }
   else
   {
      %cameraMode = $advCamera.getCameraMode();
      switch(%cameraMode) {
         case 0: // TrackMode
            trackMoveMap.pop();
         case 1: // GodViewMode
            godviewMoveMap.pop();
         case 2: // ThirdPersonMode
            thirdpersonMoveMap.pop();
         case 3: // ThirdPersonTargetMode
            thirdpersontargetMoveMap.pop();
         case 4: // OrbitMode
            orbitMoveMap.pop();
         case 5: // StaticMode
            staticMoveMap.pop();
      }
   }

Apply all of the following changes to default.bind.cs:

add the following at the beginning of the file after the line "new ActionMap(moveMap);"

if ( isObject( firstpersonMoveMap ) )
   firstpersonMoveMap.delete();
new ActionMap(firstpersonMoveMap);

if ( isObject( orbitMoveMap ) )
   orbitMoveMap.delete();
new ActionMap(orbitMoveMap);

if ( isObject( godviewMoveMap ) )
   godviewMoveMap.delete();
new ActionMap(godviewMoveMap);

if ( isObject( thirdpersonMoveMap ) )
   thirdpersonMoveMap.delete();
new ActionMap(thirdpersonMoveMap);

if ( isObject( thirdpersontargetMoveMap ) )
   thirdpersontargetMoveMap.delete();
new ActionMap(thirdpersontargetMoveMap);

if ( isObject( trackMoveMap ) )
   trackMoveMap.delete();
new ActionMap(trackMoveMap);

if ( isObject( staticMoveMap ) )
   staticMoveMap.delete();
new ActionMap(staticMoveMap);

add this code after the zoomCamera function:

function cycleCamera(%val)
{
   if (%val)
   {
      // 1stperson -> thirdperson -> thirpersontarget -> orbit -> godview -> track -> static
      if($firstPerson)
      {
         $firstPerson = false;
         ServerConnection.setFirstPerson($firstPerson);

         $advCamera.setThirdPersonMode();
         firstpersonMoveMap.pop();
         thirdpersonMoveMap.push();
      }
      else
      {
         %cameraMode = $advCamera.getCameraMode();
         switch(%cameraMode) {
            case 0: // TrackMode
               $advCamera.setStaticMode();
               trackMoveMap.pop();
               staticMoveMap.push();
            case 1: // GodViewMode
               $advCamera.setTrackMode();
               godviewMoveMap.pop();
               trackMoveMap.push();
            case 2: // ThirdPersonMode
               $advCamera.setThirdPersonTargetMode();
               thirdpersonMoveMap.pop();
               thirdpersontargetMoveMap.push();
            case 3: // ThirdPersonTargetMode
               $advCamera.setOrbitMode();
               thirdpersontargetMoveMap.pop();
               orbitMoveMap.push();               
            case 4: // OrbitMode
               $advCamera.setGodViewMode();
               orbitMoveMap.pop();
               godviewMoveMap.push();
            case 5: // StaticMode
               $firstPerson = true;
               ServerConnection.setFirstPerson($firstPerson);
               staticMoveMap.pop();
               firstpersonMoveMap.push();
         }
      }
   }
}
moveMap.bind(keyboard, tab, cycleCamera );

firstpersonMoveMap.bind( mouse, xaxis, yaw );
firstpersonMoveMap.bind( mouse, yaxis, pitch );
firstpersonMoveMap.bind( mouse, button0, mouseFire );
//firstpersonMoveMap.bind( mouse, button1, altTrigger );

orbitMoveMap.bind( mouse, xaxis, rotateCameraHorizontal);
orbitMoveMap.bind( mouse, yaxis, rotateCameraVertical );
orbitMoveMap.bind( mouse, zaxis, zoomCamera );
orbitMoveMap.bind( mouse, button0, mouseFire );
//orbitMoveMap.bind( mouse, button1, altTrigger );

godviewMoveMap.bind( mouse, xaxis, yaw );
godviewMoveMap.bind( mouse, yaxis, pitch );
godviewMoveMap.bind( mouse, button0, mouseFire );
//godviewMoveMap.bind( mouse, button1, altTrigger );

thirdpersonMoveMap.bind( mouse, xaxis, yaw );
thirdpersonMoveMap.bind( mouse, yaxis, pitch );
thirdpersonMoveMap.bind( mouse, button0, mouseFire );
//thirdpersonMoveMap.bind( mouse, button1, altTrigger );

thirdpersontargetMoveMap.bind( mouse, xaxis, yaw );
thirdpersontargetMoveMap.bind( mouse, yaxis, pitch );
thirdpersontargetMoveMap.bind( mouse, button0, mouseFire );
//thirdpersontargetMoveMap.bind( mouse, button1, altTrigger );

trackMoveMap.bind( mouse, xaxis, yaw );
trackMoveMap.bind( mouse, yaxis, pitch );
trackMoveMap.bind( mouse, button0, mouseFire );
//trackMoveMap.bind( mouse, button1, altTrigger );

staticMoveMap.bind( mouse, xaxis, yaw );
staticMoveMap.bind( mouse, yaxis, pitch );
staticMoveMap.bind( mouse, button0, mouseFire );
//staticMoveMap.bind( mouse, button1, altTrigger );

Comment out or remove any of the following lines that are in the file:

moveMap.bind( mouse, xaxis, yaw );
moveMap.bind( mouse, yaxis, pitch );
moveMap.bind( mouse, button0, mouseFire );

moveMap.bind( mouse, xaxis, rotateCameraHorizontal);
moveMap.bind( mouse, yaxis, rotateCameraVertical );
moveMap.bind( mouse, zaxis, zoomCamera );

moveMap.bind(keyboard, tab, toggleFirstPerson );

add this function before the toggleCamera function:

function switchToFirstPerson()
{
   // advanced camera doesn't support togglecamera, so switch to 1st person first
   $firstperson = true;
   ServerConnection.setFirstPerson(true);
   
   // change to the first person action map from whatever mode we were in
   %cameraMode = $advCamera.getCameraMode();
   switch(%cameraMode) {
      case 0: // TrackMode
         trackMoveMap.pop();
      case 1: // GodViewMode
         godviewMoveMap.pop();
      case 2: // ThirdPersonMode
         thirdpersonMoveMap.pop();
      case 3: // ThirdPersonTargetMode
         thirdpersontargetMoveMap.pop();
      case 4: // OrbitMode
         orbitMoveMap.pop();
      case 5: // StaticMode
         staticMoveMap.pop();
   }
   firstpersonMoveMap.push();
}

modify toggleCamera to look like this:

function toggleCamera(%val)
{
   if (%val)
   {
      if($firstperson) {
         commandToServer('ToggleCamera');
      }
      else
      {
         [b]switchToFirstPerson();[/b]
                  
         commandToServer('ToggleCamera');
      }
   }
}

in creator/editor/editor.cs, add the following code in the ToggleEditor function:
...
      else
      {
         [b]// fix for advanced camera
         switchToFirstPerson();[/b]
         
         if (!isObject(Editor))
         {
            Editor::create();
            MissionCleanup.add(Editor);
         }
...

in creator/editor/editor.bind.cs, add the following at the bottom of the file:

// Needed because of new bindings for the mouse elsewhere
EditorMap.bind( mouse, xaxis, yaw );
EditorMap.bind( mouse, yaxis, pitch );
WorldEditorMap.bind( mouse, xaxis, yaw );
WorldEditorMap.bind( mouse, yaxis, pitch );
TerrainEditorMap.bind( mouse, xaxis, yaw );
TerrainEditorMap.bind( mouse, yaxis, pitch );
AIEditorMap.bind( mouse, xaxis, yaw );
AIEditorMap.bind( mouse, yaxis, pitch );

About the author

Recent Blogs


#1
01/18/2006 (6:29 pm)
Ive implemented Thomas's code change, and cant wait to try this out.

Thanks

-Surge
#2
03/07/2006 (2:07 pm)
Works like a charm...

Thanks
#3
04/16/2006 (6:51 pm)
I implemented your changes and have gone over it several times but i only seem to get a orbit view mode that doesnt move with the mouse. i tried forcing the case statment (in client/scripts/defaul.bind.cs for the fps tutorial) to a particular camera settings eg switch (4) but that doesnt seem to change the camera...anyone have suggestions on how to fix this?
Thanks,

Dan
#4
05/05/2006 (7:10 am)
Hey this is a great resource but remember his changes assume that you are hosting your own server and are singleplayer only
For this to work remotely you CANNOT set the global and you cannot use the serverConnection bits
Instead replace them with %this. and make sure to save off the needed refferences on the client connection object itself.

Otherwise you are going to get some serious wierdness
#5
06/17/2006 (6:52 am)
Everything compiled fine and I dont get any errors, however I cannot cycle through the cameras. I am pressing tab but it just cycles through the old first and third person cameras. The console report does not show me anthing that points to the problem...

Can anyone help me out here.

Regards
#6
07/09/2006 (9:56 am)
Louden, you probably still have a bind to ToggleFirstPerson on the tab key. Also you have to delete any custom binding files you have so that they get re-created from default.bind.cs.
#7
11/21/2006 (8:41 pm)
I had the same problem as Louden and for the mentioned reason. but after I deleted the config.cs file, it recreated it with the same bindings as before. I manually changed the tab key to bind as cycleCamera, and now the tab key switches to 3rd person but then gets stucks there. After it switches to 3rd person, the tab key doesn't switch anything anymore, it just stays in 3rd person.
What gives?
#8
01/07/2007 (2:10 pm)
Cheers thanks for the code - makes editing much easier when using the advanced camera resource.

--Amr
#9
09/26/2007 (6:44 pm)
I modify TGEA demo's scripts and want to handle mouse event when the application started.I hope that use mouse to control the camera movement and rotation(etc. model viewer).I think use setOrbitMode() function.

if mouseLeftButtonDown and drag it,the camera has been moved;
if mouseRightButtonDown and darg it,the camera has been rotated around a player.

But I have a question about bind mouse event.I changed default.bind.cs in demo\client\scripts directory.In this file,I add these codes:

moveMap.bind( mouse, button0, mouseMove );
moveMap.bind( mouse, button1, mouseRotate );

and

$MouseMove = false;
$MouseRotate = false;

function mouseMove(%val)
{
if(%val >0)
{
$MouseMove = true;
echo("MouseMove = true");
}
else
{
$MouseMove = false;
echo("MouseMove = false");
}
}

function mouseRotate(%val)
{
if(%val >0)
{
$MouseRotate = true;
echo("MouseRotate = true");
}
else
{
$MouseRotate = false;
echo("MouseRotate = false");
}
}

But it does't work.What's wrong these codes?And How tontrol camera by mouse like that model viewer in TGEA?

Thanks!