Jump to content

  • Log In with Google      Sign In   
  • Create Account


Tonyyyyyyy

Member Since 01 Oct 2011
Offline Last Active Nov 23 2012 05:48 PM
-----

Topics I've Started

Authoritative Server-side Input

29 October 2012 - 10:09 PM

After hours of googling and countless re-reads of Valve's networking documentation, I simply can't get it to work. Posted Image
I implement prediction in my game as follows (I'm probably doing something extremely stupid):

struct InputPacket
{
    private byte _id = 0;
    bool forward; // > 0
    bool forward_zero; // == 0
    bool right; // > 0
    bool right_zero; // == 0
    float pitch;
    float yaw;
    public InputPacket(byte id, int forward, int strafe, float pitch, float yaw, bool jumpDown)
    {
  _id = id;
	    this.forward = forward > 0;
	    this.forward_zero = forward == 0;
	    this.right = strafe > 0;
	    this.right_zero = strafe == 0;
	    this.jumping = jumpDown;
	    this.pitch = pitch;
	    this.yaw = yaw;
}
public Packet CreatePacket()
{
  // creates a packet...
}
}
vector3 pastpositions[256];
mainLoop() // 60 FPS
{
if(shouldUpdate) // input is sampled at 30 FPS
{
  input.sample();
  int forward = 0;
  int right = 0;
  if(input.forward.down)
   forward++;
  if(input.back.down)
   forward--;
  if(input.strafe_right.down)
   strafe++;
  if(input.strafe_left.down)
   strafe--;
 
  // set player input
  playerObj.Forward = forward;
  playerObj.Strafe = right;
  // set player direction
  playerObj.Yaw = camera.yaw;
  playerObj.Pitch = camera.pitch;
  playerObj.ForwardMove = camera.forwardmove;
  playerObj.RightMove = camera.rightmove;
}
// goes before because some values may be changed
if(shouldUpdate)
  sendMessage(new InputPacket(...).CreatePacket());
// exact same code as the server
playerObj.Update(elapsedTime);
if(shouldUpdate)
{
  pastpositions[counter++] = playerObj.Position;
}
}
receivePos(byte id, Vector3 pos)
{
if(pastpositions[id] != pos)
{
  // client will interpolate position to match this
  playerObj.ServerPos = pos;
}
}

This works pretty well, except every single time, the prediction is off from 0 to at most, 1 (units). The error increases with ping, and I get around 0.3 units off at 50ms.

After reading the Valve documentation though, it seems that they have it right most of the time. I strongly suspect that what's causing the error for me is that the timing on the server/client may be different.

For example, say the client starts moving at time t = 0, and stops moving at time t = 1. The client thinks it has moved for 1t, and advances the position as it should. However, due to network latency, the first packet may arrive at t=1, and the packet that says "I stopped moving" may arrive at t = 2.25. In the server's eyes, the client moved 1.25 seconds, and thus an error has been produced.

I noticed that Valve includes a duration in their packet, but wouldn't this make the prediction off if the FPS is variable? Seeing as many players don't have a constant FPS, it boggles my mind as to how they rarely get prediction errors.

Even if I were to use the time of the last frame (as Valve states they do), how could I split that time between the player updates? As you can see, my update is sampled at 30 FPS, and my player is updated at 60 FPS, and therefore, I have to somehow intelligently split the time between the extra frames. I guess what worries me the most is that a changing FPS will royally screw over all my guesswork.

Thanks in advance!

Rendering Edge on 3D Quad

09 May 2012 - 10:03 PM

I want to use textures on quads in my game instead of an actual model (for the HUD), so what I currently do is I make a quad, draw the texture on to it, and then rotate it a bit. However, this gives the impression that the tool is flat and 2D, and doesn't have any width to it.
The best example I can think of is probably Minecraft. If you hold a tool in Minecraft (such as a pickaxe), the texture is drawn and it has an "edge". The color of the edge isn't just a random color, but rather it is about the same color of the edge on the actual face of the tool.

Images:
Edge highlighted:
Posted Image
Full image:
Posted Image
How can I do this with XNA?
As stated before, I currently construct a quad and render an image to it.

[XNA] Using Textured Quad for HUD

01 October 2011 - 12:06 AM

I'm trying to render an image of a gun onto a textured quad, which will be part of my HUD (think Minecraft or Ace of Spades).

However, I just can't get the image to rotate or have a Z value.

Here's some code:

public void Render()
        {
            //If we have an active screen, don't draw the rest of the HUD, return.
            if (displayScreen != null)
            {
                displayScreen.Draw(spriteBatch);
                return;
            }

            // Test

            gunBillboardEffect.Parameters["World"].SetValue(Matrix.Identity);
            gunBillboardEffect.Parameters["View"].SetValue(Matrix.Identity);
            //gunBillboardEffect.Parameters["Projection"].SetValue(Cameras.CameraManager.ActiveCamera.Projection);
            gunBillboardEffect.Parameters["Projection"].SetValue(Matrix.CreateOrthographic(Globals.GameInstance.GraphicsDevice.Viewport.Width, Globals.GameInstance.GraphicsDevice.Viewport.Height, 0, 4000f));

            gunBillboardEffect.Parameters["BillboardTexture"].SetValue(tempBillboard);
            
            foreach (EffectPass pass in gunBillboardEffect.CurrentTechnique.Passes)
            {
                pass.Apply();

                DrawBillboard();
            }

            //Draw the normal HUD.

            spriteBatch.Begin();

            spriteBatch.End();
        }

        private void DrawBillboard()
        {
            VertexBillboard[] billboardVertices = new VertexBillboard[4];

            Vector3 v1 = Vector3.Zero;

            billboardVertices[0] = new VertexBillboard(new Vector3(v1.X + 10, v1.Y + 10, 0), new Vector2(1, 1));
            billboardVertices[1] = new VertexBillboard(new Vector3(v1.X + 10, v1.Y - 10, 0), new Vector2(0, 1));
            billboardVertices[2] = new VertexBillboard(new Vector3(v1.X - 10, v1.Y + 10, 0), new Vector2(1, 0));
            billboardVertices[3] = new VertexBillboard(new Vector3(v1.X - 10, v1.Y - 10, 0), new Vector2(0, 0));

            short[] billboardIndices = new short[] { 3, 2, 0, 3, 0, 1 };

            Globals.GameInstance.GraphicsDevice.DrawUserIndexedPrimitives<VertexBillboard>(PrimitiveType.TriangleList, billboardVertices, 0, 4, billboardIndices, 0, 2);
        }


The code above will draw the image on the screen. However, if I add any rotation to the World matrix, or I specify a Z value for the vertices, the image disappears.
I'm not sure if this is a problem with my code, or if I'm just doing something wrong.

VertexBillboard

public struct VertexBillboard : IVertexType
    {
        Vector3 _position;

        Vector2 _textureCoordinate;

        public static readonly VertexElement[] VertexElements = new VertexElement[]
        {
            new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
            new VertexElement(sizeof(float) * 3, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
        };

        public static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration(VertexElements);
        VertexDeclaration IVertexType.VertexDeclaration { get { return VertexDeclaration; } }

        public VertexBillboard(Vector3 position, Vector2 texcoords)
        {
            _position = position;

            _textureCoordinate = texcoords;
        }

        public Vector3 Position { get { return _position; } set { _position = value; } }
        public Vector2 TextureCoordinate { get { return _textureCoordinate; } set { _textureCoordinate = value; } }
        public static int SizeInBytes { get { return sizeof(float) * 5; } }
    }


GunBillboard.fx

float4x4 World;
float4x4 View;
float4x4 Projection;

Texture BillboardTexture;

sampler BillboardSampler = sampler_state
{
	texture = <BillboardTexture>;
	magfilter = POINT;
	minfilter = POINT;
	mipfilter = POINT;
	AddressU = WRAP;
	AddressV = WRAP;
};

struct VertexShaderInput
{
    float4 Position : POSITION0;

	float2 TextureCoords : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;

    float2 TextureCoords : TEXCOORD0;
	float4 Color : COLOR0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    output.TextureCoords = input.TextureCoords;

	output.Color.rgb = float3(1, 1, 1);
	output.Color.a = 1;

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    float4 texColor = tex2D(BillboardSampler, input.TextureCoords);

	float4 color;

	color.rgb = texColor.rgb * input.Color.rgb;
	color.a = texColor.a;

	if(color.a == 0)
		clip(-1);

    return color;
}

technique Technique1
{
    pass Pass1
    {
        // TODO: set renderstates here.

        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}


I'm fairly new to writing my own shaders, so please, be patient with me. :)

Thanks for any help
-Tony

PARTNERS