Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

Moving where facing. Nan error.

Started by Yoyoyoyo Apr 25, 2011 at 5:58 PM 20 replies 5.2k views
Original Post
Yoyoyoyo
Yoyoyoyo
Trouble code has its font enlarged so you will see it easily. EDIT- its merely wrapped in size[] code. Boo, it is listed below the code section.
Im getting nan errors where in the past using the same technique, it worked.



{

public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
List<Texture2D> Tiles = new List<Texture2D>();
private int tileSize = 78;
MouseState mouse;
private Vector2 mousePos;
private Vector2 pPos = new Vector2(100,100);

private float pRot = 1.0f;
Camera2d cam = new Camera2d();
private SpriteFont font;
private Vector2 camPos;
private float mapX;
private float mapY;
public Vector2 mapV;
private Texture2D player;
private Vector2 temp;
private float pVx = 0.0f;
private float pVy = 0.0f;
private float speed = 0.00f;

public class Camera2d
{
protected float zoom;
public Matrix transform;
public Vector2 pos;
protected float rot;

public Camera2d()
{
zoom = 1.0f;
rot = 0.0f;
pos = new Vector2(640,400);
}

public float Zoom
{
get {return zoom;}
set {zoom = value; if (zoom < 0.2f) zoom = 0.2f;}
}

public float Rotation
{
get {return rot;}
set {rot = value;}
}


public void Move(Vector2 amount)
{
pos += amount;

}

public Vector2 Pos
{
get { return pos;}
set {pos = value;}
}







public Matrix getTransformation(GraphicsDevice graphicsDevice)
{
transform = Matrix.Identity *
Matrix.CreateTranslation(new Vector3(-pos.X, -pos.Y, 0)) *
Matrix.CreateRotationZ(rot) *
Matrix.CreateScale(new Vector3(zoom, zoom, 1)) *
Matrix.CreateTranslation(new Vector3
(graphicsDevice.Viewport.Width *
0.5f, graphicsDevice.Viewport.Height *
0.5f, 0));

return transform;
}

}


public Vector2 ToWorldLocation(Vector2 position)
{
return Vector2.Transform(position, Matrix.Invert(cam.transform));
}




//here is my array



public Vector2 ComputeAdd(Vector2 first, Vector2 second)
{
Vector2 result = new Vector2();
result = (first + second);
return result;
}


public Vector2 ComputeSub(Vector2 first, Vector2 second)
{
Vector2 result = new Vector2();
result = (first - second);
return result;
}













public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}

/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
graphics.PreferredBackBufferWidth = 1280;
graphics.PreferredBackBufferHeight = 800;
graphics.ToggleFullScreen();
graphics.ApplyChanges();
this.IsMouseVisible = true;



















base.Initialize();
}

/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);

Tiles.Add(Content.Load<Texture2D>("Tiles/Black"));
Tiles.Add(Content.Load<Texture2D>("Tiles/DungeonFloor"));
Tiles.Add(Content.Load<Texture2D>("Tiles/DungeonFloor2"));
Tiles.Add(Content.Load<Texture2D>("Tiles/marble2"));
Tiles.Add(Content.Load<Texture2D>("Tiles/grass1"));
Tiles.Add(Content.Load<Texture2D>("Tiles/dirt1"));
Tiles.Add(Content.Load<Texture2D>("Tiles/rock1"));
Tiles.Add(Content.Load<Texture2D>("Tiles/mud1"));
Tiles.Add(Content.Load<Texture2D>("Tiles/wood1"));
///////////////////////////////////////////////////

font = Content.Load<SpriteFont>("Fonts/font");
/////////////////////////////////////////////////////

player = Content.Load<Texture2D>("Entity/Sprite-player1");












// TODO: use this.Content to load your game content here
}

/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}

/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();




mouse = Mouse.GetState();





mousePos = new Vector2(mouse.X, mouse.Y);
mousePos = ToWorldLocation(mousePos);


temp = ComputeSub(pPos, mousePos);
pRot = (float)Math.Atan2(temp.Y, temp.X); // This returns the rotation angle correctly.


[size="5"] pVx = ((float)Math.Cos(pRot) * speed);


// i have removed the pVy code, but it was also from 'good stock' that worked.



pPos = new Vector2(pPos.X + pVx, pPos.Y + pVy); // Not causing an error yet. But does when i uncomment the above pVx/y code.


if (Keyboard.GetState().IsKeyDown(Keys.PageUp))
{
cam.Zoom += 0.02f;
}

if (Keyboard.GetState().IsKeyDown(Keys.PageDown))
{
cam.Zoom -= 0.02f;
}


if (Keyboard.GetState().IsKeyDown(Keys.OemPeriod))
{
cam.Rotation += 0.02f;
}


if (Keyboard.GetState().IsKeyDown(Keys.OemComma))
{
cam.Rotation -= 0.02f;
}

if (Keyboard.GetState().IsKeyDown(Keys.Back))
{
cam.Rotation = 0.0f;
}


if (Keyboard.GetState().IsKeyDown(Keys.Up))
{

cam.Move(new Vector2(0, -5));
}

if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
cam.Move(new Vector2(0, 5));
}

if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
cam.Move(new Vector2(5, 0));
}

if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
cam.Move(new Vector2(-5, 0));
}


if (Keyboard.GetState().IsKeyDown(Keys.W))
{
speed += 0.07f;

}









// TODO: Add your update logic here

base.Update(gameTime);
}

/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);




// TODO: Add your drawing code here
spriteBatch.Begin(SpriteSortMode.FrontToBack,null,

null,
null,
null,
null,
cam.getTransformation(GraphicsDevice));



for (int y = 0; y < map.GetLength(0); y++)
{
for (int x = 0; x < map.GetLength(1); x++)
{
spriteBatch.Draw(Tiles[map[y, x]],
new Rectangle(x * tileSize,
y * tileSize,
tileSize,
tileSize),
Color.White); //want a way to change the colour value, based on a location of map. SO from pos can find elements in array and the iterate them to particular colours.
}
}

spriteBatch.Draw(player, pPos , null, Color.White, pRot, new Vector2(35, 35), 0.62f, SpriteEffects.FlipHorizontally, 1.0f);



spriteBatch.End();
spriteBatch.Begin();


spriteBatch.DrawString(font, "mousePosX " + mousePos.X, new Vector2(100, 200), Color.White);
spriteBatch.DrawString(font, "mousePosY " + mousePos.Y, new Vector2(100, 220), Color.White);



spriteBatch.DrawString(font, "camPosX " + camPos.X, new Vector2(100, 240), Color.White);
spriteBatch.DrawString(font, "camPosY " + camPos.Y, new Vector2(100, 260), Color.White);
spriteBatch.DrawString(font, "ppos " + pPos, new Vector2(100, 280), Color.White);
spriteBatch.DrawString(font, "pVx " + pVx, new Vector2(100, 300), Color.White);
spriteBatch.DrawString(font, "pVy " + pVy, new Vector2(100, 320), Color.White);
spriteBatch.DrawString(font, "speed " + speed, new Vector2(100, 340), Color.White);
spriteBatch.DrawString(font, "pRot " + pRot, new Vector2(100, 360), Color.White);


spriteBatch.End();






base.Draw(gameTime);
}
}
}





Im trying to simply move the sprite in the direction it is facing(dictated by the mouse position). If i put in code that ive used before, (basically finding the x and y velocities using the highlighted code) which has worked no problem in the past.
It's fairly simple code, but i cant find why it isnt working.


The highlighted code;

pVx = ((float)Math.Cos(pRot) * speed);

pVx = player X velocity
pRot = player Rotation in radians. (Which works fine)
speed is a float value, set to zero (but even setting it to 1 changes nothing, and speed has always started at zero in my other projects where this code worked)

I get Nan errors for pRot, and Ppos.X
Ive run the same code before and it's not been a problem, i just can't find the source of the problem, seems so simple.
Can anyone see why i would be getting a nan error?
Zakwayda
Zakwayda
Begin by stepping through the code in the debugger and determining where, exactly, the NaN's are being introduced.
frob
frob
Several math operations can result in NaN.

These include floating point divide by zero, certain operations with infinity such as inf-inf, trig operations that are out of range, and more.

