Sign in to follow this  
caymanbruce

How to write robust, efficient and well structured client interpolation code?

Recommended Posts

caymanbruce    209

I have implemented client interpolation and it works well. But I don't like my current structure. It looks really ugly and created too many temporary objects, besides that it is really hard to maintain the code.

I am not going to show too many logic here as it is very tightly coupled with other parts of my game. Note that my code is written in javascript but if you show me some direction in generic language or C++ that's OK too because I think the logic should not be too different.

In my game I have hundreds of players and other NPCs, and every network update I get a timestamp. I just bundle them up in a very big state object. Let's call it "currentRenderState", similarly I have "previousRenderState" and "futureRenderState", which means the state I receive in last update and the state I receive in current update. I am going to interpolate from "previousRenderState" to "futureRenderState". The interpolation result will be stored in "currentRenderState". If next update state hasn't arrived and the player state hasn't reached "futureRenderState" I will interpolate from "currentRenderState" to "futureRenderState".

 

So my state object contains a lot of information.

state = {
  timestamp,
  allPlayerStates,
  allNPCStates
}

 

Here "allPlayerStates" is a very big object too. It contains all the states of all players and each player contains dozens or even hundreds of properties.

Every time I interpolate I need to clear the object in currentRenderState, also I need to reference allPlayerStates and allNPCStates in "previousRenderState" and "futureRenderState" to get one of the individual state and interpolate it. At the end of the interpolation I create a very big temporary state object and put the interpolation value into this state object and assign to "currentRenderState". Then in the interpolation code I loop through the "allPlayerStates" of "currentRenderState", and assign the value to each player on client side. Also I loop through "allNPCStates" to assign the value to each NPC on client side. This logic works, but I feel tiresome each time I read through my code. Is there a better way to organise my interpolation code, and probably make it more efficient too?

Edited by caymanbruce

Share this post


Link to post
Share on other sites
Kylotan    9857

Looks like you're storing your state in the inverse way to how I'd store it.

I'd have each object responsible for its own state, and its past states. I can then ask each object "what is your state at time T" and it can produce an interpolated or extrapolated state accordingly.

However, you don't always need to store the current, interpolated state for an object. If I'm just using this system to decide where to render something on screen, I can just ask for that value to be produced when necessary.

It's also usually not necessary to explicitly label states as current/previous/future. States have timestamps, and you have the current time (or at least, the notional time that you intend rendering), and you can interpolate between whichever 2 states are either side of the current time to decide what to render.

Finally, treating NPC states and player states separately is making extra work for yourself, so why bother?

Share this post


Link to post
Share on other sites
caymanbruce    209
4 minutes ago, Kylotan said:

Looks like you're storing your state in the inverse way to how I'd store it.

I'd have each object responsible for its own state, and its past states. I can then ask each object "what is your state at time T" and it can produce an interpolated or extrapolated state accordingly.

However, you don't always need to store the current, interpolated state for an object. If I'm just using this system to decide where to render something on screen, I can just ask for that value to be produced when necessary.

It's also usually not necessary to explicitly label states as current/previous/future. States have timestamps, and you have the current time (or at least, the notional time that you intend rendering), and you can interpolate between whichever 2 states are either side of the current time to decide what to render.

Finally, treating NPC states and player states separately is making extra work for yourself, so why bother?

Thank you for your input. I have thought about putting the interpolation logic inside the loop of the player list. But maybe I am just being lazy not to test out if that works better or not because changing my interpolation code is really a headache. It can take up a day or even more. And it usually breaks my game and takes me even more time to debug.

The main reason of separating NPC and player states is that they are different thing. They behave totally diffenrently and NPC has only a few properties versus player which has a lot more properties.

Quote

However, you don't always need to store the current, interpolated state for an object. If I'm just using this system to decide where to render something on screen, I can just ask for that value to be produced when necessary.

In my game, it works like this: (Pseudo code, not in interpolation, but in the code when client receives an update)

previousRenderState = futureRenderState;

if (currentRenderState exists AND currentRenderState.timestamp > previousRenderState.timestamp) {

    previousRenderState = currentRenderState;

}

futureRenderState = (incoming update state values...);

So sometimes I need to assign the current state to the "previousRenderState" for better interpolation.

Share this post


Link to post
Share on other sites
Kylotan    9857

Ok, your method of interpolation is the simplest one and does require storing the current interpolated state. That's fine. I'd still store it on a per-object basis.

If you want a more concrete example of how to make your code look less "tiresome" then we're going to have to see the code.

