Dead Reckoning - Client/Server game - How to handle keystrokes - java

I've read a few articles about dead reckoning, but it's still a bit confusing to me.
I'm pretty sure I understand the concept of point-and-click movement, but how would I update keystroke movement between the client and server, when the end-point of the movement is unknown?
How would you estimate where the player is going (server-side) if there is no end-point?

Let's start with dead reckoning. Try to think about it on a straight line where there is no left or right movement.
You are at point A and want to get to point B. You know the distance to point B so you can compute how much acceleration and velocity it will take to get there. Dead Reckoning works the other way. You are at point A and will move at a set speed to get near point B.
In the video game world they use this method all the time. So don't think about it as you're moving to point B you're just moving towards point B in increments because in like a FPS your point B will constantly moving. When in fact its really only moving in increments in the direction of point B.
Once you get moving forward then you can start worrying about left/right and up/down which will follow the same principle just in different directions.
As for implementing this you have 2 options.
One way, you could make this calculation on the client side then send the new position to the server. Then update what everyone else sees on screen.
The other way which I think is better you can make all these calculations on the server side and just receive an update where you ended up. X-Box live makes one of the consoles the host so that machine is running all the software and the external users are just firing events. This is why you'll hear people complain about having an unfair host advantage.
Now let's look at some code. This script comes from the Unity Sdk standard install package.
/// This script moves the character controller forward
/// and sideways based on the arrow keys.
/// It also jumps when pressing space.
/// Make sure to attach a character controller to the same game object.
/// It is recommended that you make only one call to Move or SimpleMove per frame.
var speed : float = 6.0;
var jumpSpeed : float = 8.0;
var gravity : float = 20.0;
private var moveDirection : Vector3 = Vector3.zero;
function Update() {
var controller : CharacterController = GetComponent(CharacterController);
if (controller.isGrounded) {
// We are grounded, so recalculate
// move direction directly from axes
moveDirection = Vector3(Input.GetAxis("Horizontal"), 0,
Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= speed;
if (Input.GetButton ("Jump")) {
moveDirection.y = jumpSpeed;
}
}
// Apply gravity
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
controller.Move(moveDirection * Time.deltaTime);
}
So in this example we have speed which is set to a constant. So when moving in a direction we will travel in that Vector at a constant rate with no care about where point B is located.
Jump speed is how fast will we move in the y axis in the positive direction and gravity in the negative direction stopping at point 0.
So, How can you use this? You could build a server script that executes a move action and have a client side controller that passes the direction information to the server.
So lets say on the client side action is key press down, you send a call to the server to move you in the direction selection and the server will keep you moving you in that direction until action key press up or a change in direction from another input.
I hope this helped.

Let's see... I understand you know how to code, but not what, am I right?
You can feed the keystrokes directly to the server and let it do all the work. The server has no need to know where you are heading, it has your coordinates and direction and that's all it will need, unless you have server-handled AI. In the later case, you can do something similar to raycasting in Unity, start checking what is straight ahead and see if it is anything of interest, if so you know the potential destination.
It is safe to constantly send back to the client all his data, so it is always up to date. If you believe this will strain your connection you can do that every 50ms or as often as you believe is safe, and for smooth function estimate everything on the client side too. Make sure the server does all the collision detection and all the mechanics not related to the UI, or else the game will be prone to client-side malfunction or malicious tampering.
If you do have to look at where the player might be going, you can use a few approaches, you could either have a number of virtual cubes in the world which keep track of what is inside them, which will simplify finding what's ahead in terms of resources, or you could check everything there is, which is rather heavy on the machine, but this adds some other complexities too. In the first case do not forget to stop looking once you hit an obstacle.
You can also calculate the angle between the player's direction and other items of importance to check what else might be on his mind.
The question about UDP has already been answered, plus I'm sure Wikipedia has a helpful book on UDP and TCP, I have nothing to add.
The explanation of dead reckoning was also quite satisfactory, I hope I added other angles to the concept.
I hope I helped, if you need any clarifications or any other help feel free to contact me, if I was less than unhelpful then feel free to downvote, I study computer engineering and am creating my second game for PC so maybe I have ran into some problem already and can share the knowledge.

Related

Will "Rubber banding" resolve multiplayer interpolation stutter?

I wrote multiplayer Pong using UDP. I am using interpolation and extrapolation in order to create a smooth looking effect on the client.
It works. However, there is a bit of constant stuttering in the ball. It jumps a tiny bit forward every time a new packet is received. It looks a little laggy, but it is playable.
There must be a way to make the game look smoother. I've read about Rubber Banding. What would be the best way to move from here?
I hope someone who is able to answer my question well will find it.
Update
As requested by Ivan, here is a graph of the ping times. However, I do believe that the problem exists inside the client smoothing code.
Filling in with context from your previous question, I understand that you are sending paddle & ball positions from each client to the other. However, as long as the clients agree on where the paddles are at each moment in time, the ball's movement is completely determined (barring rounding errors), and you should experiment zero ball-stutter.
Each client should keep its own internal state with the positions and speeds of paddles and the ball. Pseudocode would be similar to the following:
// input thread
if input changed,
alter paddle speed and/or direction
send timestamped message to inform my opponent of paddle change
// incoming network thread
if paddle packet received
alter opponent's paddle speed and/or direction at time it was sent
fix any errors in previously extrapolated paddle position <--- Easy
if ball-packet received
fix any errors in ball position and speed <--- Tricky
// update entities thread
for each entity (my paddle, opponent paddle, the ball)
compute updated entity position, adjusted by time-since-last-update
if ball reached my end, send ball-packet to other side
draw updated entity
This assumes that two package types are being exchanged:
paddle packets are timestamped positions + speeds of paddles, and are sent whenever a client alters the speed of its own paddle.
ball packets are timestamped positions + speeds of the ball, and are sent whenever a ball reaches a client's (local) side, whether it bounces off the paddle or not.
The pseudocode is performing extrapolation ("assume things keep on moving as usual") for all unknowns in the update-entities thread. The only point where problems arise is marked with <--- arrows.
You can easily correct for paddle positions by warping them to their new position, possibly interpolating the movement over a short period to make it less jarring.
Correcting for ball positions is easy if both clients more-or-less agree (and then you can do the interpolation trick again, to smoothen it up further). However, one client may see a near miss and another a near hit. In this case, since you are using a peer-to-peer model, we are letting the local client make the call, and explain what happened to the opponent (in another design, you would have a central server making these kinds of decisions; this is good to avoid cheating). You cannot avoid an ugly jump there if both clients disagree - but hopefully, this should be relatively rare and short, unless it coincides with a ping spike.
One of the ideas which allows to get rid of this effect is Using smoothing when applying error prediction corrections on client.
How that works
At some point in your code you identify that ball position and client are different.
Instead of applying that as a correction to client code immediately (which is one reason you can see those jumps), you perform that over some time, cl_smoothtime e.g. 500ms.
At first your program should store time when the error detection event occured m_flPredictionErrorTime.
public void onErrorDetected() {
this.m_flPredictionErrorTime = System.currentTimeMillis();
}
Somewhere close to the display code you calculate how much of error you're going to display. Here's some pseudocode for that.
public void draw() {
Point preditctionError = this.clientPredictedBallCoordinates - this.serverCoordinates;
Point deltaToDisplay = calculateErrorVector(preditctionError);
Point positionToDisplay = clientPredictedBallCoordinates + deltaToDisplay;
// actually draw the ball here
}
public Point calculateErrorVector(Point coordinatesDelta) {
double errorAmount = ( System.currentTimeMillis() - this.m_flPredictionErrorTime ) / this.cl_smoothtime.
if (errorAmount > 1.0) {
// whole difference applied in full, so returning zero delta
return new Point(0,0);
}
if (errorAmount < 0) {
// no errors detected yet so return zero delta
return new Point(0,0);
}
Point delta = new Point(coordinates.x*errorAmount, coordinates.y*errorAmount);
return delta;
}
I've picked this idea from Source Multiplayer Networking wiki. Actual code example in Cpp is available in their SDK around GetPredictionErrorSmoothingVector function.

Quick Time Event in Swing [pseudocode request]

I am in the extremely early stages of designing a game (so early that I haven't even committed to it yet). The idea is an RPG with a Quick Time Event for attacking and defending that relies on precise mouse movements or timed button presses to reduce damage taken or increase the damage of an attack (similar to Mario and Luigi or Paper Mario). I'm wondering the best way to go about programming a class that can handle this. Ultimately, I'd like to be able to write code such as this when I call the attack function, where all of the functionality of the QTE occurs in a single function call;
//Example code.
int attackPower = 23;
double qteSucessPercent = -1;
//more code
if(e.getSource == player.sword()) //when the player chooses to execute a sword attack.
{
qteSucessPercent = QTE.Jump();
if(qteSucessPercent< 0)
throw BadQTEException;
else if(qteSucessPercent>= .9)
player.attack(enemy[0], attackPower*2);
else if(qteSucessPercent>= .75)
player.attack(enemy[0], attackPower*1.5);
else if(qteSucessRate>= .5)
player.attack(enemy[0], attackPower);
else
System.out.println("Attack Failed");
}
This class needs to do several things.
It needs to be able to draw itself.
The QTE class needs to be able to handle key pressing or mouse motion events. I can handle the code for each type of QTE I wish to implement, but they need to be able to detect, on their own, where the mouse is and what buttons are being pressed.
Whatever it is drawing needs to delete itself once the QTE is over.
There will be multiple types of Quick Time Events. Each one will be drawn differently, have different victory conditions (one may require you to hit a sequence of buttons in the correct order, another may make you press a single button in rapid succession as many times as you can, ect), and modify the attack in various ways. The basic design of all QTEs is that they return a double value between 0 and 1, depending on how well the player did (generally, the higher the number, the better; if the attack returns 0, then the QTE received no input at all). In some situations, the QTE may be pass/fail, but the rest of the program is just watching for a non-0 number to be passed from the function call. For the sword, the attack's power is being modified by how well you do.
I know Swing isn't thread-safe (which, to my knowledge, means components won't update properly if you try to activate parts of their code from a thread other than the one you called them with, meaning I can't have two blocks of code executing at the same time if I want both sets of code to display animations), which is why I've written the code the way I have. The main thread gets to line 6, and executes QTE.Sword(). Until QTE.Sword() returns (which could be as long as five seconds), the rest of the program will freeze and not animate. I plan to use this to my advantage to achieve a bullet time effect, where the only thing animating is the QTE and the players and enemies remain stationary - though if I wanted an animation, like for a Mario and Luigi-like jump QTE, I'd set the player's sprite to be an animated gif that only plays once and only for as long as the QTE goes off.
Note that I am NOT ASKING FOR CODE. I'm asking for either pseudo-code or just a paragraph explanation of how I could program this. I think I can find a dead, open-sourced project on Github or Google Code and figure out the basics of the rest of the engine from there, but this is really the sticking point for me. Also, I am not asking for help handling mouse movements or keyboard presses. I have enough knowledge to code these on my own - I'm just not sure how to implement this in the context of an RPG. I know this isn't really stackoverflow's thing, and this question will probably get deleted, but I figure this is the best place to ask this sort of thing.

Box2D - Character sticking to sides of objects

I am using Box2D with libgdx. I am having an issue with the default collision action. When I jump or hit the top of an object, everything works fine. My object doesn't stick. If it hits the top, it stands on it. If it hits the bottom, it falls back down. But if it hits either of the sides, my object sticks, as long as I'm moving in that direction. In other words, the gravity has no effect on it while it collides with the side of the block/wall. I did some research, but all solutions said to use the b2Settings, which I can't use with libgdx. Is there any way I can fix this? The code I use to move my character(moving left) is as follows:
level.character.body.setLinearVelocity(
-level.character.terminalVelocity.x,
level.character.body.getLinearVelocity().y);
Here's an illustration. As you can see, it sticks to the brick instead of falling. (My character is currently a coin :p)
Instead of using SetLinearVelocity, try using ApplyForce or ApplyImpulse to move things around. The problem is that SetLinearVelocity allows you to create unrealistic situations, for example in this case when the ball hits the wall it should stop and the horizontal velocity really should be zero, but you are overriding the natural result and saying that the ball did not stop at all, and it is still moving.
Note that you may still get this problem even when using ApplyForce or ApplyImpulse, if the force is strong enough and there is enough friction between the fixtures (just like in the real world, if you push something against a wall hard enough and the surfaces are not too slippery, you can stop it from falling).

how to detect this specific movement gesture via sensors?

I'm working on an Android project. it's goal is to detect predefined movement gesture of the device. if the device rotates 45 degrees over an axis(X,Y or Z) and then rotates back to its first position( the first and second positions are not going to be accurate, I mean if it was rotated 50 degrees instead of 45, not important !!!)then the gesture has happened and the app should detect it.
I tried to do that using Accelerometer and Magnetic sensors of device to continually monitor the orientation of the device and detect gesture but the results weren't acceptable(explained here). any start point or idea please ?
It doesn't seem like anybody is going to provide a concrete and valuable answer. So let me try to do that.
First of all, even a bit primitive and straightforward approach allows to spot the fact you do not need to process all the data coming from sensors. Moreover humans are not that fast, so there is no need to proceed 10000 values per second in order to identify any specific move as well.
What you actually need is just to identify key points and make your decision. Does it sound like a tanget to you?
What I'm actually suggesting is to test your solution using an ordinary mouse and available gesture recognition framework. Because the actual idea is pretty much the same. So please check:
iGesture - Gesture Recognition Framework
Mouse Gestures
It such a way it might be easier to develop a proper solution.
Update
Let's imagine I'm holding my phone and I need to rotate it 90 degrees counterclockwise and then 180 degrees clockwise. I hope you will not expect me to do some complex 3D shapes in the air (it will break usability and frankly I do not want to loose my phone), so it is possible to say there might be a point we can track or we can easily simulate it.
Please see my other answer in order to see simple, but working solution of a similar problem:

Java Collision Detection Not Working

I have made threads in the past about similar questions but because of my lack of detail the answers have not really been related to what I needed so I am going to try explain my question in as much detail as I can and hopefully it will be easier for you to understand what I require.
I watched Bucky's slick game tutorials on youtube and made a 2D Java game, the game is basically a 2D player viewed from above (birds eye view) can move around a 2D map with user key input (up, down, left, right). The map the player moves around is very small so that meant boundaries had to be set so that the player could not walk off of the map, to give you a better idea of how this was done, here is the tutorial for setting up the voundries:
http://www.youtube.com/watch?v=FgGRHId8Fn8
The video will also show you exactly what the game is like.
The problem is, these boundaries only require one axis meaning that if the player is walking down you say something like "if player gets to the coordinate (number) on the X axis change the player movement to the opposite direction so that he can not go any further."
Now this creates a problem for me because this only requires one axis so it easy to set up and understand but if you look on the video, on the map there is a house and I want my player not to be able to walk over that also but this deals with 2 dimensions, I have looked at things like rectangle collisions and have seen things relating to them in the other posts but I get confused because I am new to Java and havent really done much with it at the moment apart from watching Bucky's tutorials.
My code at the moment for my game class has got the following methods: init, render and update. So to sum it up I really just want to set up a way of not letting my player walk through the house, I will mention also (I should have mentioned it in my other threads) as I am very new to Java, could you please take a step by step method of showing me how to set up the collisions, I mean even the basics of things like making the rectangle if required.
If my code is required please tell me and I will post it as soon as possible.
Thank you in advance.
You can set up the board as a 2x2 grid of a class that has has property such as 'isBlocked'. By default the edges of the board would have this property set to true to prevent the character from walking off the edge. When you add other obstacles such as a house or a wall the grid position(s) the object occupies would also have the property set to true. Then when moving a character you just check if the grid position the character moves to has the property set to false to see if it's an allowable move. This also makes it quite trivial to save the level data so you can just load them from disk later on.
Two possible options:
Extend Shape or Rectangle or the relevant Slick objects (they should exist IMO) and just check for intersect()
Look for (x1,y1) and (x2,y2) values such that it starts outside and ends up inside.
Assuming you have intersect() methods:
//Grab the previous position
prevPosX = movingobject.X;
prevPosY = movingobject.Y;
//Update the position
movingobject.update();
//Test for collision
if(movingobject.intersects(targetobj)) {
//If it collided, move it back
movingobject.X = prevPosX;
movingobject.Y = prevPosY;
//And reverse the direction
//(might want to do other stuff - e.g. just stop the object)
movingobject.speed *= -1; //Reverse the speed
}
in this case your update class should also add one more condition to look for the house. let say the cooridnates of house(assuming rectanglular house here for other shape just change x and y values) are (x1,y1)(x1,y2)(x2,y2)(x3,y1) you have to add a condition to make sure
x value is not between x1 and x2 and at the same time y value cannot between y1 and y2.

Categories