As specific examples, if you use acos() or asin() with a value outside -1 to 1, you will generate a NaN. If you divide by zero in floating point math you will generate NAN. (divide by zero on integer math will still crash.)

C# does not crash your program on floating point math errors. It simply returns NaN and continues on it's way. Unless things have changed very recently there is no way to adjust the behavior.
Yoyoyoyo
Yoyoyoyo
It's really wierd, i can gather the Vx and Vy velocities (correctly computed) and create a new Vector2 with them, then to my mind, its a simple matter of adding this Vector 2 to the Vector2 of the player position.

So i can correctly create everything except when i add to the player position it creates nan errors. Otherwise all information is generated ok.

pVx = ((float)Math.Cos(pRot) * speed);
pVy = ((float)Math.Sin(pRot) * speed);

pVect = new Vector2(pVx, pVy);
// Works fine up to this point.

pPos = Vector2.Add(pVect, pPos);
This line creates nan errors. Ive tried it many ways, but no joy.


Zakwayda
Zakwayda
Can you post some example values? What are the values of pVect and pPos immediately before you call Vector2.Add()? And what's the value of pPos immediately after?
Yoyoyoyo
Yoyoyoyo
at speed ~ 0.1 ;

pVect =(-0.1 , 0.006) (x component needs to reassigned opposite -/+) But shouldn't matter at this stage.
pPos = (100,100)
pRot = 3.08

After the Add all these figures are nan!
Zakwayda
Zakwayda
So you're saying that when you step through the code in the debugger, when the Vector2.Add() line is next to be executed (but hasn't yet been executed), the values are as shown above, but immediately after executing that line, they all change to NaN?

Can you post a longer excerpt that includes the code after the line in question? (Maybe that's in the code you originally posted, but I didn't see it anywhere.)
Yoyoyoyo
Yoyoyoyo
No, its if i comment out the trouble line and run the program. Then comment it back in i get the nan errors. Im not sure how to go through it with the debug..

This is the code that follows;






if (Keyboard.GetState().IsKeyDown(Keys.PageUp))
{
cam.Zoom += 0.02f;
}

if (Keyboard.GetState().IsKeyDown(Keys.PageDown))
{
cam.Zoom -= 0.02f;
}


if (Keyboard.GetState().IsKeyDown(Keys.OemPeriod))
{
cam.Rotation += 0.02f;
}


if (Keyboard.GetState().IsKeyDown(Keys.OemComma))
{
cam.Rotation -= 0.02f;
}

if (Keyboard.GetState().IsKeyDown(Keys.Back))
{
cam.Rotation = 0.0f;
}


if (Keyboard.GetState().IsKeyDown(Keys.Up))
{

cam.Move(new Vector2(0, -5));
}

if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
cam.Move(new Vector2(0, 5));
}

if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
cam.Move(new Vector2(5, 0));
}

if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
cam.Move(new Vector2(-5, 0));
}


if (Keyboard.GetState().IsKeyDown(Keys.W))
{
speed += 0.002f;

}

if (Keyboard.GetState().IsKeyDown(Keys.S))
{
speed -= 0.002f;
}





the update is here, i just didnt bother putting it in






protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);




// TODO: Add your drawing code here
spriteBatch.Begin(SpriteSortMode.FrontToBack,null,

null,
null,
null,
null,
cam.getTransformation(GraphicsDevice));



for (int y = 0; y < map.GetLength(0); y++)
{
for (int x = 0; x < map.GetLength(1); x++)
{
spriteBatch.Draw(Tiles[map[y, x]],
new Rectangle(x * tileSize,
y * tileSize,
tileSize,
tileSize),
Color.White);
}
}

spriteBatch.Draw(player, pPos , null, Color.White, pRot, new Vector2(35, 35), 0.62f, SpriteEffects.FlipHorizontally, 1.0f);



spriteBatch.End();
spriteBatch.Begin();


spriteBatch.DrawString(font, "mousePosX " + mousePos.X, new Vector2(100, 200), Color.White);
spriteBatch.DrawString(font, "mousePosY " + mousePos.Y, new Vector2(100, 220), Color.White);



