• Content count

  • Joined

  • Last visited

Community Reputation

140 Neutral

About simonlourson

  • Rank
  1. Hi.   I'm developing a fast paced networked action game. In my game, the server keeps a circular buffer of past gamestates, so I can replay client input in the past (for client prediction)   My question is, how do i handle object creation in the circular buffer?   For example, let's say the server has received an input from client A, telling it to fire bullets (my bullets are ballistic types, not instantaneous) at frame 10. 3 bullets are created, and I send these objects creation to each of the clients.   When I'll be replaying my circular buffer during the next timestep, those bullets will be re-created, and not necessarily with the same ids, which is a problem, because I don't want to resend the creation of these bullets to each client!   Is my question clear enough ? How can I handle the fact that some actions need to be definitive (object creation), while at the same time replaying my circular buffer of past gamestates according to new user input?
  2. Thank you for the very good advice !
  3. Hi!   I am trying to develop a fast pace networked action game. I've read some articles and tutorial on the subject, and I've come across a problem in my implementation.   I've successfully implemented client side prediction, but I've run into a performance issue.   Both my server and my clients maintain a circular buffer of previous gamestates.   The server has this buffer so it can replay client input that are received late because of lag.   The client has this buffer so it can replay it's input (the ones that have not yet been acknowledged).   Now here comes the performance issue : I am coding in C#, and the way I went about implementing my circular buffer is this:   Each GameState is store into a LinkedList. The first item in the LinkedList is the most recent, the last is the older.   When I need to replay part of my circular buffer, I do it like this :   1) I clone the last GameState. 2) I store the clone into Last.Previous 3) I update Last.Previous   This "works", the client side prediction works flawlessly, my simulation is deterministic, and I the entity I control never "snaps".   However, with all the cloning going on, the c# garbage collector is on it's knees, and it's starting to show!   Is there a best practice (more efficient than what I am doing currently) to implement a circular buffer of past gamestates, and replaying them?
  4. Item system without database software

    Why would you not want to use a DB? There are some very good free ones, PostGre, MySQL, and even Oracle has an express version. You could code something using files, but it would probably end up way slower, and more complicated than using a database. Also, what language are you using?
  5. Best inventory solution

    It seems you did not read my post until the end; quoting myself: Quote:Original post by simonlourson Then you don't have to have a class per different object, of course. Your "Uzi" class would be the same as your "M16" class, with different parameters (a different model, diffrent sprite, different stats (firing rate, damage, and even customized names) So in your case, you would have about 20 different classes, one for each functionality, but these classes can be have different parameters for each instance, wether it is, in my example, a M16, or a Uzi.
  6. Best inventory solution

    Why not use an OO approach? You could have abstract classes like "fruit", "clothes", "weapon", and then derive the class "apple", "banana", "shirt", "shoes" from these. With polymorhism, you could have one "UseItem" function, that coud have different code wether it's a weapon or a fruit. Then you don't have to have a class per different object, of course. Your "Uzi" class would be the same as your "M16" class, with different parameters (a different model, diffrent sprite, different stats (firing rate, damage, and even customized names) Also, use enums, not directly ints for your IDs.
  7. Interpolation vs Client side prediction

    Quote:Original post by fenghus Interpolation for proxies, ie. objects not controlled by the player, is fairly straight forward and it sounds like you've got it covered. Predicting controlled objects is hairier; This is how I do it. At T6 the client receives state T4 from server. It takes state T4 and applies all input entered during T5 and T6 to arrive at state P6. This is what's rendered on the screen (unless we use the technique below). At T7 the client receives state T5 from server. It takes state T5 and applies all input entered during T7 and T7 to arrive at state P7. Unfortunately, it turns out that on the server, the player collided with a newly spawned object. This was (of course) not part of our prediction, so a visible SNAP will occur between P6 and P7. To remedy this, the client will at T7 ALSO keep predicting from T4 (the old server state), applying input from T5, T6 and T7 to arrive at P7v2. Using both P7 and P7v2 we can interpolate for a short period of time between our old prediction and our new (better) prediction, to avoid snapping and instead smoothly going from misprediction to correct prediction. Very helpful post, I implemented your design and it works very well! Problem solved. :D
  8. Interpolation vs Client side prediction

    Quote:Original post by fenghus Run two separate predictions; one based on the latest received server state and another one based on the previous received server state; then just interpolate between the two over some amount of time, to get the final result. The problem when I am doing that, is that when I "interpolate between the two over some amount of time", during that amount of time, I'm not taking into account the client's input anymore, and that looks horrible Maybe I wasn't clear enough in my op, I'll clarify: I have two models to smooth the objects movements and display them on the client. The first one, cubic splines interpolation, I use on all the objects not "owned" by the client. (ie other players). The second one, client side prediction, I use on the object "owned" by the player (the object the player controls). These two models rely on two methods in my implementation : ReceiveUpdate() is called when I receive a message from the server updating the client on a new position. This method is aware of the "old" position, (the position currently displayed on the client), and is also aware of the "new" position (the position we just received). This method can also access an array of the last inputs the user made. Update() is called every frame on the client. This method is aware of how much time has passed since it was last called, and is also aware of the current user input. Here is what I do in both these methods, for my two models: // Cubic splines interpolation: public void Receive() { create cubic spline (using old position and velocity, and new position and velocity) } public void Update() { Move the object along the cubic spline, } // Client side prediction: public void Receive() { Take the received update Replay the x last player inputs, where x is RTT / (average milliseconds per frame) Move the player to this new position (this is where the snaping occur) } public void Update() { Move the player according to his current input } Now, my cubic spline work just fine, even when the objects take an unexpeted turn, because I'm only interpolating between two known updates. The client side prediction also works fine in most cases, because the code for moving the object according to user input is shared by the client and the server. When I just move freely around the map, no snaping occurs. The problem is when the player owned by the client moves in a way I cannot possibly predict, ie because of a collision, explosion, etc. My problem is that if I use interpolation on the object owned by the client, I'm not using the user input to move the object each update anymore, and that defeats the purpose of client side prediction. I'm feeling I'm missing something simple here...
  9. Hi. I am developping an action game to be played over internet. Here's what I have so far: My basic client architecture: Clients send their inputs to the server at 10Htz, server sends updates to the clients at 10htz also. The client interpolates between two frames using cubic splines, and I'm pleased with the results, except that I have to wait a full RTT before an object starts to move when the player presses a button. Now I wanted to implement client side prediction, so I implemented the technique linked in the FAQ to, which is to store an array of the player's last inputs, and replay them when I receive a server update. So for the object controlled by the player, I use client side prediction, and for the other objetcts, I use cubic splines. The problem is when the object controlled by the player takes an "unexpected turn" (ie because of an unpredictable collision), the this object will "snap", because I'm not using the cubic splines smoothing algorithm anymore... I can't quite get my head around somehow mixing those two algorithms. Any insight? [Edited by - simonlourson on August 9, 2010 10:32:04 AM]
  10. Yes, you would need a history of all the objects states. The longer you want to go back, the more memory / cycles you use. However, I understand the "rewinding" approach opens your game to speed hacks. (A hacked client could make the server believe an input was sent at t-20, where it was in fact sent at t-1, thus the object controlled by the hacked client would seem to move faster. For my game, I send inputs at 10Htz, an send updates at the same rate (updates are sent less frequently if the server can't keep up with the upload bandwith). The server handles the input when it receives it, period. This is acceptable however, since the client plays animations (like heat from the engines, play a sound when it fire a weapon) and predict it's movement, so even at 150 RTT, the lag is not really noticeable.
  11. Dead reckoning cubic spline confusion

    Actually, when you use dead reckoning in your application, you do have the two points and the two velocities needed for cubic splines. Lets say object A is part of your simulation. At time t0, you receive an update from the server, saying that A is at position (1 ; 1), and is moving at velocity (0.5 ; 0.5). Using this information, your client will believe that at t1, A is at (1.5 ; 1.5), and at t2, A is at (2 ; 2). Now let's say that between t0 and t2, the player controlling A has taken a sharp turn, and is now at (3 ; 1), and travelling at velocity (2 ; 0). If you receive an update from the server with this new position, you will need the client to move A from (2 ; 2), velocity (0.5 ; 0.5) to (3 ; 1), velocity (2 ; 0). That's your two positions and velocities right there. You could just snap the player to that location, but the result is not very nice looking. Another option is to perform the interpolations described in the article you linked.
  12. I don't even know if it's possible in your language, but ping would be my choice
  13. About the 8 bit channel not being precise enough: I've had this problem as well. I've solved it by multiplying my output texture by a factor: "colorMult" in my HLSL code, then dividing by the same number when "decoding" the texture. This works because most of the time I only have to offset a few pixel, so I'm using only a fraction of the 0->1 range. There you can see what the distortion would look like without that multiplier: Compared to a 5 multiplier: in the first image there is obviously a precision problem, some lines are "doubled". In the second image, you can barely see it. Of course, if the multiplier is too high, at some point the displacement map will become white (Actually, not white, but purple / yellow / turquoise) in some areas, and we'll loose info too. I've found 5 to be a good compromise. Another problem with the multiplier solution is that all the displacement maps must be "recorded" with the same multiplier, otherwise they will not "decode" the same way. I'm still pretty new to this, so I didn't understand your post fully though. Are you talking about alpha blending uv textures with a 0.5 offset? Because with my method, I'm pretty sure the coordinates add up linearly, even when I tint my sprites.
  14. Quote:Original post by snake5 Quote:Normal maps (and the DuDv maps that he started with) can't be additively blended because of the 0.5 offset. From what I can tell, the point of this method is that it supports simple additive blends. They don't need to be blended like that. You can simply blend one normal map on another with 0.5 alpha. And a shader for adding 2 normalmaps (converting to vectors, adding them and converting back) isn't that big too.. I'm just confused about having a big shader for drawing and one simple operation for blending the displacement maps.. The thing is, in my game, sometimes I have hundreds of small displacements to apply to each frame. I could have 2 or 3 shock waves, I use a particle system to simulate heat haze effects, I could have warp bubbles going on... With this system, I simply draw all my hundreds of pre-rendered textures to a texture in a back buffer, using SpriteBatch.Draw, then i draw my scene, and then in a single simple shader pass, I add all the distortion to my scene. Also, i never used normal maps, so I don't know if they provide the "added benefits" I mentioned in my previous post.
  15. Thanks a lot ; I know nothing of shader optimization, so this is very helpful. Also, yes, the point is to be able to blend displacement maps using a simple SpriteBatch.Draw call. The added benefits are the possibility to modulate the power of the displacement just by tinting the sprite, to scale it, and to be able to use any image editor to create complex effects. I don't know if that's possible using normal maps (I never used them). I just noticed you used "dot()" in your correction to my HLSL code! The whole transformation relies heavily on dot products, which I have been calculating manually, but since the function is available in HLSL, (and I suppose it's faster), I'll edit my code to use it.