2 playable characters
by Richard Chouinard · in Torque Game Engine · 03/30/2007 (12:49 pm) · 15 replies
Hi, I've searched the forums topics. But can't found any informations on an integration of two or more playable characters into the engine. What we'd like to do is to be able to switch between 2 characters in realtime.
We've looked at the Rts add-on but we would like a simplier method. Do we need to script it into TGE or into C++? We don't know where to start for this.
Anyone can help or forward us to the right resource?
Thanks!
We've looked at the Rts add-on but we would like a simplier method. Do we need to script it into TGE or into C++? We don't know where to start for this.
Anyone can help or forward us to the right resource?
Thanks!
About the author
#2
1. If you simply want to change players look (texture) based on the same 3d object then torque allows for multiple textures to be created for the same object and swapped using script.
2. If you're trying to switch the 3d model to a completely new one then you can try looking up the setdatablock method which should allow you to switch mid game any of the player related datablock elements - mass, speed, 3d model, etc and you might find the Player::onNewDataBlock callback useful which is called when you swap an objects datablock. This does work but there is no transition in a blink it swaps from one model to another - so you may want to put a special effect (particle emitter for example) to mask the change-over.
3. Thirdly Torque must always have a control object which is the object currently being controlled by the gamer, this control object can also be swapped mid-game - for example when you enter mission editor you can switched control between the player and free camera, it's also possible to switch control to any other object too. So you could have other characters loaded but set as hidden... then when ready to use swap the hidden objects and control object over - to see how to switch over the control object look at the commands.cs in the /server/scripts folder as you can see
function serverCmdToggleCamera(%client)
{
%control = %client.getControlObject();
if (%control == %client.player)
{
%control = %client.camera;
%control.mode = toggleCameraFly;
}
else
{
%control = %client.player;
%control.mode = observerFly;
}
%client.setControlObject(%control);
}
As you can see switching over control is as simple as passing the reference to the object you want to have control, i.e. new player avatar/vehicle.
4. You could also look at having it all in the dts file and then hiding/showing nodes via script/c++, had a look for resource where this was done and you can have a look at this:
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2150
That's all I can think of for the moment hope some of it is of use
03/31/2007 (3:54 pm)
Not 100% sure what exactly it is that you are trying to do - if it's trying to have 2 people controlling different players at the same time I am not sure how but if you're just trying to swap one persons character mid-game to a different model then I have some suggestions - I'm new to torque so all might not work but worth investigating.1. If you simply want to change players look (texture) based on the same 3d object then torque allows for multiple textures to be created for the same object and swapped using script.
2. If you're trying to switch the 3d model to a completely new one then you can try looking up the setdatablock method which should allow you to switch mid game any of the player related datablock elements - mass, speed, 3d model, etc and you might find the Player::onNewDataBlock callback useful which is called when you swap an objects datablock. This does work but there is no transition in a blink it swaps from one model to another - so you may want to put a special effect (particle emitter for example) to mask the change-over.
3. Thirdly Torque must always have a control object which is the object currently being controlled by the gamer, this control object can also be swapped mid-game - for example when you enter mission editor you can switched control between the player and free camera, it's also possible to switch control to any other object too. So you could have other characters loaded but set as hidden... then when ready to use swap the hidden objects and control object over - to see how to switch over the control object look at the commands.cs in the /server/scripts folder as you can see
function serverCmdToggleCamera(%client)
{
%control = %client.getControlObject();
if (%control == %client.player)
{
%control = %client.camera;
%control.mode = toggleCameraFly;
}
else
{
%control = %client.player;
%control.mode = observerFly;
}
%client.setControlObject(%control);
}
As you can see switching over control is as simple as passing the reference to the object you want to have control, i.e. new player avatar/vehicle.
4. You could also look at having it all in the dts file and then hiding/showing nodes via script/c++, had a look for resource where this was done and you can have a look at this:
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2150
That's all I can think of for the moment hope some of it is of use
#3
04/01/2007 (8:55 pm)
Yes it's 2 mid-game switchable characters all played by one player. We'll look into your suggestions next week. Thank you very much for your help.
#4
I gave the game connection a SimSet (named 'players') to hold the switchable characters. Then I changed the createPlayer function so that it created an AIPlayer, instead of a Player. Then I modified the getAIMove C++ method in aiPlayer.cc to obey a a new AIPlayer instance variable named 'isHumanControlled' and exposed it to script. If the 'isHumanControlled' variable was true, getAIMove short circuited and return false. I'm not sure if this was strictly necessary, however. Then to switch between players, I just switched the control object on the game connection between them with setControlObject, set the game connection's '%client.player' variable to that character, and set isHumanControlled to the appropriate value (true if switching to the character, false if switching away from it).
One of the reasons I decided to derive my players from AIPlayer was so that they didn't just sit there like statues when they weren't being actively controlled. This way, they were 'autonomous' when not controlled, and then obey the player's move commands when they were currently 'inhabited' by the human player. I added a key command to rotate to the next playable character in the game connection's SimSet, and could switch between an arbitrary number of characters (most I tried was 6, but see no reason for there to be any hard limit).
04/03/2007 (5:45 am)
I did this in a prototype I was working on. I don't have time to dig out code examples right now, so here's just a brief description of how I implemented this.I gave the game connection a SimSet (named 'players') to hold the switchable characters. Then I changed the createPlayer function so that it created an AIPlayer, instead of a Player. Then I modified the getAIMove C++ method in aiPlayer.cc to obey a a new AIPlayer instance variable named 'isHumanControlled' and exposed it to script. If the 'isHumanControlled' variable was true, getAIMove short circuited and return false. I'm not sure if this was strictly necessary, however. Then to switch between players, I just switched the control object on the game connection between them with setControlObject, set the game connection's '%client.player' variable to that character, and set isHumanControlled to the appropriate value (true if switching to the character, false if switching away from it).
One of the reasons I decided to derive my players from AIPlayer was so that they didn't just sit there like statues when they weren't being actively controlled. This way, they were 'autonomous' when not controlled, and then obey the player's move commands when they were currently 'inhabited' by the human player. I added a key command to rotate to the next playable character in the game connection's SimSet, and could switch between an arbitrary number of characters (most I tried was 6, but see no reason for there to be any hard limit).
#6
I want to toggle the control between the two characters. I created a function serverCmdToggleCharacter that is called when the user presses a key.
The code that I have right now does not work :
function serverCmdToggleCharacter(%client)
{
// Give the client control of the player
%client.player = %player2;
%client.setControlObject(%client.advCamera);
// set the camera system around the %player
%client.advCamera.setPlayerObject(%player2);
}
I am unsure how to get the %player2 variable. I think this portion of the code can't see it and instantiates a new player2. How do I pass the correct %player2 to %client.player and %client.advCamera.setPlayerObject()?
04/05/2007 (7:41 am)
I was able to spawn to UI characters in a mission. I am currently controlling one of them with mouse clicks and the setMoveDestination function. I want to toggle the control between the two characters. I created a function serverCmdToggleCharacter that is called when the user presses a key.
The code that I have right now does not work :
function serverCmdToggleCharacter(%client)
{
// Give the client control of the player
%client.player = %player2;
%client.setControlObject(%client.advCamera);
// set the camera system around the %player
%client.advCamera.setPlayerObject(%player2);
}
I am unsure how to get the %player2 variable. I think this portion of the code can't see it and instantiates a new player2. How do I pass the correct %player2 to %client.player and %client.advCamera.setPlayerObject()?
#7
04/05/2007 (7:51 am)
You would probably pass in the ID of the player2 object created, or store it as a global variable on the server side:function serverCmdToggleCharacter(%client, %player2ID)
{
// Give the client control of the player
%client.player = %player2ID;
%client.setControlObject(%client.advCamera);
// set the camera system around the %player
%client.advCamera.setPlayerObject(%player2ID);
}
#8
I don't have access to the player2 object on the client side (in default.bind.cs), that's why I created the serverCmdToggleCharacter function. I thought it would have access to the player2. Now I don't know who has access to the object. Can anyone point me to a tutorial on the scope of objects?
04/05/2007 (7:55 am)
How do I set a global variable on the server side?I don't have access to the player2 object on the client side (in default.bind.cs), that's why I created the serverCmdToggleCharacter function. I thought it would have access to the player2. Now I don't know who has access to the object. Can anyone point me to a tutorial on the scope of objects?
#9
Pseudo code:
This just pseudo-code, since I don't know how you are creating your character or toggling them behind the scenes. This is just how to set the global variable and use it later in the server commands.
04/05/2007 (8:01 am)
When you create the player 2 object, set a variable:Pseudo code:
function creatPlayerTwo()
{
$playerTwoObject = new Player("PlayerTwo"){...};
}
function serverCmdToggleCharacter(%client)
{
// Give the client control of the player
%client.player = $playerTwoObject;
%client.setControlObject(%client.advCamera);
// set the camera system around the %player
%client.advCamera.setPlayerObject($playerTwoObject);
}This just pseudo-code, since I don't know how you are creating your character or toggling them behind the scenes. This is just how to set the global variable and use it later in the server commands.
#10
function GameConnection::createPlayer(%this, %spawnPoint)
{
if (%this.player > 0) {
error( "Attempting to create an angus ghost!" );
}
// Create the player object
%player = new AIPlayer() {
dataBlock = PlayerBody;
client = %this;
};
MissionCleanup.add(%player);
// Player setup...
%player.setTransform(%spawnPoint);
%player.setShapeName(%this.name);
if (%this.player2 > 0) {
error( "Attempting to create an angus ghost!" );
}
// Create the player object
%player2 = new AIPlayer() {
dataBlock = Player2Body;
client = %this;
};
MissionCleanup.add(%player2);
// Player setup...
%player2.setTransform(%spawnPoint);
%player2.setShapeName(%this.name + "2");
// 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(%this.advCamera);
// We set the camera system to run in 3rd person mode around the %player
%this.advCamera.setPlayerObject(%player);
%this.advCamera.setThirdPersonMode();
%this.advCamera.setFollowTerrainMode(false);
%this.advCamera.setVerticalFreedomMode(false);
%this.setCameraObject(%this.advCamera);
%this.advCamera.setOrbitMode();
%this.advCamera.setOrbitMinMaxDeclination("0 180");
$advCamera::declination = 95;
$advCamera::azimuth = 0;
$advCamera::Zoomdistance = 10;
04/05/2007 (8:03 am)
This is the function that creates the players:function GameConnection::createPlayer(%this, %spawnPoint)
{
if (%this.player > 0) {
error( "Attempting to create an angus ghost!" );
}
// Create the player object
%player = new AIPlayer() {
dataBlock = PlayerBody;
client = %this;
};
MissionCleanup.add(%player);
// Player setup...
%player.setTransform(%spawnPoint);
%player.setShapeName(%this.name);
if (%this.player2 > 0) {
error( "Attempting to create an angus ghost!" );
}
// Create the player object
%player2 = new AIPlayer() {
dataBlock = Player2Body;
client = %this;
};
MissionCleanup.add(%player2);
// Player setup...
%player2.setTransform(%spawnPoint);
%player2.setShapeName(%this.name + "2");
// 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(%this.advCamera);
// We set the camera system to run in 3rd person mode around the %player
%this.advCamera.setPlayerObject(%player);
%this.advCamera.setThirdPersonMode();
%this.advCamera.setFollowTerrainMode(false);
%this.advCamera.setVerticalFreedomMode(false);
%this.setCameraObject(%this.advCamera);
%this.advCamera.setOrbitMode();
%this.advCamera.setOrbitMinMaxDeclination("0 180");
$advCamera::declination = 95;
$advCamera::azimuth = 0;
$advCamera::Zoomdistance = 10;
#11
04/05/2007 (8:07 am)
Ok, so just switch %player and %player2 for $playerOne and $playerTwo respectively.
#12
04/05/2007 (8:07 am)
I got it working by changing player and player2 objects to global variables. Thank you Michael.
#13
04/05/2007 (8:11 am)
Happy to help out.
#14
I'd think about trying to store every function and reference related to a single player inside structures related to that player, such as the GameConnection, Player, etc... ie, if you only want your human player to be able to deal with two potentially controllable characters, move those $player and $player2 references to %client.player and %client.player2 respectively (as an extremely generalized example). If you want potentially more characters to be player-controllable, think about something of variable length, such as a SimSet (ie.,, %client.players, if initialized).
Global variables that refer to player attributes are fine if you are SURE you are writing a single-player game. But just think about how much cooler it would be if it were multi-player, and about how much easier it would be if you had taken that into consideration right from the start...
04/07/2007 (10:26 pm)
Any time i use global variables for something specifically player-related, I hear a tiny voice in my head that says, "You're doomed!"I'd think about trying to store every function and reference related to a single player inside structures related to that player, such as the GameConnection, Player, etc... ie, if you only want your human player to be able to deal with two potentially controllable characters, move those $player and $player2 references to %client.player and %client.player2 respectively (as an extremely generalized example). If you want potentially more characters to be player-controllable, think about something of variable length, such as a SimSet (ie.,, %client.players, if initialized).
Global variables that refer to player attributes are fine if you are SURE you are writing a single-player game. But just think about how much cooler it would be if it were multi-player, and about how much easier it would be if you had taken that into consideration right from the start...
#15
%player2.setTransform(vectorAdd(%spawnPoint , "2 0 0"); //so things don't start in the same place
04/07/2007 (11:35 pm)
Just a suggestion%player2.setTransform(vectorAdd(%spawnPoint , "2 0 0"); //so things don't start in the same place
Torque Owner Andy Rollins
ZDay Game
1. If you simply want to change players look (texture) based on the same 3d object then torque allows for multiple textures to be created for the same object and swapped using script.
2. If you're trying to switch the 3d model to a completely new one then you can try looking up the setdatablock method which should allow you to switch mid game any of the player related datablock elements - mass, speed, 3d model, etc and you might find the Player::onNewDataBlock callback useful which is called when you swap an objects datablock. This does work but there is no transition in a blink it swaps from one model to another - so you may want to put a special effect (particle emitter for example) to mask the change-over.
3. Thirdly Torque must always have a control object which is the object currently being controlled by the gamer, this control object can also be swapped mid-game - for example when you enter mission editor you can switched control between the player and free camera, it's also possible to switch control to any other object too. So you could have other characters loaded but set as hidden... then when ready to use swap the hidden objects and control object over - to see how to switch over the control object look at the commands.cs in the /server/scripts folder as you can see
function serverCmdToggleCamera(%client)
{
%control = %client.getControlObject();
if (%control == %client.player)
{
%control = %client.camera;
%control.mode = toggleCameraFly;
}
else
{
%control = %client.player;
%control.mode = observerFly;
}
%client.setControlObject(%control);
}
As you can see switching over control is as simple as passing the reference to the object you want to have control, i.e. new player avatar/vehicle.
4. You could also look at having it all in the dts file and then hiding/showing nodes via script/c++, had a look for resource where this was done and you can have a look at this:
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2150
That's all I can think of for the moment hope some of it is of use