Game Development Community

Player Speeds / Stuck

by Xavier "eXoDuS" Amado · in Torque Game Engine · 06/04/2002 (9:30 am) · 20 replies

I made a little modification to the player's movement, so instead of using the value of the datablock it uses a member variable which is accessed via a function, like this:

if( mWaterCoverage >= 0.9 )
  walkSpeed = getMax(getUwWalkForwardSpeed() * move->y,
              getUwWalkSideSpeed() * mFabs(move->x));

But now when i go in game the player moves in a jerky way, not smoothly, it's like if it gets stuck or something...
Anyone have any ideas?

I did the corresponding networking send of the new speeds too...

#1
06/04/2002 (3:33 pm)
I did the same thing in my resource here.
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2698

I had that jerky problem originally and it is usually due to a sync problem between server and client.
#2
06/04/2002 (4:42 pm)
Yes you told me that in your email, but i checked with your code and i dont see any noticeable differences... :\
#3
06/04/2002 (11:15 pm)
I would check your code to check that it isnt after something like

if(isServerObject())

or something like that. Them things can ruin your day
#4
06/05/2002 (8:55 am)
Here's my code for sending the data, this is in Player::packUpdate :

if(stream->writeFlag(mask & SpeedMask))
{
   stream->writeFloat(mWalkForwardSpeed,5);
   ...
}

And this is in setSpeeds() (my own function for changin the speeds:

if(isServerObject())
{
   setMaskBits(SpeedMask);
}

Anyway, if i try using this with just a static value defined in the constructor (ie, without changing the values on the fly) it doesnt work either, but i'm guessing that both client and server get the values defined in the constructor by default?
Shouldn't that work?
#5
06/05/2002 (1:07 pm)
This looks ok, I am guessing by your explaination that the issue is in the player movement function.

A good test method is to put in a console output of some data so that you can see what is happening whilst in game.

If there is a differnce between the client and server values, then you will be able to see it
#6
06/05/2002 (1:43 pm)
I dont understand why the player movement function... what i tried doing is simply replace the datablock value with a fixed value (float) and it still had the jerky movement... wihtout sending any data or anything... just replaced datablock with a float value.
#7
06/05/2002 (3:45 pm)
Imagine if you had something like this

mValue = 5;

if(isServerObject())
   mValue = 10;

mSpeed *= mValue;

You can se how a sync problem could arise between the client and the server in this kind of instance. Obviously your situation is more complex but I think it will be along these lines.
#8
06/05/2002 (4:05 pm)
mmm...
but the movement functions aren't under any if isServerObject()

if( mWaterCoverage >= 0.9 )
  walkSpeed = getMax(getUwWalkForwardSpeed() * move->y,
              getUwWalkSideSpeed() * mFabs(move->x));
else
  walkSpeed = getMax(getWalkForwardSpeed() * move->y,
              getWalkSideSpeed() * mFabs(move->x));

That's the code that i changed, nothing else, and that's not only for the server object.. it's for both...
#9
06/05/2002 (10:34 pm)
well,
you have a sync problem there between the client and server somewhere.

I suggest outputting values to the console for both the sevrer and client and you will see if your data is updating correctly or not.

That is the only way you will narrow down where the problem is.
#10
06/06/2002 (1:17 pm)
Well, it turned to be that the sync problem was caused by the use of WriteFloat() and readFloat().
I replaced these with ints instead and it works perfectly, no sync error. Using the float one i always got a speed of 0.79677 on the client.

Also, what's the number for? (in your example it's a 5). I think it's an Id to identify which variables are the ones being sent?
#11
06/06/2002 (1:33 pm)
Yes, that is a sync error.
Sync error = different value on client and server.

The values of 5 and 10 I had were just random values to point out that there can be a difference between the two.

Good that you solved it :)
#12
06/06/2002 (1:52 pm)
Lol, i didnt meant that '5' ... i meant the 5 used in the writeInt() commands... after the variable there's a 5 number... is it an id?

Also i didnt solve my problem... cause i need to use floats :\
#13
06/06/2002 (6:07 pm)
5 is the number of bits used to send the value in binary
#14
06/07/2002 (5:19 am)
I see, and what does it depend on? How do i know if 5 is ok?
#15
09/22/2002 (1:54 pm)
Can either of you guys suggest a good place in c++ code for a call to setMaxSpeed that initially populates the speed from the datablock? I tried the end of Player::onAdd, but if I adjusted the speed later it got out of sync on client and server.

It works if I make the call from script after the player is created, but I want the c++ code to do it.
#16
09/22/2002 (6:48 pm)
Well... the unpackUpdate function is executed when the object is first created... so you could make it read the value from the datablock and set it up... ummm... I can't remember how i've done this... lemme look it up in my code...

*looks up*

Well... what i did is add a call to updateSpeed() in unpackUpdate... so it gets called everytime a modification to the speed is done... since all masks are set when the object is created it is also called by then.
In this function i get the value of the datablock and do the modifications relative to the value in the datablock
for example:

S32 runspeed = mDatablock->mRunspeed;
mPlayerRunSpeed = runSpeed - speedModifier;

That's in my case, not sure what kind of modifications you are doing to the speed....
#17
09/22/2002 (8:24 pm)
Thanks. I actually ended up restructing my code so that the initial call to set the speed is not necessary most of the time. But basically I'm doing the same thing as you which is modifying a particular player's speed on the fly.

Now I just need to figure out that weird writeFloat function :)
#18
09/23/2002 (8:23 am)
You mean the problem I had with it?
Well if you figure that out make sure to drop me a line :)
#19
09/23/2002 (5:50 pm)
With writeFloat, part of the problem is that it doesn't do what you expect: i.e. write an arbitray float. It expects values between 0 and 1 (or between -1 and 1 for writeSignedFloat). Then, you have to choose the number of bits wisely so that your float actually gets passed intact. I glanced at the implementation in core/bitStream.cc, but it looked pretty involved. I'll need to take another look.

Anyway, you can still write floats just by using the regular write and read functions, e.g.:

F32 foo = 1.2;
stream->write(foo);
stream->read(&foo);

This works but it probably less efficient since it has to transmit all 32 bits of the float (although there might be some compression going on to reduce this).
#20
09/23/2002 (7:19 pm)
Thanks a lot John, please post any new news you get about this writeFloat function :)