Gamestudio Links
Zorro Links
Newest Posts
Newbie Questions
by AndrewAMD. 12/05/23 10:56
Zorro Trader GPT
by TipmyPip. 12/04/23 11:34
Square root rule
by Smallz. 12/02/23 09:15
RTest not found error
by TipmyPip. 12/01/23 21:43
neural function for Python to [Train]
by TipmyPip. 12/01/23 14:47
Xor Memory Problem.
by TipmyPip. 11/28/23 14:23
Training with command line parameters
by TipmyPip. 11/26/23 08:42
Combine USD & BTC Pairs In Asset Loop
by TipmyPip. 11/26/23 08:30
AUM Magazine
Latest Screens
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Tactics of World War I
Who's Online Now
6 registered members (AndrewAMD, alibaba, fairtrader, ozgur, TipmyPip, Quad), 622 guests, and 1 spider.
Key: Admin, Global Mod, Mod
Newest Members
fairtrader, hus, Vurtis, Harry5, KelvinC
19019 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 1 of 2 1 2
some multiplayer thoughts #400063
04/25/12 10:59
04/25/12 10:59
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline OP
Senior Expert
Superku  Offline OP
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
I was asked about some tips for client-side multiplayer movement and decided to post my thoughts here, maybe someone will find this useful. The following text and code is taken from an old Skype conversation:


at first I only tried to update xyz and pan 8times a second or so, and interpolate the rest. but I didn't get it as smooth as it should be and it used too much traffic bandwidth
so I've implemented a variable/ skill like my.keys and set its bits according to the player input, f.i. as follows:

my.keys = key_w + key_s*2 + key_a*4
if(my.keys != my.old_keys)
{
my.old_keys != my.keys;
send_skill(my.keys,SEND_ALL);
}

you see, the skill only gets send when the player presses a different button/ releases a button.
the server transmits obviously the skill to all other clients.
then in the entity action the skill is used to move the client (same action on client and server), f.i.
if(my.keys & 4) move left
as you turn the player with the mouse and the pan value probably almost changes every frame, you cannot do it the same way. instead, I use something as follows:

my.pan_update = maxv(my.pan_update -time_step,0);
if(!my.pan_update && abs(ang(my.old_pan-my.pan)) > 1)
{
my.pan_update = 2;
my.old_pan = my.pan;
send_skill(my.old_pan,SEND_ALL); // do not send my.pan here
}

the code updates the old_pan skill at most 8 times a second and only when the pan changes significantly
(on the sever you have to transmit the skill of course to the other players, too)
in the player-animation (of entities that are not controlled by the player), you simply write something as follows:

my.pan += ang(my.old_pan-my.pan)*time_step;
this should almost be sufficient to have a smooth multiplayer experience.
the problem is, because of the approximations, after a little time the players can be on different locations on different pcs. that's why you have to send the xyz position from time to time to the other clients and smoothly blend between the two positions.
when you do that smoothly, you will run into another problem.
when you simply move the entity to let's say my.dplay_x (that's a skill vector), in detail:

my.pos_update = maxv(my.pos_update -time_step,0);
if(!my.pos_update && vec_dist(my.x,my.dplay_x) > 8)
{
vec_set(my.dplay_x,my.x);
my.pos_update = 8;
send_skill(my.dplay_x,SEND_ALL | SEND_VEC);
}
...

if( vec_dist(my.x,my.dplay_x) > 8)
{
my.x += (my.dplay_x-my.x)*0.5*time_step;
my.y += (my.dplay_z-my.z)*0.5*time_step;
my.z += (my.dplay_z-my.z)*0.5*time_step; // you should calculate the z-position with c_trace, not with such a formula
}

with this smooth alignment, the player will not be able to move forward until he reaches the position
so you have to calculate a direction vector instead when you receive a new dplay_x position and apply the force over a time:

vec_diff(temp,my.dplay_x,my.x);
my.skill1 = 4;
while(my.skill1 > 0)
{
move entity by temp*time_step/4;
my.skill1 -= time_step;
wait(1);
}

this should correct the position pretty accurately, and it took a while to come up with this idea


EDIT: When you use the native multiplayer engine, make the following settings:

dplay_entrate = 100;
dplay_smooth = 0;
dplay_localfunction = 2;

