Tactics-Action Hybrid Game Tutorial Part3: Camera System
by Steve Acaster · 05/08/2011 (7:11 am) · 6 comments
Back to Part Two: Level Creation
The third person camera system that we will be using in this tutorial is derived from the method used in the RTSprototype in the official documentation, so if you have completed that, this should be fairly familiar.
In your favourite "IDE/Torsion/text editor", open the file scripts/server/commands.cs and add the script for our new camera system.
This will tell the camera to orbit the player's selected character. Remember, the person playing is "the client" and the object which they control is the "player". eg: %client.player.
From now on in this tutorial series, when dealing with script or server actions, the person playing the game will be refered to as "the client" and the controlled character will be called "the player or playerObject".
In the above script snippet, we also give the client's camera (you need a camera in scene or you can't view it!) a new variable called "camDist", which should always be the distance that the camera is from the player. Now we can use that variable to make a function to alter the distance so we can zoom in and out. This will help with both movement and targeting later.
Adding this script directly beneath the previous in "commands.cs" you will notice that we intend to increment the zoom by 0.5 units (less jerky than 1 full unit) and that we carry over the current rotation of the camera when we reset the distance so it doesn't snap back to mDegToRad(20) @ " 0 0" in a horrible, sharp manner.
Now we have the functions, we need to be able to use them with input.
Open up "scripts/client/default.bind.cs" and we shall customize our input. We are only going to use the mouse, so that's "button0, button1 and the zAxis" (zAxis I call "the spinny thing", though apparently it's proper name is the "scroll wheel").
We now have input to send the zoom adjustments we make with the "scroll wheel" to change the camera's distance to the playerObject. Now let's make a toggle for showing/hiding the cursor. With the cursor "off" we can rotate the camera around the playerObject.
Whilst I did just call this a "toggle" in practise it will really be used for enabling the cursor only, giving the client direct input into the "playGui" (that's the GUI which fills the screen in-game and shows what is happening through the camera) and ends the rotation of the camera. With the client having input on to "playGui" they will be able to click locations in-game for the playerObject to move to and shoot at.
To get back to being able to "toggle" the cursor off again and thus rotate the camera around the playerObject again, we need another "toggle" - this time on the PlayGui.
Open up the file game/art/gui/playGui.gui. At the bottom, under //--- OBJECT WRITE END --- add the following.
You don't need to add a keybind for this.
Since we have given the "scroll wheel/zAxis" a new input function, we need to remove the old one. In stock T3D, zAxis supported "WeaponCycling" which we no longer require. Back in default.bind.cs find the keybind and comment it out, leave the actual function for now - if you comment that out as well, you'll likely have to go and comment out every reference to it spread over a variety of scripts - so let's not bother right now.
And now do the same for both of the mouse button controls (fire, altFire) as we won't be using them.
To make sure that the system updates our new input controls we need to edit scripts/client/config.cs. This file is autocreated by the game if it doesn't exist, so rather than actually editing we can delete it and force the game to create a new, up-to-date version for us. Run (double-click) on deletePrefs.bat in the root directory of your Project. eg: Torque3D version whatever/My Projects/Torque_Tactics_Tutorial.
Now let's test that camera.
In scripts/server/gamecore.cs find the function GameCore::PreparePlayer and make these changes.
The first change takes away the camera control from the playerObject, the second starts our custom camera function from commands.cs.
There is one last issue. We are not directly controlling he player, we are controlling them by "proxy". So we need to use an AiPlayer. Open scripts/server/gameDm.cs and change the following:
We have to do it in gameDM.cs and not gameCore.cs because the creation of a server defaults to "Deathmatch" as a gametype.
Load up the game and the level. You should now be presented with the playerObject standing in front of you. As you move the mouse you will rotate the camera around the playerObject. When you move the "scroll wheel" you will zoom in and out. When you press the right mouse button you will lose camera control and gain a cursor on screen. Press the right mouse button again and you lose the cursor and regain control of the camera.
Just to check select the playerObject in the World Editor (F11) and you should see that he is an AiPlayer with the datablock "DemoPlayer" rather than a regular Player class object.
That's the new camera system taken care of, next we need the player to be able to move and shoot.
Part Four: Player Actions
Part3: Camera System
The third person camera system that we will be using in this tutorial is derived from the method used in the RTSprototype in the official documentation, so if you have completed that, this should be fairly familiar.
In your favourite "IDE/Torsion/text editor", open the file scripts/server/commands.cs and add the script for our new camera system.
function serverCmdtacticsCam(%client)
{
%client.camera.setOrbitObject(%client.player, mDegToRad(20) @ " 0 0", 0, 1.5, 1.5);
%client.camera.camDist = 1.5;
}This will tell the camera to orbit the player's selected character. Remember, the person playing is "the client" and the object which they control is the "player". eg: %client.player.
From now on in this tutorial series, when dealing with script or server actions, the person playing the game will be refered to as "the client" and the controlled character will be called "the player or playerObject".
In the above script snippet, we also give the client's camera (you need a camera in scene or you can't view it!) a new variable called "camDist", which should always be the distance that the camera is from the player. Now we can use that variable to make a function to alter the distance so we can zoom in and out. This will help with both movement and targeting later.
function serverCmdadjustCamera(%client, %adjustment)
{
if(%adjustment == 1)
%n = %client.camera.camDist + 0.5;
else
%n = %client.camera.camDist - 0.5;
if(%n < 0.5)
%n = 0.5;
if(%n > 5)
%n = 5;
%client.camera.setOrbitObject(%client.player, %client.camera.getRotation(), 0, %n, %n);
%client.camera.camDist = %n;
}Adding this script directly beneath the previous in "commands.cs" you will notice that we intend to increment the zoom by 0.5 units (less jerky than 1 full unit) and that we carry over the current rotation of the camera when we reset the distance so it doesn't snap back to mDegToRad(20) @ " 0 0" in a horrible, sharp manner.
Now we have the functions, we need to be able to use them with input.
Open up "scripts/client/default.bind.cs" and we shall customize our input. We are only going to use the mouse, so that's "button0, button1 and the zAxis" (zAxis I call "the spinny thing", though apparently it's proper name is the "scroll wheel").
function mouseZoom(%val)
{
if(%val > 0)
{
commandToServer('adjustCamera', -1);
}
else
{
commandToServer('adjustCamera', 1);
}
}
moveMap.bind( mouse, zaxis, mouseZoom );We now have input to send the zoom adjustments we make with the "scroll wheel" to change the camera's distance to the playerObject. Now let's make a toggle for showing/hiding the cursor. With the cursor "off" we can rotate the camera around the playerObject.
// Turn mouse cursor on or off
// If %val is true, the button was pressed in
// If %val is false, the button was released
function toggleMouseLook(%val)
{
// Check to see if button is pressed
if(%val)
{
// If the cursor is on, turn it off.
// Else, turn it on
if(Canvas.isCursorOn())
hideCursor();
else
showCursor();
}
}
//mouse button1 is right mouse button
moveMap.bind( mouse, button1, "toggleMouseLook");Whilst I did just call this a "toggle" in practise it will really be used for enabling the cursor only, giving the client direct input into the "playGui" (that's the GUI which fills the screen in-game and shows what is happening through the camera) and ends the rotation of the camera. With the client having input on to "playGui" they will be able to click locations in-game for the playerObject to move to and shoot at.
To get back to being able to "toggle" the cursor off again and thus rotate the camera around the playerObject again, we need another "toggle" - this time on the PlayGui.
Open up the file game/art/gui/playGui.gui. At the bottom, under //--- OBJECT WRITE END --- add the following.
function PlayGui::onRightMouseDown(%this, %pos, %start, %ray)
{
if(Canvas.isCursorOn())
hideCursor();
else
showCursor();
}You don't need to add a keybind for this.
Since we have given the "scroll wheel/zAxis" a new input function, we need to remove the old one. In stock T3D, zAxis supported "WeaponCycling" which we no longer require. Back in default.bind.cs find the keybind and comment it out, leave the actual function for now - if you comment that out as well, you'll likely have to go and comment out every reference to it spread over a variety of scripts - so let's not bother right now.
function mouseWheelWeaponCycle(%val)
{
if (%val < 0)
commandToServer('cycleWeapon', "next");
else if (%val > 0)
commandToServer('cycleWeapon', "prev");
}
moveMap.bind(keyboard, q, nextWeapon);
moveMap.bind(keyboard, "ctrl q", prevWeapon);
//moveMap.bind(mouse, "zaxis", mouseWheelWeaponCycle);//not anymore you don't!And now do the same for both of the mouse button controls (fire, altFire) as we won't be using them.
/*
function mouseFire(%val)
{
$mvTriggerCount0++;
}
function altTrigger(%val)
{
$mvTriggerCount1++;
}
moveMap.bind( mouse, button0, mouseFire );
moveMap.bind( mouse, button1, altTrigger );
*/To make sure that the system updates our new input controls we need to edit scripts/client/config.cs. This file is autocreated by the game if it doesn't exist, so rather than actually editing we can delete it and force the game to create a new, up-to-date version for us. Run (double-click) on deletePrefs.bat in the root directory of your Project. eg: Torque3D version whatever/My Projects/Torque_Tactics_Tutorial.
Now let's test that camera.
In scripts/server/gamecore.cs find the function GameCore::PreparePlayer and make these changes.
%playerSpawnPoint = pickPlayerSpawnPoint($Game::DefaultPlayerSpawnGroups);
// Spawn a camera for this client using the found %spawnPoint
//%client.spawnPlayer(%playerSpawnPoint);
// %game.spawnPlayer(%client, %playerSpawnPoint);//yorks out!
%game.spawnPlayer(%client, %playerSpawnPoint, false);//yorks in!
commandToServer('tacticsCam');//yorks start our custom camera!
// Starting equipment
%game.loadOut(%client.player);The first change takes away the camera control from the playerObject, the second starts our custom camera function from commands.cs.
There is one last issue. We are not directly controlling he player, we are controlling them by "proxy". So we need to use an AiPlayer. Open scripts/server/gameDm.cs and change the following:
$Game::defaultPlayerClass = "AiPlayer";//"Player"; $Game::defaultPlayerDataBlock = "demoPlayer";//"DefaultPlayerData";
We have to do it in gameDM.cs and not gameCore.cs because the creation of a server defaults to "Deathmatch" as a gametype.
Load up the game and the level. You should now be presented with the playerObject standing in front of you. As you move the mouse you will rotate the camera around the playerObject. When you move the "scroll wheel" you will zoom in and out. When you press the right mouse button you will lose camera control and gain a cursor on screen. Press the right mouse button again and you lose the cursor and regain control of the camera.
Just to check select the playerObject in the World Editor (F11) and you should see that he is an AiPlayer with the datablock "DemoPlayer" rather than a regular Player class object.
That's the new camera system taken care of, next we need the player to be able to move and shoot.
Part Four: Player Actions
About the author
One Bloke ... In His Bedroom ... Making Indie Games ...
#2
Check your spawnsphere to make sure that nothing is listed in the various spawn options of the object or they'll act as an override.
05/16/2011 (4:21 pm)
Dso files should not be created unless you're shipping a final product/demo. Check your spawnsphere to make sure that nothing is listed in the various spawn options of the object or they'll act as an override.
#3
I try to use this tutorial but now , with t3d 1.2 , it´s not working:
the player is not moving to target where I make click.
11/24/2011 (2:45 pm)
Hi.I try to use this tutorial but now , with t3d 1.2 , it´s not working:
the player is not moving to target where I make click.
#4
10/17/2012 (7:25 am)
i had same issue as chip, glad you cleared that up with spawnsphere, might have been there for hours finding the issue lol
#5
10/18/2012 (11:29 am)
Steve, I've tried this 4 times on a fresh install of T3D 1.2 and I must be doing something wrong because every time I do this tutorial, the camera no longer works properly. The camera works great before, but after the addition of this, I can no longer rotate the camera, and none of the keyboard keys work like 'h' for example to get rid of the help gui. Any ideas?
#6
//moveMap.bind( mouse, button1, mouseButtonZoom );
~line 487 or so
03/08/2013 (7:41 pm)
Running through the tutorial now and I noticed an additional line that should be commented out...//moveMap.bind( mouse, button1, mouseButtonZoom );
~line 487 or so

Associate Chip Lambert
Crusader Games
I'm having one problem, I made the change to gameDM.cs however when I look in the World Editor, I see my player is still listed as DefaultPlayerData. I tried cleaning up the dso files but still doesn't work. Any tips?