TGE Local Multiplayer
by Manoel Neto · 04/04/2006 (11:00 am) · 12 comments
Download Code File
This resource implements local multiplayer support, allowing a client to control two or more players at the same time through a single connection. It does so by adding a slaveObject array to the gameConnection class, that contain additional control objects. These slave objects behave as if they were control objects themselves, recieving moves in their processTick calls.
The move manager is also updated, keeping track of an array of moves, instead of a single one, so it's possible to bind keys for each player independently, since the move-related console variables now use the torquescript "array" format (example: $mvForwardAction[0], $mvForwardAction[1], $mvForwardAction[2], etc...). The scripts in the .ZIP file show an example on how to setup the key bindings.
I tried making everything in accordance with TGE's networking, so nothing prevents you from mixing local and remove players, but that wasn't really tested, so be warned.
A big thanks goes to Matt Zuhlke, who took these modifications apart and organized them into a nice resource.
To install, find and replace the files in a clean 1.4 TGE install by the ones in the ZIP and re-compile. The scripts are based on the starter.fps scripts. Use a DIFF tool to check the differences or to merge with your own project if you have your own changes.
Also, make sure all players are properly scoped to the client that's controlling them, to avoid problems like jittering or players not interpolating properly.
This resource implements local multiplayer support, allowing a client to control two or more players at the same time through a single connection. It does so by adding a slaveObject array to the gameConnection class, that contain additional control objects. These slave objects behave as if they were control objects themselves, recieving moves in their processTick calls.
The move manager is also updated, keeping track of an array of moves, instead of a single one, so it's possible to bind keys for each player independently, since the move-related console variables now use the torquescript "array" format (example: $mvForwardAction[0], $mvForwardAction[1], $mvForwardAction[2], etc...). The scripts in the .ZIP file show an example on how to setup the key bindings.
I tried making everything in accordance with TGE's networking, so nothing prevents you from mixing local and remove players, but that wasn't really tested, so be warned.
A big thanks goes to Matt Zuhlke, who took these modifications apart and organized them into a nice resource.
To install, find and replace the files in a clean 1.4 TGE install by the ones in the ZIP and re-compile. The scripts are based on the starter.fps scripts. Use a DIFF tool to check the differences or to merge with your own project if you have your own changes.
Also, make sure all players are properly scoped to the client that's controlling them, to avoid problems like jittering or players not interpolating properly.
About the author
#2
04/04/2006 (4:55 pm)
Wow very nice I will definetely use this in my game!
#3
04/11/2006 (3:08 am)
Great resource!!!
#4
07/09/2006 (3:11 am)
Thanks, this is brilliant
#5
08/22/2006 (2:24 pm)
Has anyone tried this and had some odd jittering? (Yes, objects are scoped.)
#6
As you can see, int i is already being used, so in your second FOR statement the iterator should be some other letter.
09/23/2006 (7:11 pm)
Good stuff! The only problem I see is around line 574 in gameConnectionMoves.cc://--------------------------------------------------------
// LOCAL_MULTIPLAYER
for (U32 i=0; i<MAX_PLAYERS; i++) {
//--------------------------------------------------------
//----------------------------------
// LOCAL_MULTIPLAYER
Move tmp;
for (int i = 0; i < skip; i++)
tmp.unpack(bstream);
// LOCAL_MULTIPLAYER
//----------------------------------As you can see, int i is already being used, so in your second FOR statement the iterator should be some other letter.
#7
01/02/2007 (8:14 pm)
I noticed that if the Second Player is dead. Both the players are considered dead and respawned. Is there a fix for this?
#8
02/07/2007 (9:46 pm)
My second player is incredibly jittery (bounces up and down in place). Is this because I don't have the Advanced Camera resource implemented or is there something else going on?
#9
if (bstream->readFlag())
{
S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
GameBase* obj = dynamic_cast<GameBase*>(resolveGhost(gIndex));
setSlaveObject(i,obj); //setSlaveObject(obj);
obj->readPacketData(this, bstream);
}
From what I understand the problem is that dynamic_cast is always returning a NULL value and assigning it to obj so the program fails every time it tries to execute obj->readPacketData(this, bstream);. Anyone has an idea of what could be the reason why is always assigning a NULL value to obj?
02/02/2010 (1:26 pm)
Hi guys! I’m implementing this resource for T3D 1.1 Alpha and I’m having a problem. I keep getting this error every time I try to play a level: “Unhandled exception at 0x106319f7 (myproject_DEBUG.dll) in myproject_DEBUG.exe: 0xC0000005: Access violation reading location 0x00000000”. The error occurs in this part of the code in gameConnection.cpp:if (bstream->readFlag())
{
S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
GameBase* obj = dynamic_cast<GameBase*>(resolveGhost(gIndex));
setSlaveObject(i,obj); //setSlaveObject(obj);
obj->readPacketData(this, bstream);
}
From what I understand the problem is that dynamic_cast is always returning a NULL value and assigning it to obj so the program fails every time it tries to execute obj->readPacketData(this, bstream);. Anyone has an idea of what could be the reason why is always assigning a NULL value to obj?
#10
I think you can fix this by finding this block in server/game.cs:
And add this right after it:
This will force the slave object to be ghosted to the client that'll control it.
02/11/2010 (6:16 pm)
This means resolveGhost() failed, which means the object you're setting as slave wasn't ghosted yet. I remember this was a limitation of the resource back then: I couldn't figure out how the control object was automatically ghosted.I think you can fix this by finding this block in server/game.cs:
// Player 1 setup... %trans = getWord(%spawnPoint, 0) + 2 SPC getWord(%spawnPoint, 1) SPC getWord(%spawnPoint, 2); %player1.setTransform(%trans); %player1.setShapeName(%this.name);
And add this right after it:
%player1.scopeToClient(%this);
This will force the slave object to be ghosted to the client that'll control it.
#11
I've ported it to TGEA 1.8.2.
Thanks.
05/31/2010 (7:47 pm)
Hi guys, I'm having the same problem with Will Hankinson whereby the player is jumping up and down. Anyone know how to solve this problem ?I've ported it to TGEA 1.8.2.
Thanks.
#12
hey,manoel can not u do this?
08/20/2011 (4:49 am)
It will be Awesome if someone port it for t3d 1.1.hey,manoel can not u do this?

Torque 3D Owner Phil Carlisle
Phil.