spriteBatch.DrawString(font, "camPosX " + camPos.X, new Vector2(100, 240), Color.White);
spriteBatch.DrawString(font, "camPosY " + camPos.Y, new Vector2(100, 260), Color.White);
spriteBatch.DrawString(font, "ppos " + pPos, new Vector2(100, 280), Color.White);
spriteBatch.DrawString(font, "pVx " + pVx, new Vector2(100, 300), Color.White);
spriteBatch.DrawString(font, "pVy " + pVy, new Vector2(100, 320), Color.White);
spriteBatch.DrawString(font, "speed " + speed, new Vector2(100, 340), Color.White);
spriteBatch.DrawString(font, "pRot " + pRot, new Vector2(100, 360), Color.White);
spriteBatch.DrawString(font, "pVect " + pVect, new Vector2(100, 380), Color.White);



spriteBatch.End();






base.Draw(gameTime);
}
}
}


Zakwayda
Zakwayda
You need to step through it using the debugger; that will be by far the most straightforward way to determine what's going wrong.

If you're not sure how to do that, we'll be happy to help. Just tell us what development environment you're using, etc., and someone should be able to point you in the right direction.
Zakwayda
Zakwayda

Thanks i'm running Visual studio express 2010

I don't have VS open right now, but here are some tips. If this isn't enough to get you started, just post back with whatever questions you have.

There should be a 'run' or 'debug' menu in the menu bar, and there should be a 'debug' item in that menu (or something similar).

In the code editor, you should be able to add breakpoints by clicking somewhere on the left of the window. This should add a red dot or marker of some kind. When you start debugging, when the line where the marker is is reached, the IDE will break at that point and drop you into the debugger.

Debuggers typically have three commands that you can use to step through the code: one to execute the next statement, one to step into a function, and one to step out of a function. In Visual Studio, the shortcuts for these are F10, F11, and shift-F11 (IIRC). Also, you can continue execution at any time (F5 in VS).

While debugging, there's a variety of windows you can open to see what's going on. What you'll probably want here is the 'locals' window, which will show all the variables at local scope (including 'this', the object on which the current function has been called if it's a non-static member function). With this window you can observe the values of the variables in question and determine exactly where the NaN's are introduced.
Yoyoyoyo
Yoyoyoyo
Hmm it wont let me insert a breakpoint anywhere, its all set to debug, not release. Perhaps the steps i just took on that site have screwed with it.
Yoyoyoyo
Yoyoyoyo
Thanks a tonne jyk, it's not fixed yet but at least i can find out why im getting invaded by nan's.

k it's telling me certain values are becoming nan, although running the program without that trouble piece of code there is no error, all works as normal.
Strange happenings.
As above in the code, after calling ToWorldLocation it tells me mousepos has become nan, though this is not the case when running the prog.
Although this could render all the following info nan. Ill post the solution eventually
kdmiller3
kdmiller3
Here's a snippet of code that I use to enable floating-point exceptions for divide-by-zero and invalid operation:

// turn on floating-point exceptions
unsigned int prev;
_controlfp_s(&prev, 0, _EM_ZERODIVIDE|_EM_INVALID);

This lets you catch the offending operations in the debugger without littering your code with _isnan() or stepping through your code line-by-line. The downside is that you won't be able to continue past the exception. (It's just like any other processor exception in that regard.)

I usually wrap that snippet in an "if (IsDebuggerPresent())" check since floating-point exceptions aren't nearly as useful without a debugger connected.
frob
frob

Here's a snippet of code that I use to enable floating-point exceptions for divide-by-zero and invalid operation:

// turn on floating-point exceptions
unsigned int prev;
_controlfp_s(&prev, 0, _EM_ZERODIVIDE|_EM_INVALID);

This lets you catch the offending operations in the debugger without littering your code with _isnan() or stepping through your code line-by-line. The downside is that you won't be able to continue past the exception. (It's just like any other processor exception in that regard.)

I usually wrap that snippet in an "if (IsDebuggerPresent())" check since floating-point exceptions aren't nearly as useful without a debugger connected.


That would work if he were programming in C++.

The OP posted code written in C#. That language does not allow floating point exceptions. If one would occur it silently returns NaN.

