🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

How to make my multiplayer Air Hockey better?

Started by
5 comments, last by hplus0603 3 years, 10 months ago

I've made simple multiplayer web game but don't like how it works. Here.s video example (captured at 85 avg ping) showing what I have.

What I used:

- Super naive client prediction - called so because there is no reconciliation - most of the time players' strikers can't be moved by anything except players themselves

- Interpolation (it's turned off on the attached video because at the current state of the game in combination with prediction it made things look way worse. Without prediction it looks beter input lag is unacceptably big)

I've read some valve wiki articles, Gambetta's articles and some other not so popular sources, which helped to understand general ideas, but I still lack understanding on how to combine various techniques of minimizing delays for players and some implementation details. So here are the questions:

- What is the best way to sync time on client and server and when to start clocks? It's not very important at the current state of the game but I definitely will need to make it precise for more advanced latency-masking techniques. I should measure average ping and then what? Server sends notifications to clients 'start clocking in X ms' based on ping? Should they even start clocking at the same time?

- How to improve user experience for my game? I guess I should probably use extrapolation for puck and lag compensation to avoid situation like at 0:07.

Is interpolation even needed with 60 tickrate for anything with 60 or lower hz screens? I'm not aiming at e-sports level experience and would rather make it feel nicer for 60 hz phone screens

Advertisement

The article: Real Time Multiplayer in HTML5

Run the example from the article: https://battle-world.herokuapp.com/?debug

Source code from the article: https://github.com/ruby0x1/realtime-multiplayer-in-html5

In general, you will not have a great real-time experience over websockets or other TCP-based transport. You should design games that must work in that environment to not require low-latency controls, because it's technically quite challenging to try to reduce the control latency over available channels.

I've heard of people trying to jam game control information into WebRTC transport, which can be UDP based, but I haven't seen anything successful out of such a project yet, and it would certainly require a lot of hard engineering at the browser interface layer to make work, if it works at all.

enum Bool { True, False, FileNotFound };

To solve the problem more fundamentally you need to account for the reality that time is not synchronized.

For this game you can treat the bottom-half synchronized to the blue player and the top half to the pink player.

You have to back calculate in time when the mallet would-have-collided with the puck, accounting for the lag, then fix the position and trajectory of the puck. I would add a little click noise and maybe some graphical flash to distract the player from the puck jumping in position.

- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

@8Observer8 some snippets of that code are really helpful, thanks.

@hplus0603 I don't know nothing about networking so there probably other factors I can't account for, but is 80 ping really that bad for fast-paced games like this to not let me make user experience acceptable?
@Shannon Barber i didn't really understood that part, could you please explain?

For this game you can treat the bottom-half synchronized to the blue player and the top half to the pink player.

also this

a little click noise and maybe some graphical flash to distract the player from the puck jumping in position.

is a very nice idea, do you know any readings about how to fool players for better experience in tricky situations?

How long does it take for the puck to travel from side A to side B when smashed?

If your ping is 80 milliseconds, and the puck travels in, say, 100 milliseconds, you're always going to be 80% out of date.

Generally, the local player will be displayed in a time frame “ahead” of the server, estimated such that the commands from the player will reach the server/other side just ahead of the server actually needing them. Separately, you will know which timestamp the received entities were calculated at; these will be at timestamps “behind” the server as they were sent out at that time and transmission takes time.

Regarding what @shannon barber said: The way “tennis” type games usually work, is that you have two time frames on the local client: “close to me” and “close to others.” When the puck is heading towards me, the puck, will be moved forward in time to my own time frame (which runs ahead of everyone else for obvious reasons); when the puck is heading away, it will be moved backwards in time towards the “others" or “server” time frame. The thinking is that, objects right near me, that I interact with, will be reactive to me, and hopefully nobody else will interact with them, so I don't get a lot of corrections because I extrapolate; once objects are further away, I'm less likely to interact with them, so interpolating based on received “true” data (that is older) is better, to avoid snapping when other people interact with the objects. At there.com we built a system that did this automatically for any physical object built in the system.

The end result is that you get a kind of “doppler” effect of physics – as objects move closer, they “speed up,” because they end up being displayed at closer and closer time frames, so they appear to simulate physics faster than real time; when objects move away, they seem to “slow down” because they get moved into further back time frames and thus appear to display the output of time stamps that advance slower than real time (until they reach the maximum delay, at which point they proceed normally again.)

So, for each simulated entity, you have functions something like:

class Entity {
  // this is the trail of states received from the server/network
  timestamp lastReceivedTimestamp;
  state lastReceivedState;
  timestamp previousReceivedTimestamp;
  state previousReceivedState;

  // this is how the object displays to the screen  
  void displayAtTimestamp(timestamp time);
  
  // you will likely end up needing these in implementation
  timestamp lastDisplayedTimestamp;
  state lastDisplayedState;
};

Now, when the game renders the object, it will provide a “timestamp" to “displayAtTimestamp” that is between previousReceived and lastReceived, for objects that are “far away,” and thus interpolated on the screen. For objects that are near, the “displayAtTimestamp” value will be made to be ahead of lastReceivedTimestamp, so the object will display itself extrapolated.

enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement