Sign in to follow this  

Dragging the camera problem (Fixed)

This topic is 2850 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I'm currently developing a 4x Game, and i have a problem with my camera. I have a star map, that consists of alot of textured quads positioned on X and Y where Z is always 0. Now when i drag the mouse i would like the camera to move, that i have no problem with. The problem is that it moves to fast. Currently i apply a scaledown factor, but this seems a weird solution, and doesn't really give the best results. To illustrate the problem, imagine you start dragging with the cursor over one of the stars, i would like to have that star stay under the cursor while i drag, currently it drifts when i move the mouse. so that it's final position is not under the cursor. There must be a way to do this, i will provide a working sample if anyone wants to take a look, be aware that it is around 7-10 mb to download. I also have various zoom levels, but i take it, that solving it for one zoom level will allow me to solve for all of them. [Edited by - Firestar_Jes on February 25, 2010 10:57:27 AM]

Share this post


Link to post
Share on other sites
First, for consistency, make sure the mouse position is in window coordinates, not screen coordinates.

Use the difference in the mouse position in pixels from one mouse-move to the previous to change the screen location where you draw each tile.

On mouse-click:
basePos = mousePos;
...
On mouse-move:
deltaPosX = mousePosX - basePos.x;
deltaPosY = mousePosY - basePos.y;
// ---- this is probably what you're missing
basePos = mousePos; //!!!!!!!!!!!!

Share this post


Link to post
Share on other sites
Actually that is exactly what i'm doing at the moment, it just don't work very well.

I'm updating the camera's vector with the amount the mouse moved, it still creates drift.

This is not a 2D problem, everything is in 3D.

Share this post


Link to post
Share on other sites
Quote:
.. positioned on X and Y where Z is always 0. .. This is not a 2D problem, everything is in 3D.

That's a bit confusing, I'm afraid.

So the map is displayed in 2D, you're dragging something in 3D (presumably with Z != 0) and want the 2D display to match (or something..)? If so, take a look at the D3DXProject and D3DXUnproject functions.

Or, perhaps, you could post your code where you get the mouse position, calculate the delta and display the map using the delta.

Does it occur when zoom = 1?

p.s. Not interested in a 7 meg download, thanks. [wink]

Note: you can use code and source tags to post code. Click on Edit for my post (you can look at it but won't be able to save changes) to see:

Here's how
code can be displayed


//Here's some source code
void function(..)
{
//stuff
}


Share this post


Link to post
Share on other sites
Well it is a 2D map, in the sense that the Z coord is always zero for all of the quads that make up the star map.

this is the code used for moving the camera, the cameras Z position is set according to zoom level, and the cameras target is set as the same position, but with Z 0.

Code:


float deltaX = mouseState.X - _lastMouseState.X;
float deltaY = mouseState.Y - _lastMouseState.Y;
camPosition += new Vector3(-(deltaX) * _mouseMoveScale, (deltaY) * _mouseMoveScale, 0);
if (camPosition.X > 1000)
camPosition.X = 1000;
if (camPosition.Y > 1000)
camPosition.Y = 1000;
if (camPosition.X < 0)
camPosition.X = 0;
if (camPosition.Y < 0)
camPosition.Y = 0;
camTarget = new Vector3(camPosition.X, camPosition.Y, 0);
_cameraUpdated = true;



Share this post


Link to post
Share on other sites
Here is the draw code (it's using XNA)


if (_cameraUpdated)
{
viewMatrix = Matrix.CreateLookAt(camPosition, camTarget, new Vector3(0, 1, 0));

}
GraphicsDevice.Clear(Color.Black);
g.Draw(gameTime, viewMatrix, projectionMatrix);



g.draw is the what draws the map, it calls DrawIndexedPrimitives with the projection matrix and the viewmatrix.

Share this post


Link to post
Share on other sites
From my previous post.
Quote:
On mouse-move:
deltaPosX = mousePosX - basePos.x;
deltaPosY = mousePosY - basePos.y;
// ---- this is probably what you're missing
basePos = mousePos; //!!!!!!!!!!!!

Do you set _lastMouseState = mouseState after you update the camera*?

If not, you're moving the camera based on a change from the initial position of the mouse, not how much the mouse moved since the last update.

Also, are you using an ortho projection?

EDIT:
*Or does XNA update it automatically?

EDIT2: Your camera always has a non-zero Z position component, correct?

Share this post


Link to post
Share on other sites
Cross-post. Your camera always has a non-zero Z position component, correct?

EDIT: By the way, zooming is normally done by changing the fov. What does mouseMoveScale do (or is it just 1)?

Share this post


Link to post
Share on other sites
Hey, yes the camera always has a positive z component.

right now mouseMoveScale scales the movement the camera does in any direction down so it doesn't move so fast, if excluded the screen drags way to fast compared to how much you moved the mouse.

EDIT: Changed zoom to use FOV instead of moving the camera along the Z-axis

Share this post


Link to post
Share on other sites
Quote:
scales the movement the camera does in any direction down so it doesn't move so fast

So you move the mouse 2 pixels, the camera moves 1 pixel. Wouldn't you then expect the mouse to move faster than the camera? If mouseMoveScale != 1, then you'll see what you're getting.

EDIT: You need to reposition the mouse ( SetCursorPos or something like that ) backed to its scaled position each update.

Something like:
newMousePos = lastMousePos + scaledDeltaMove;
SetCursorPos( newMousePos ); // can't remember, this might be screen coords

Share this post


Link to post
Share on other sites
The problem is, that if i leave it a 1, the camera moves way to fast, when zoomed in, and way to slow when zoomed out.

The mouseScaleValue i calculated when zoom changes, based on what i knew looked atleast decent at one zoom level.

Share this post


Link to post
Share on other sites
Sorry. Crossposts again.

Reposition the mouse after each camera update.

newMousePos = lastMousePos + scaledDeltaPos;
SetCursorPos( newMousePos ); // this might be in screen coords. convert if necessary

It needs to move in the opposite direction by the same amount that you move the camera.

Don't know if that will trigger another mousemove. I'm not an XNA person. You may need to handle that.

Share this post


Link to post
Share on other sites
The mouse cursor is visible during dragging, but what would setting the mouse cursor position help?

I've upload the binaries of my test program, here: http://www.megaupload.com/?d=00OSOPLN

It's 3.7Mb, if you download it and zoom in and left click to drag around, you should see the problem. it requires the XNA runtimes, so if you don't have them, or don't want to download them, just ignore the download :)

But thanks for your help so far.
Good examples of what i'm trying to accomplish with the dragging is Galactic Civilization 2, FreeOrion and Armada 2526 all implements the dragging perfectly.

Share this post


Link to post
Share on other sites
Quote:
The mouse cursor is visible during dragging, but what would setting the mouse cursor position help?

Setting the mouse position will move the visible cursor. And it may appear to jiggle and hand-eye effects will be a little annoying.

In my apps, I hide the mouse and draw my own mouse sprite where I've positioned the mouse to smooth that out. Another choice is to just hide the mouse and display something in the middle of the screen, since that's the center of interest. You'll still need to reposition the mouse to keep it from dragging offscreen.

If you do something like that, you should drag the screen only when a button is down or some key is pressed so the user can access the menu bar, etc., in a natural fashion. If it's a full screen app, just hide the mouse and draw your own.

EDIT: I'm not familiar with them, but I doubt seriously if those games display the actual mouse cursor.

Share this post


Link to post
Share on other sites
You might consider buffering the last N frames of delta mouse movement, and moving based on the average value in the buffer. That is, if "doesn't really give the best results" means a choppy feeling, then this will make it silky smooth...

Share this post


Link to post
Share on other sites
Thanks for all the help.

I finally figured out how to do what i want. I take the difference in world coords and not screen and then move the camera by that. A rather simple thing, but took me a while to figure out. The code is below



Vector3 worldCoords = GraphicsDevice.Viewport.Unproject(new Vector3(mouseState.X, mouseState.Y, 1.0f), projectionMatrix, viewMatrix, Matrix.Identity);
Vector3 lastWorldCoords = GraphicsDevice.Viewport.Unproject(new Vector3(_lastMouseState.X, _lastMouseState.Y, 1.0f), projectionMatrix, viewMatrix, Matrix.Identity);
float deltaX = worldCoords.X - lastWorldCoords.X;
float deltaY = worldCoords.Y - lastWorldCoords.Y;
camPosition += new Vector3(-(deltaX), -(deltaY), 0);


Share this post


Link to post
Share on other sites

This topic is 2850 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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