IMPORTANT NOTE: Hi and thanks for visiting. This tutorial so far works pretty good. If you try it out and find a error, please let me know. I would like to think that most of the problems have been ironed out before I post it as a resource at GarageGames.com. You can e-mail me here. Please include the subject Torque Tutorial in your message. I will most likely update the info as people try it out and make suggestions. So please check back from time-to-time. If you'd like to see a few more tutorials, you can go to my Games Blog as well. NEW UPDATE September 11, 2006 - It's ready! The initial draft to my latest Torque Tutorial. Some progress on the Torque Tutorial - Player Selection and Player Previewer. This bit of script allows you to choose a character and mount weapons. Check out the preview movie to get an idea of what it looks like at this time.
Interested in the next Torque Tutorial? Get an alert, please join my free newsletter .
|
OVERVIEW
This tutorial shows an example of simple player selection via a pop up menu and explains how to pass a user provided value. In this tutorial, the value that the user chooses is captured and is stuffed into a variable. The variable is then used to determine which shape file to use for the player. Below is an example of the gui showing player selection:

RESOURCES
There were a number of references for this tutorial and this is my first stab at scripting in Torque. Here are a few links I checked out that might be of interest:
For the drop down menu - http://www.garagegames.com/mg/forums/result.thread.php?qt=30088
The thread that inspired this tutorial - http://www.garagegames.com/mg/forums/result.thread.php?qt=15408. There were good leads by Gonzo T. Clown and Mike Rowley.
Other threads relating to more advanced player selection that I found really interesting include:
http://www.garagegames.com/mg/forums/result.thread.php?qt=25909
http://www.garagegames.com/mg/forums/result.thread.php?qt=48985
In addition to the named links, there were other threads that I read as well, but I personally can't remember them as I was hunting around quite a bit trying to get the examples to work. However, as much as I tried to follow their examples, I wasn't able to do what I wanted to do. I found that they would be talking about files and functions that I may not have been aware of or didn't have. Maybe the point of reference for their code was TGE 1.4. I dunno. I am a newbie Torquer and as such, the info is my own approach to this problem just by surfing around the forums. To clarify, we will be using TGE 1.3.
FRAMEWORK/POINT OF REFERENCE
Check out GarageGames for the best Indie Game Engine around!
starter.fps (the one that came with the original TGE 1.3 install).
INITIAL SETUP AND RESOURCE DOWNLOAD
We will be working with models and .cs files. In this initial set, we will be putting the models in the correct directories.
Before you begin, you should put the Thom.dts and its associated files in the player folder located at starter.fps\data\shapes\player. You can download the support files here. As you go through the tutorial, be sure to look at the files so you know where to put those code snippets in this tutorial.
Download support files (*new as of September 5, 2006)
There are two datablocks we are interested in:
1. PlayerBody - The default that this starter.fps kit uses, this is the Orc model. Its .dts file name is player.dts and is located in starter.fps\data\shapes\player.

Above is the Orc. The Orc is defined in the player.cs file in datablock PlayerData(PlayerBody).
2. PlayerBody2 - This is the new one. This one uses the Thom.dts file.

