Game Development Community

Movement speeds per player

by Keith "The Dip" Wagner · in Torque Game Engine · 02/10/2005 (8:56 pm) · 5 replies

This is continuing from a thread here.

I want players' movement speeds set differently depending on the inventory they have equipped. I have modified the code in player.h and player.cc to add a new variable (in this case swimSpeed), and initialize it in the player constructor with a value 1.0. I created a player::initPersistentFields and put swimSpeed in there. I also added a stream->read and stream->write to player::readpacketdata and player::writepacketdata, respectively.

Now, when I create a new player in game.cs:
%player = new Player() { ... };
I can see the swimSpeed variable and echo it just fine.
However, player::updateMove (in player.cc) gets called twice.

(breaking thought, tried some things)

I think I figured out what's been driving me nuts! If I have the code like this:
player.cc
void Player::updateMove(const Move* move)
{
....
     if (mWaterCoverage >= 0.8f)
     {
       if (move->y > 0) // Forward
         Con::executef(mDataBlock,3,"swim",scriptThis());
       else if (move->y < 0) //Backward
         Con::executef(mDataBlock,4,"swimbackward",scriptThis());
    }
}

player.cs
function Armor::swim(%this, %obj)
{   
  %speed = 2 * %obj.swimSpeed;
  echo("speeeed: " @ %speed);
  if (%obj.getMountedImage(4).frozen) return;
  %position = %obj.getTransform();
  %pos = getWords(%position, 0, 2);
  %eye = %obj.getEyeVector();
   
  %xx = getWord(%eye, 0) * %speed;
  %yy = getWord(%eye, 1) * %speed;
  %zz = getWord(%eye, 2) * %speed;
   
  %vec = (%xx SPC %yy SPC %zz);
   
  %obj.applyImpulse(%pos, VectorScale(%vec, %obj.getDataBlock().mass));
}

It doesn't work. The first time updatemove is called, swim gets swimSpeed correctly from %obj. The second time, it does not. Net result, the player 'jumps' forward instead of moving smoothly.

This code:
player.cc
void Player::updateMove(const Move* move)
{
....
     if (mWaterCoverage >= 0.8f)
     {
       F32 tempSwimSpeed;
       if (move->y > 0) // Forward
       {
         tempSwimSpeed = 2 * swimSpeed;
         Con::executef(mDataBlock,4,"swim",scriptThis(), Con::getFloatArg(tempSwimSpeed));
       }
       else if (move->y < 0) //Backward
       {
         tempSwimSpeed = 0 - swimSpeed;
         Con::executef(mDataBlock,4,"swimbackward",scriptThis(), Con::getFloatArg(tempSwimSpeed));
       }
     }
}
player.cs
function Armor::swim(%this, %obj, %speed)
{   
  echo("speeeed: " @ %speed);
  if (%obj.getMountedImage(4).frozen) return;
  %position = %obj.getTransform();
  %pos = getWords(%position, 0, 2);
  %eye = %obj.getEyeVector();
   
  %xx = getWord(%eye, 0) * %speed;
  %yy = getWord(%eye, 1) * %speed;
  %zz = getWord(%eye, 2) * %speed;
   
  %vec = (%xx SPC %yy SPC %zz);
   
  %obj.applyImpulse(%pos, VectorScale(%vec, %obj.getDataBlock().mass));
}

Works correctly. Both times updatemove is called, swim gets the correct swimSpeed. (2.0 in this case). Player moves smoothly.

Why does the second one work and not the first? I know that if I added the swimspeed variable to the playerdata class, it would have worked, but it would have modified all players using the same datablock, which is not what I want. caveat: I have not tried the above code in a multiplayer environment, changing the variable between players, so I am not 100% sure this is any different from putting it in the playerdata class. But it should be. Testing will happen after work tomorrow. I wanted to get some input on it in the meantime.

edit: rewording

#1
02/12/2005 (6:05 pm)
Well I tried it in a multiplayer environment, and I can't figure out what I'm missing. The host of the game works correctly. The other players do not. Example:
host:
createplayer: this id: 1496
onAdd: obj id: 1510
(%player.swimspeed = 1.5)
client:
createplayer: this id: 1497
onAdd: obj id: 1523
(%player.swimspeed = 0.5)

swimming (2x swimspeed, per my function):
1510's speed: 3
1514's speed: 3
1523's speed: 1
1527's speed: 2

==>1510.dump();
Member Fields:
  dataBlock = "Player7"
  position = "159.652 -26.3391 67.4742"
  rotation = "0 0 1 130.062"
  scale = "1 1 1"
  swimSpeed = "1.5"
Tagged Fields:
  client = "1496"
...

==>1514.dump();
Member Fields:
  dataBlock = "Player7"
  position = "159.652 -26.3391 67.4742"
  rotation = "0 0 1 130.062"
  scale = "1 1 1"
  swimSpeed = "1.5"
Tagged Fields:
(none)

==>1523.dump();
Member Fields:
  dataBlock = "Player1"
  position = "22.4261 26.3692 68.9975"
  rotation = "0 0 1 96.2297"
  scale = "1 1 1"
  swimSpeed = "0.5"
Tagged Fields:
  client = "1497"
...

==>1527.dump();
Member Fields:
  dataBlock = "Player1"
  position = "22.4263 26.3649 68.989"
  rotation = "0 0 1 93.5433"
  scale = "1 1 1"
  swimSpeed = "1"
Tagged Fields:
(none)

Can someone please explain to me why this would happen? What needs to be done in order for a field added to the player (not playerdata) class to be properly synced among all players?
#2
02/12/2005 (6:16 pm)
I've said it a couple of times bud--you need to use packUpdate and unpackUpdate to deliver data for a player object from server (host) to clients.
#3
02/12/2005 (6:59 pm)
Quote:
You also want to update it to the client via pack/unpack

And I misread that, seeing
void Player::writePacketData(GameConnection *connection, BitStream *stream)
and
void Player::readPacketData(GameConnection *connection, BitStream *stream)

instead of
U32 Player::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
and
void Player::unpackUpdate(NetConnection *con, BitStream *stream)

That'll teach me to read carefully!
Trying that now.
#4
02/12/2005 (7:56 pm)
Write/read are for updates for the object the player is controlling. pack/unpack are general purpose.
#5
02/12/2005 (9:13 pm)
I can finally announce success.
Did some more searching on a more general phrase, and found this thread which directed me to this thread, which did exactly what I was trying to do. The differences between mine and theirs was using console functions (which I changed to), and having a bitmask so that only if it was the serverobject would the data be changed. From looking around the packupdate function you may assume that's a no-brainer. Well, I know now, at any rate.

Thanks for the help.