Share this post


Link to post
Share on other sites
caymanbruce    209
7 minutes ago, Kylotan said:

Ok, your method of interpolation is the simplest one and does require storing the current interpolated state. That's fine. I'd still store it on a per-object basis.

If you want a more concrete example of how to make your code look less "tiresome" then we're going to have to see the code.

I agree with you too storing it on a per-object basis breaks it down into smaller unit so it's easier to debug. Unlike what I am doing now every time I debug or change some data structure it is a nightmare. But I still need to fix my code to adapt to the new structure.

Share this post


Link to post
Share on other sites
caymanbruce    209

@Kylotan But I am very curious though. How not to store the current interpolated state? You see, one of the biggest headaches I have when changing my code is that I have to assign my "currentRenderState" to the "previousRenderState" (outside of interpolation). This results in copying a very complicated object into another object, value by value, and I can't copy its reference otherwise weird things would happen and those states will become unstable because changing one state can affect another. 

Share this post


Link to post
Share on other sites
Kylotan    9857

If you simply store states as they come in, you can interpolate between them as necessary based on the current time. The current state is just a weighted average of a past state and a future state which is usually trivial to calculate once per frame for display purposes and then throw away. I explained this to you in a similar thread back in March. You have chosen a different route where, once you receive a new state update, you start interpolating towards that immediately, which requires that you assume your currently interpolated state is the starting point. (You still don't strictly need to be storing that interpolated state - you only need to 'commit' it to the 'previous' state when you get a new one to replace the 'future' state.) Both routes are valid, having different pros and cons, and I've implemented each.

You might also consider that if state copying is too expensive for you, it might mean you are copying too much state. Many games only ever need to store position and orientation for these purposes. Others might add velocity to that, or maybe the current animation(s) and frame number(s). It's still only a very small amount per entity.

Share this post


Link to post
Share on other sites
caymanbruce    209
Quote

If you simply store states as they come in, you can interpolate between them as necessary based on the current time. The current state is just a weighted average of a past state and a future state which is usually trivial to calculate once per frame for display purposes and then throw away. I explained this to you in a similar thread back in March. You have chosen a different route where, once you receive a new state update, you start interpolating towards that immediately, which requires that you assume your currently interpolated state is the starting point. (You still don't strictly need to be storing that interpolated state - you only need to 'commit' it to the 'previous' state when you get a new one to replace the 'future' state.) Both routes are valid, having different pros and cons, and I've implemented each.

Sorry I went the other route because I felt that was enough for my game and easier to implement. But what does 'commit' mean?

Quote

You might also consider that if state copying is too expensive for you, it might mean you are copying too much state. Many games only ever need to store position and orientation for these purposes. Others might add velocity to that, or maybe the current animation and frame number. It's still only a very small amount per entity.

Apart from those values I have "alive" to check if player is alive, and "username" because I need to show it on screen, and the player's "score". The player's position is not just x and y. It has many parts moving after it so I need to pass those position values too.

Share this post


Link to post
Share on other sites
Kylotan    9857

By 'commit' in this situation, I just meant 'store into previous state'. Because the interpolated value can just be a transient, calculated value, used merely for display. It's only when you receive a new state and need to treat the current state as the beginning of the interpolated range that you would actually need to store it.

It sounds to me like your state is not really all that large, and you're including things that shouldn't be in there anyway. Username is usually completely static, so it doesn't need to be in there. You can't interpolate it anyway. Dead or alive is certainly state, but you can't interpolate that, so again, it doesn't need to be in this specific data structure. I can't comment on position because for most MMOs this is literally one vector or matrix - if you have something more complex, it might well require a lot more state, or, it might just require a more sensible way of storing and deducing it.

Share this post


Link to post
Share on other sites
caymanbruce    209

@Kylotan I might have been too lazy to split those properties such as "alive" and "username". But I have this concern: because I am putting every state into a big object, when I query a state from a list of players or NPCs I can quickly get the property and display its status. Otherwise I will have to maintain and query another state list to get these properties. And if this other state list doesn't have the same player IDs with the current state  I am in big trouble.

Back to 'commiting' the current state. I think you mean recalculate it when I need to store it to the "previousRenderState"? Would that be doing extra calculation when that situation comes up?

Edited by caymanbruce

Share this post


Link to post
Share on other sites
Kylotan    9857

Sorry, I don't understand what you are talking about with the state lists.

Yes, I mean recalculate it. Typically this is a couple of multiplications and a few additions; the sort of thing a modern computer does billions of times per second normally.

Share this post


Link to post
Share on other sites
caymanbruce    209

@Kylotan I mean I put those extra properties in because I want to query it directly from "currentRenderState" when I want to display or use them on client. But if I don't put those properties into "currentRenderState" I need to maintain a separate data structure that only contains those values. That will be a lot of work when adding or deleting values(player status) in it.  I guess that will be fine?

Edited by caymanbruce

Share this post


Link to post
Share on other sites
Kylotan    9857

It shouldn't be a lot of work. You don't need everything about one entity to live in one massive lump of data anyway. That's never going to scale well. Separate the data you need to interpolate from the data you don't.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By CoffeeAddict19
      I was looking for an opportunity to learn/improve skills so I wrote this simple Tic-Tac-Toe game.
      I have written Python code for simple network tests and know enough JavaScript to get by. Still not certain on fine details though, particularly what subtle (or not) best practices I am likely missing.
      Code review, testing and advice on how to improve would be appreciated.
      Code is running on PythonAnywhere here:
      http://coffeeaddict.pythonanywhere.com/tictactoe
      Code is here on GIT:
      https://github.com/coffeeaddict19/tictactoe
      The three pieces are:
      JavaScript and Markup: tictactoe_page.html
      Bottle Framework Implementation: tictactoe_bottle.py
      Python Game Logic: tictactoe_logic.py
      If you look closely at the game logic the AI is...primitive. Researching MinMax to improve it is the next thing on list but in my experience if I wait for perfection I never get anything done.
      Anyway...how can I improve this game and this code?
      Thanks,
      John
    • By suerozcelik
      Hi everyone, My name is Arda Süer, i’m a game developer and producer of Pocket Universe : Create Your Community. Pocket Universe is on pre-order and soon the early access to Steam. I need your help and I want to introduce you to my game. Please read the game story and website content etc. If you have any suggestions tell us and we can develop. Example:"Story is good but you need more faction","You need add bla,bla to the game". Anyway I will put links here to help you to understand Pocket Universe. Story : http://www.pocketuniversegame.com/?page_id=7 Features : http://www.pocketuniversegame.com/?page_id=180 Factions : http://www.pocketuniversegame.com/?page_id=54 Press Release : http://www.pocketuniversegame.com/?page_id=237 If you want to help more, please buy my game Kinguin : https://www.kinguin.net/category/38680/pocket-universe-create-your-community-pre-order-steam-cd-key/ G2A : https://www.g2a.com/pocket-universe-create-your-community-steam-key-global-i10000070716001 Press Relase.rtf
    • By purplecheese44
      I dont really know exactly how to explain my issue so i will do my best. I'm looking to make an html game with javascript. I want to know how to setup an environment that has a big "world" but what you can see is only a small part of it as you move around. If you have ever played agar.io thats what i mean. Feel free to ask questions.
    • By harentius
      Hello everyone!
      Like it often happens, I am software developer (not gamedev), and once I got an idea
      And I try to implement it.
      Idea was to create game, where main character is a developer. And after some occasion, he turns in mysterious world, where developers horrors/memes becomes true.
      For example, primary weapon is a crutch, player collects them. Player can use it for melee attack, or throw them for distant attack.
      Also player collects coffee to increase health.
      Basic enemies are bugs (literally), spaghetti monster, deadline, etc.
      Actually there are lot of ideas which can be implemented (such as skills, debuffs, selecting speciality for dev-player, which influences set of skills and so on), question only in finding free time for it)
      I plan multiple locations, starts with office, then city, then some nature place.
      I decided to use platformer genre, pixel art style (I considered it as easiest to implement. Problem that I don't have any experience in gamedev or creating art, drawing, etc)
      Here is brief video for 0-level.
      I reimplemented basic idea several times...
      I will very appreciate any opinion about this idea. Does it have any chance? Especially with so horrible design.
      Or may be you have some crazy ideas of game items?
      Thanks.
       
    • By hotsaucebg3
      Hello, what I need to achieve is very simple HTML5(and Jquery)  draggable tiled game map with players on it(for my mmorts), like the ones below. I'm not asking for someone to make it for me, just need some directions where to start and what to use(since my game has database should I use it for the map too?). Also I need to click on players's castles, but I think in canvas this is not possible.
      I want the map to be big, about 25000x25000px, but rendering that big image all at once would not be the way, obviously.
      EDIT: Can someone move this topic to beginners section, i think posted it in wrong place.


  • Popular Now