Above is the Thom model. The model is defined in the player.cs file in datablock PlayerData(PlayerBody2) and can be found in the download file provided. This datablock describes the Thom model's attributes and has all of the characteristics of PlayerBody, except it has a different "body" as defined by the .dts file the shape file is pointing to.
The PlayerBody and PlayerBody2 datablocks are updated in the player.cs file. The file can be found in starter.fps\server\scripts\. Here's an excerpt from the player.cs file from the download files showing the first datablock for PlayerBody:
//more code above...
datablock PlayerData(PlayerBody)
{
renderFirstPerson = false;
emap = true;
className = Armor;
shapeFile = "~/data/shapes/player/player.dts"; //<--original dts file. It's Orc.
cameraMaxDist = 3;
computeCRC = true;
canObserve = true;
cmdCategory = "Clients";
cameraDefaultFov = 90.0;
cameraMinFov = 5.0;
cameraMaxFov = 120.0;
debrisShapeName = "~/data/shapes/player/debris_player.dts";
debris = playerDebris;
//more code below...
This datablock can be used as the template for other additional player types.
I then copied the original PlayerBody datablock, pasted it underneath, then changed PlayerBody to PlayerBody2. Here's the PlayerBody2 datablock:
//more code above...
//jt*************************************************************************
datablock PlayerData(PlayerBody2)
{
renderFirstPerson = false;
emap = true;
className = Armor;
shapeFile = "~/data/shapes/player/Thom.dts"; //<---uses a different dts file to define this datablock.
cameraMaxDist = 3;
computeCRC = true;
canObserve = true;
cmdCategory = "Clients";
cameraDefaultFov = 90.0;
cameraMinFov = 5.0;
cameraMaxFov = 120.0;
debrisShapeName = "~/data/shapes/player/debris_player.dts";
debris = playerDebris;
//more code below..
SIDE NOTE: datablock PlayerData(PlayerBody: PlayerBody2) |
FIND OUT WHAT THE USER CHOSE
While the shapefile can be manually changed in the player.cs files that would be a pain. So in order to communicate to the game what player to use, we need to use a gui or an interface. In this tutorial example, we use the pop up menu.
After, we've placed the models in the proper directories and have adjusted the player.cs file so that the game knows which file to use, we then go on to the next part where we capture the user's choice. The user's choice will be captured via the gui and the user's choice will be stuffed in the variable jtPlayerData.
In order to capture the user's choice for multi-player or single play mode, we need to adjust the joinServerGui.gui and the startMissionGui.gui respectively.
joinServerGui.gui (located in starter.fps\client\ui)- This is the gui that pops up when you want to join a multiplayer environment. It looks like this:

startMissionGui.gui (located in starter.fps\client\ui) - This pops up when playing single player only. It looks like this:

Two additional files we will be working with include:
clientConnection.cs (located in \common\server, unlike the other files, this one resides outside of the starter.fps folder) - This file handles the variable (in our example jtPlayerBody) value from the client form. It captures what we type in the text control that we pass from the client form. For this tutorial, we are interested in the GameConnection::onConnect function.
game.cs (located in starter.fps\server\scripts) - The game uses the passed value in this file's function GameConnection::onClientEnterGame(%this)
PLAYER SELECTION FOR SINGLE PLAYER MODE
For the start.fps starter kit, there are two modes of play. One is in single player mode, where you do not connect to a master server and the other is multi-player mode where you do connect to a master server so that you can play with other connected players. The single player mode uses the startMissionGui.gui as the gui for entry into the game. Below is what it looks after going through this tutorial:

The other file we will look at is the joinServerGui.gui file. We'll look at that file a little later on.
For single game play, you need to go to the startMissionGui.gui located in client\ui\ . Here's the code snippet that sets up the pop up menu:
new GuiPopUpMenuCtrl(jtPlayerBodyChoice) {
profile = "GuiPopUpMenuProfile";
horizSizing = "left";
vertSizing = "bottom";
position = "272 15";
extent = "126 19";
minExtent = "8 2";
visible = "1";
variable = "pref::Player::jtPlayerBody";
text = "Choose Player";
maxLength = "255";
maxPopupHeight = "200";
};
The value that the user chooses is then used to connect locally to the server. Before that happens, we need to add the jtPlayerBody variable as one of the values that gets passed as the player's choice. We do this in the same file. Around lines 163 or so, you will see:
//----------------------------------------
function SM_StartMission()
{
%id = SM_missionList.getSelectedId();
%mission = getField(SM_missionList.getRowTextById(%id), 1);if ($pref::HostMultiPlayer)
%serverType = "MultiPlayer";
else
%serverType = "SinglePlayer";createServer(%serverType, %mission);
%conn = new GameConnection(ServerConnection);
RootGroup.add(ServerConnection);//jtmd
//below is the original
//%conn.setConnectArgs($pref::Player::Name);//we want to pass the value that the user types into the text control
//namely, the one marked as pref::Player::jtPlayerBody
%conn.setConnectArgs($pref::Player::Name, $pref::Player::jtPlayerBody);%conn.setJoinPassword($Client::Password);
%conn.connectLocal();
}
Remember that TGE is a client/server program. So even locally, it still connects to a server. See how we added the additional variable? To get a better idea, just read my comments just above the conn.setConnectArgs() function.
...and just a few lines down after the SM_StartMission() funcion, add this code snippet so we can capture the user's choice of player:
//jtmd**************************************************************************
//setup the pop up menu
//adds the selections
jtPlayerBodyChoice.add("Be an Orc",0);
jtPlayerBodyChoice.add("The Yellow Man",1);
jtPlayerBodyChoice.add("Default",2);function jtPlayerBodyChoice::onSelect(%this, %id, %text)
{
echo("ID = " @ %id);
if(%id != -1)
{
if(%id == 0)
{jtPlayerBodyChoice.setText("Orc"); //<--if chosen this value gets passed to the server via the variable jtPlayerBody
} else if(%id == 1)
{jtPlayerBodyChoice.setText("Yellow Man"); //<--if chosen this value gets passed to the server via the variable jtPlayerBody
} else if(%id == 2)
{jtPlayerBodyChoice.setText("Dunno"); //<--if chosen this value gets passed to the server via the variable jtPlayerBody
}
}
}
//jtmd**************************************************************************
PLAYER SELECTION FOR MULTI-PLAYER MODE
Now for the multiplayer mode, the joinServerGui.gui looks like this:

The joinServerGui is used for multi-player mode. It allows you to enter a name, load the game, look for a server, and other fun things.
Open up the joinServerGui.gui and add the following line:
new GuiTextEditCtrl(jtPlayerBodyChoice) {
profile = "GuiTextEditProfile";
horizSizing = "right";
vertSizing = "bottom";
position = "269 34";
extent = "171 18";
minExtent = "8 8";
visible = "1";
variable = "pref::Player::jtPlayerBody"; //<--this is our variable. Whatever is captured from the gui is "stuffed" into variable jtPlayerBody!
text = "PlayerBody";
maxLength = "255";
historySize = "0";
password = "0";
tabComplete = "0";
sinkAllKeyEvents = "0";
helpTag = "0";
};
The above code is located on or about line 141 in the example. The above is for the gui that pops up when the user wants to join a game. In other words a multi-player environment. In the same file, we still need to pass the value that the user will put in the pop up menu control. In this tutorial, it's either PlayerBody or PlayerBody2, Orc and Thom respectively. On or about line 350, we see function JoinServerGui::join(%this). In its setConnectArg() function, we make sure to add the additional variable so we can pass it to the server. In this case, the variable jtPlayerBody with a user choice value of either PlayerBody or PlayerBody2 via the pop up menu.
//----------------------------------------
function JoinServerGui::join(%this)
{
cancelServerQuery();
%id = JS_serverList.getSelectedId();
// The server info index is stored in the row along with the
// rest of displayed info.
%index = getField(JS_serverList.getRowTextById(%id),6);
if (setServerInfo(%index)) {
%conn = new GameConnection(ServerConnection);
//%conn.setConnectArgs($pref::Player::Name);
//the jtPlayerBody is tied into a text control on this gui
%conn.setConnectArgs($pref::Player::Name, $pref::Player::jtPlayerBody);
%conn.setJoinPassword($Client::Password);
%conn.connect($ServerInfo::Address);
}
}
//...more code here....
Just keep the above in the back of your mind as the value of jtPlayerBody is later used to decide which shape file to use.
After the gui has been closed off with a "}" you should add this function in the same file. This sets up the pop up menu where the user will be able to choose which player he wants to be:
//jtmd**************************************************************************
//setup the pop up menu
//adds the selections
jtPlayerBodyChoice.add("Be an Orc",0);
jtPlayerBodyChoice.add("The Yellow Man",1);
jtPlayerBodyChoice.add("Default",2);
function jtPlayerBodyChoice::onSelect(%this, %id, %text)
{
echo("ID = " @ %id);
if(%id != -1)
{
if(%id == 0)
{
jtPlayerBodyChoice.setText("Orc"); //<--if chosen this value gets passed to the server via the variable jtPlayerBody
} else if(%id == 1)
{
jtPlayerBodyChoice.setText("Yellow Man")//<--if chosen this value gets passed to the server via the variable jtPlayerBody
} else if(%id == 2)
{
jtPlayerBodyChoice.setText("Dunno"); //<--if chosen this value gets passed to the server via the variable jtPlayerBody
}
}
}
//jtmd**************************************************************************
Once you've done that, open the clientConnection.cs file located in \common\serve. You will need to add this in the GameConnection:onConnect function so it looks like this:
//-----------------------------------------------------------------------------
// This script function is the first called on a client accept
//
function GameConnection::onConnect( %client, %name, %jtPlayerBody )
{
//find out what was passed so we can work with it
switch$(%jtPlayerBody)
{
case "Orc":
%client.jtPlayerBody="PlayerBody"; //<--Orc (player.dts)
case "Yellow Man":
%client.jtPlayerBody="PlayerBody2"; //<--Yellow dude (thom.dts)
default:
%client.jtPlayerBody="PlayerBody2";
}
What we're doing here is capturing the value of jtPlayerBody. We use a switch$ statement to decide which PlayerBody to use. For example, if the jtPlayerBody variable was stuffed with the "Orc" value, then the game will use datablock PlayerData(PlayerBody) as the user's body of choice. Now if the jtPlayerBody variable was stuffed with the "Yellow Man" value, then the game will use datablock PlayerData(PlayerBody2) as the user's body of choice. If all else fails, the datablock PlayerData(PlayerBody2) is used.
When the user has chosen the either PlayerBody or PlayerBody2 in the pop up menu. TGE stuffs it into the variable jtPlayerBody and then passes the value via the setConnectArgs() function to the server. The next part describes what happens when it connects.
The clientConnection.cs file is located in common\server\. On or about line 21 you will see this:
//-----------------------------------------------------------------------------
// This script function is the first called on a client accept
//
function GameConnection::onConnect( %client, %name, %jtPlayerBody )//<--this accepts the value chosen by user via the gui and is then used in the game.
{
%client.jtPlayerBody=%jtPlayerBody;
// Send down the connection error info, the client is
// responsible for displaying this message if a connection
// error occures.
messageClient(%client,'MsgConnectionError',"",$Pref::Server::ConnectionError);
// Send mission information to the client
sendLoadInfoToClient( %client );
// Simulated client lag for testing...
// %client.setSimulatedNetParams(0.1, 30);
//...more code below....
The above is just a snippet of the onConnect event. So what's happened here is that the passed value is picked up by the onConnection() event. See the %jtPlayerBody? Well that's where the value that was passed from the gui via the setConnectArgs() function goes when we chose launch the mission as a single player or join up in multi-player mod.. We can then use it like this:
%client.jtPlayerBody=%jtPlayerBody;
For example, if the user chose "Yellow Man" (which equates to the Thom model) into the pop up menu, it is just as though the line were to read like this:
%client.jtPlayerBody="PlayerBody2";
USE THE VARIABLE VALUE IN THE GAME (*sigh* finally...)
Now that we've got it figured out, we can then apply it to the onClientEnterGame() event. So open up your game.cs file and replace:
%this.spawnPlayer();
with
%this.spawnPlayer(%this.jtPlayerBody);
And now in the function GameConnection::createPlayer(%this, %spawnPoint) add the following:
function GameConnection::createPlayer(%this, %spawnPoint)
{
if (%this.player > 0) {
// The client should not have a player currently
// assigned. Assigning a new one could result in
// a player ghost.
error( "Attempting to create an angus ghost!" );
}// Create the player object
%player = new Player() {
//jtmd
dataBlock=%this.jtPlayerBody;
client = %this;
};
MissionCleanup.add(%player);// Player setup...
%player.setTransform(%spawnPoint);
%player.setShapeName(%this.name);
// Starting equipment
//jt
%player.setInventory(Crossbow,1);
%player.setInventory(CrossbowAmmo,10);
//jt mod
%player.mountImage(CrossbowImage,0);// Update the camera to start with the player
%this.camera.setTransform(%player.getEyeTransform());// Give the client control of the player
%this.player = %player;
%this.setControlObject(%player);
}
And that about does it for now. This last part will then choose the shape file based on the user's choice via the pop up menu.
This information is then used in the game.cs and player.cs files to determine what shape to use. In this case, PlayerBody2 would use the Thom.dts file.
So there you have it. You can effectively launch the game and have your choice of character via a pop up menu. I am sure there is probably a more optimized way to approach player selection and as such I welcome your comments. But for now, it works for me, woo hoo!
So do you want to be an Orc or Thom?
Happy Torquing...
You can then change the switch statement to account for the newly created third character or third PlayerBody:
//-----------------------------------------------------------------------------*Notice that in the switch statement it is written as switch$ with the dollar sign vs. switch. That is because we are comparing String characters. Had it been numbers, we would use just the switch(%value).
THE NEXT TUTORIAL
Above: I used the files from this resource by Vince_Smurf and Loonatik. For the example above, I used the extended guiObjectView by Xavier. My tutorial will expand just a bit more on the guiObjectView and script to allow the display of the player and mountable weapons. I worked on an initial draft and will post when it's ready. But for now, I need people to test it. Please let me know if you'd like to test it. Send me an e-mail here.
SOME INITIAL PROGRESS FOR THE PLAYER PREVIEWER
Ok, below is a preview of the next tutorial I am writing. I've gotten really busy with a few projects so I will most likely take my time with this one as the code I wrote is a bit of a kludge that I am embarassed to put it out in public. It's sorta like sneezing too hard and things just fly out of control, *if* you know what I mean.
Ew.
Anyway, for the buttons, I used a GuiBitmapButtonCtrl so you can add a custom bitmap picture with different states such as up, down, over, and press.
Above: To replay the Flash movie, right mouse-click the screen and a context menu will appear. You can then select rewind then play. If you feel lazy and you can also just hit the refresh button on your browser. For this one, I used two new characters. A male and female avatars purchased online as a content pack along with some weapons
WHO IS THOM?
Thom is a character that is used in the Animation Master tutorials and is also a used by Obsidian Games as the model for their AMSdtsPlus exporter plugin. The plugin allows you to now export DTS and DSQ from Animation Master v.12 and v.13. You could say that Thom is the equivalent of the Orc found in the starter.fps starter files.You can see a sample of an animation I did a few years ago here.
Go Back to tutorial...
NEW DOWNLOAD?
As of this Tuesday September 5th 2006 I've replaced the original download as the human avatar should not have been included within the downloads. It was a model I was doing some testing on at the time. If you're interested it's from Ken Finney's book 3D Game Programming All-in-One (Torque). It's an excellent intro to Torque and the tools that can be used. To date, I'm still going through the first few chapters and as I read through it, I am constantly thinking how I wish I had gotten it sooner.
Go Back to tutorial...
James Tadeo Web Designer and Programmer, Brampton ON CANADA
© Copyright 2006 James Tadeo All trademarks, copyrights, and branding belong to their respective owners.