In entity-functions:
while(my.client_id < 0) wait(1);
my.smask |= NOSEND_ALPHA | NOSEND_AMBIENT | NOSEND_ORIGIN | NOSEND_ANGLES | NOSEND_ATTACH | NOSEND_COLOR | NOSEND_FLAGS | NOSEND_FRAME | NOSEND_LIGHT | NOSEND_SCALE | NOSEND_SKIN | NOSEND_SOUND;


Last edited by Superku; 04/25/12 11:21.

"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends
Re: some multiplayer thoughts [Re: Superku] #400069
04/25/12 12:28
04/25/12 12:28
Joined: Nov 2011
Posts: 274
de
lemming Offline
Member
lemming  Offline
Member

Joined: Nov 2011
Posts: 274
de
Thanks Superku for the hints!

In my network code I use another invisible entity for the player that recieves the position from the server. The position is then always slightly corrected towards the invisible entity (i use vec_lerp). But your solution seems less complex to me.

Re: some multiplayer thoughts [Re: lemming] #400076
04/25/12 13:17
04/25/12 13:17
Joined: May 2008
Posts: 2,113
NRW/Germany
alibaba Online
Expert
alibaba  Online
Expert

Joined: May 2008
Posts: 2,113
NRW/Germany
At first itīs a great idea!
But if you use this in a fast paced shooter game and the keys are pressed a lot, then wouldnīt this lead to high traffic as well?


Professional Edition
A8.47.1
--------------------
http://www.yueklet.de
Re: some multiplayer thoughts [Re: alibaba] #400081
04/25/12 15:10
04/25/12 15:10
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline OP
Senior Expert
Superku  Offline OP
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
No, I think this should be fine (and it has proven to keep the overall traffic low in my experiments).


"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends
Re: some multiplayer thoughts [Re: Superku] #400085
04/25/12 15:45
04/25/12 15:45
Joined: May 2008
Posts: 2,113
NRW/Germany
alibaba Online
Expert
alibaba  Online
Expert

Joined: May 2008
Posts: 2,113
NRW/Germany
Oh cool!
I'll try to implement it then, thanks you very much!
You contribute a lot, thank you!


Professional Edition
A8.47.1
--------------------
http://www.yueklet.de
Re: some multiplayer thoughts [Re: alibaba] #400099
04/25/12 19:19
04/25/12 19:19
Joined: May 2009
Posts: 5,367
Caucasus
3run Online
Senior Expert
3run  Online
Senior Expert

Joined: May 2009
Posts: 5,367
Caucasus
* removed


Looking for free stuff?? Take a look here: http://badcom.at.ua
Support me on: https://boosty.to/3rung
Re: some multiplayer thoughts [Re: 3run] #400121
04/26/12 06:10
04/26/12 06:10
Joined: May 2009
Posts: 5,367
Caucasus
3run Online
Senior Expert
3run  Online
Senior Expert

Joined: May 2009
Posts: 5,367
Caucasus
* removed


Looking for free stuff?? Take a look here: http://badcom.at.ua
Support me on: https://boosty.to/3rung
Re: some multiplayer thoughts [Re: 3run] #400124
04/26/12 08:13
04/26/12 08:13
Joined: Nov 2011
Posts: 274
de
lemming Offline
Member
lemming  Offline
Member

Joined: Nov 2011
Posts: 274
de
I'm not familiar with the acknex net code, but you should only update the position directly (send dplay) as a server, not as client. On both sides you move the same way with the inputkeys given, but on the server you send position updates if the client "runs away".

Re: some multiplayer thoughts [Re: lemming] #400129
04/26/12 08:46
04/26/12 08:46
Joined: May 2009
Posts: 5,367
Caucasus
3run Online
Senior Expert
3run  Online
Senior Expert

Joined: May 2009
Posts: 5,367
Caucasus
send_all makes the trick if I'm not mistaken, manual says that only server uses it. But I might be wrong cause I'm new with multiplayer stuff.