In C# it is very important to keep your values in range, as trig functions particularly can trip you up if you aren't careful.
Yoyoyoyo
Yoyoyoyo
Ok well ive found a solution for now, i simply put this code in my movement block;



if (Keyboard.GetState().IsKeyDown(Keys.S))
{
speed = 0.6f;
[color="#00FF00"]pPos += new Vector2(pVx, pVy);
}


And now it's functioning. This highlighted code would not work when it was placed with the rest of the code. Interesting.
This will likely come back to bite me on the ass, but for now im happy it's working
Yoyoyoyo
Yoyoyoyo
Workaround's are not solutions.
Well ive found what brings in the NaN's.

It's sending my vector 2 through this(just tried using a vector3 and 4 but no joy either);





mousePos.X = mouse.X;
mousePos.Y = mouse.Y;


mousePosConvert = new Vector3(mousePos, 1);
mousePosConvert = ToWorldLocation(mousePosConvert);


--->

public Vector3 ToWorldLocation(Vector3 position)
{
return Vector3.Transform(position, Matrix.Invert(cam.transform));
}

-->


public Matrix getTransformation(GraphicsDevice graphicsDevice)
{
transform = Matrix.Identity *

Matrix.CreateTranslation(new Vector3(-pos.X, -pos.Y, 1f)) *
Matrix.CreateRotationZ(rot) *
Matrix.CreateScale(new Vector3(zoom, zoom, 1)) *
Matrix.CreateTranslation(new Vector3
(graphicsDevice.Viewport.Width *
0.5f, graphicsDevice.Viewport.Height *
0.5f, 0));

return transform;
}







Assigning the value to mouseposconvert it is filled with nan's.
Ive played with the values, but nothing, but im a newb and understanding what's going on at this stage is a little beyond me unfortunately.



When i run the program all works perfectly well. When i use the converted mouse information for mouse picking the nans stop it from working, even though it 'works' in-game.
Zakwayda
Zakwayda
I suggest you take this function:

public Vector3 ToWorldLocation(Vector3 position)
{
return Vector3.Transform(position, Matrix.Invert(cam.transform));
}


And rewrite it as follows (untested):

public Vector3 ToWorldLocation(Vector3 position)
{
Matrix invTransform = Matrix.Invert(cam.transform);
return Vector3.Transform(position, invTransform);
}

Then, step through in the debugger and see what the values of 'cam.transform' and 'invTransform' are. (If you need further help, post the values here.)
Yoyoyoyo
Yoyoyoyo
+ invTransform { {M11:0 M12:0 M13:0 M14:0} {M21:0 M22:0 M23:0 M24:0} {M31:0 M32:0 M33:0 M34:0} {M41:0 M42:0 M43:0 M44:0} } Microsoft.Xna.Framework.Matrix


After running the first line of ToWorldLocation method;



+ invTransform { {M11:NaN M12:NaN M13:NaN M14:NaN} {M21:NaN M22:NaN M23:NaN M24:NaN} {M31:NaN M32:NaN M33:NaN M34:NaN} {M41:NaN M42:NaN M43:NaN M44:NaN} } Microsoft.Xna.Framework.Matrix

--------------------------------------------------------------------------
--------------------------------------------------------------------------
cam transform;


+ transform { {M11:0 M12:0 M13:0 M14:0} {M21:0 M22:0 M23:0 M24:0} {M31:0 M32:0 M33:0 M34:0} {M41:0 M42:0 M43:0 M44:0} } Microsoft.Xna.Framework.Matrix


It never gave another value

same with ;
cam.transform;


+ cam.transform { {M11:0 M12:0 M13:0 M14:0} {M21:0 M22:0 M23:0 M24:0} {M31:0 M32:0 M33:0 M34:0} {M41:0 M42:0 M43:0 M44:0} } Microsoft.Xna.Framework.Matrix
Zakwayda
Zakwayda
The camera transform shouldn't be all zeros. The fact that it is suggests that something has gone wrong elsewhere in your code, so I think the next step is probably to figure out why the camera transform has that value. (At the very least it should be identity. But, if the camera seems to be working correctly otherwise, I'm guessing you're just using the wrong matrix there or something.)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.