Looking for free stuff?? Take a look here: http://badcom.at.ua
Support me on: https://boosty.to/3rung
Re: some multiplayer thoughts [Re: 3run] #400150
04/26/12 14:06
04/26/12 14:06
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline OP
Senior Expert
Superku  Offline OP
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Originally Posted By: 3run
Code:
my.pan_update = maxv(my.pan_update - time_step, 0);
if(!my.pan_update && abs(ang(my.old_pan - my.pan)) > 1)
{
	my.pan_update = 2;
	my.old_pan = my.pan;
	send_skill(my.old_pan, SEND_ALL); // do not send my.pan here
}

// for visual rotation:
my.pan += ang(my.old_pan - my.pan) * time_step;


Yes, but keep in my that you only execute the last line of code on the clients that are not controlling the entity.

Quote:
then, on the machine which doesn't own created entity, we move it like this:
Code:
if(vec_dist(my.x, my.dplay_x) > 8)
{ 
	my.x += (my.dplay_x -my.x) * 0.5 * time_step;
	my.y += (my.dplay_y - my.y) * 0.5 * time_step;
	my.z += (my.dplay_z - my.z) * 0.5 * time_step; 
}


No, this was a (misleading) example how you should not do it, see my first post for a reason. Instead, only use the "counter" while loop method:

Originally Posted By: 3run
Code:
vec_diff(temp, my.dplay_x, my.x);
my.counter = 4;
while(my.counter > 0)
{
	temp.x = time_step / 4;
	temp.y = time_step / 4;
	temp.z = time_step / 4;
	c_move(my, nullvector, temp, GLIDE);
	my.counter -= time_step;
	wait(1);
}



Right now this does not make a lot of sense (no offense), try something as follows instead:

Code:
void player_interpolate_move()
{
	VECTOR temp, move_vec;

	proc_kill(5);
	vec_diff(move_vec,my.dplay_x,my.x);
	my.counter = 4;
	while(my.counter > 0)
	{
		vec_set(temp,move_vec);
		vec_normalize(temp,0.25*time_step);
		c_move(my, nullvector, temp, IGNORE_SPRITES | IGNORE_MODELS | IGNORE_WORLD);
		my.counter -= time_step;
		wait(1);
	}
}

void player_interpolate()
{
	if(my.dplay_x || my.dplay_y || my.dplay_z)
	{
		player_interpolate_move();
		vec_set(my.dplay_x,nullvector);
	}
	my.pan += ang(my.old_pan-my.pan)*0.5*time_step;
}



Then your player code could/ should like this:

Code:
void player_interpolate_move()
{
	VECTOR temp, move_vec;

	proc_kill(5);
	vec_diff(move_vec,my.dplay_x,my.x);
	my.counter = 4;
	while(my.counter > 0)
	{
		vec_set(temp,move_vec);
		vec_normalize(temp,0.25*time_step);
		c_move(my, nullvector, temp, IGNORE_SPRITES | IGNORE_MODELS | IGNORE_WORLD);
		my.counter -= time_step;
		wait(1);
	}
}

void player_interpolate()
{
	if(my.dplay_x || my.dplay_y || my.dplay_z) // you'd better use another skill here like my.dplay_do_interpolation or something like that and reset it after the function call below
	{
		player_interpolate_move();
		vec_set(my.dplay_x,nullvector);
	}
	my.pan += ang(my.dplay_pan-my.pan)*0.5*time_step; // better use a different skill than old_pan, otherwise it gets difficult to transmit the information from one client to the server and to a second client
}

void player_input()
{
	my.keys = key_w + key_s*2 + key_a*4 + key_d*8;
// change pan here, too
}

void player_move()
{
	move (using my.keys) and animate;
}

void player_update()
{
	update my.keys, my.dplay_pan and position
}

action act_player()
{
	while(my.client_id < 0) wait(1);

	my.smask |= NOSEND_ALPHA | NOSEND_AMBIENT | NOSEND_ORIGIN | NOSEND_ANGLES | NOSEND_ATTACH | NOSEND_COLOR | NOSEND_FLAGS | NOSEND_FRAME | NOSEND_LIGHT | NOSEND_SCALE | NOSEND_SKIN | NOSEND_SOUND;

	while(1)
	{
		if(my.client_id == dplay_id) player_input();
		else player_interpolate();
		player_move();
		if(my.client_id == dplay_id || connection != 2) player_update();
		wait(1);
	}
}



Last edited by Superku; 04/26/12 14:06.

"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends
Page 1 of 2 1 2

Moderated by  HeelX, Spirit 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1