I'm making an FPS game. In the FPS game, the mouse cursor is in the middle of the screen. So I put the mouse cursor in the center with the next code. But how can I solve this problem when the camera stutters very much every time I move the mouse?
SetCursorPos(CRenderMgr::GetInst()->GetResolution().fWidth / 2, CRenderMgr::GetInst()->GetResolution().fHeight / 2);
CRenderMgr::GetInst()->GetResolution() is Screen Width and height
What you are doing is referred to as 'relative mode' mouse movement.
For classic Win32, this is typically done using "raw input". See this article.
If you want "raw input" to also to work in a Remote Desktop, see this code. In Remote Desktop, you don't get MOUSE_MOVE_RELATIVE data, and in normal desktop scenarios you never get MOUSE_MOVE_ABSOLUTE data.
For UWP, this is implemented as mentioned in this article.
You can see the Mouse class in the DirectX Tool Kit.
Related
I am trying to record my in-game mouse movement so I can play it back. The game is Call of Duty 4, although that isn't relevant to this question. What is relevant is that most First Person Shooter games re-center the mouse cursor when you move it, so that you never hit any borders. I can't find anything about this online after searching for a while. I am currently using a mouse hook (WH_MOUSE) in order to keep track of the mouse movements (WM_MOUSEMOVE). When I list these messages, I can see that the cursor is pulled back to screenResolutionX / 2, screenResolutionY / 2 (the center of the screen).
My first attempt at figuring this out was to ignore the messages if they are equal to the center of the screen, so that when I play back these mouse movements, the re-centering is ignored. I assumed this would solve the problem, but now when I play back the mouse movements the mouse goes too far (way off from what I recorded). When I do the same recording/playing back in the main menu of the game (where the cursor isn't re-centered), the playback is incredibly accurate. My question is: what can I do to record mouse movements in the game accurately, given that the game re-centers my cursor?
Thanks in advance.
Edit: let me clarify what I'm asking. I want to only record actual user mouse input, not the game re-centering the mouse cursor.
In order to intercept those mouse messages you'd have to make a filter driver or a hook. Here's a nice article (with code) on the subject:
http://www.oblita.com/interception.html
That article is based on this Windows API: SetWindowsHookEx and shold be a good starting point for you.
Have you considered Low Level Mouse Hook? It intercepts mouse messages earlier than just mouse hook.
At the moment I simply use the WM_MOUSEMOVE message, but it limits the mouse movement to the maximum resolution. So what's the best way of capturing the mouse with Win32 (on a OpenGl window)? I don't want to use freeglut or any extra library.
For games and realtime DirectInput is very suitable, it's moderately hard to use.
That is not core win32 api, the winapi way of getting the input is either GetCursorPos/SetCursorPos driven by your own update loop, so you query and reset with your own frequency.
Or SetCapture and then upon WM_MOUSEMOVE you call SetCursorPos.
The point of setting the cursor pos is to give room for movement so you can get the delta, the amount the cursor moved since the last update and then put it back the cursor into the center of your window.
If you want to be able to capture mouse events after the mouse has existed the window, then you might want to look into the SetCapture function
If your problem is that you want to make a FPS game and you want your character to be able to spin in a continuous motion, then you want to set the mouse position to the center of the window after each mouse move event and handle input based on the difference between the position of the cursor when the mouse move event is fired and the center of the screen. To set the position of the mouse you can use the SetCursorPos function.
Your best bets are to either use DirectInput (which can be a bit of a pain to set up) or RawInput.
There is a fairly comprehensive example available in the Using RawInput page (See example 2).
I'm trying to use SetCursorPos to move the cursor location when it hits the edge of the screen (for a scrubby control); the standard "track until the edge is hit, move cursor to middle of screen" thing.
The problem is that Windows resets the cursor location back to where it was as soon as it gets a mouse event.
For debugging purposes, I made a test app using the code at:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648380(v=vs.85).aspx#_win32_Using_the_Keyboard_to_Move_the_Cursor
This is showing me the same behavior: I use the mouse to park the cursor in the top left corner of the window (right under the File menu) and use the keyboard to move the cursor off to wherever. But as soon as I touch the mouse, the cursor is right back to the top left corner.
This is obviously less than helpful for my control that uses the mouse to scrub.
How can I make Windows accept my SetCursorPos position as truth?
Thanks!
Using SetCursorPos usually works fine (even though to use it is considered bad style in general.) Some devices such as a Wacom tablet send absolute positions, though. As soon as the device sends a new location, the cursor will jump back. You really can't help this if this is the case.
However, am I right assuming you're doing this because you're trying to detect the speed of the cursor? If so, you should probably use a different API that gives you the low-level values without the need to use the position of the cursor at all. Have a look at DirectInput!
I am trying to send mouse events to a (I think SDL/OpenGL) game that doesn't support a gamepad. I know I could just use one of the many Gamepad to Keyboard/Mouse applications available, but I thought it would be fun to write my own. The following code works fine except when the game is running:
// point is a CGPoint that is set earlier on...
CGEventRef event = CGEventCreateMouseEvent(NULL,kCGEventMouseMoved , point, 0);
CGEventSetType(event, kCGEventMouseMoved);// apparently there is a apple bug that requires this...
CGEventPost(kCGHIDEventTap, event);
CFRelease(event);
With this, I can move the cursor on my desktop, and even in the games menu's, however the only time the game gets it while in the actual game is when I move my physical mouse. Sending keyboard events works fine in the game, so I don't know what the problem is
I found out what the problem was, I had to use:
CGEventSetIntegerValueField(event, kCGMouseEventDeltaX, dX);
CGEventSetIntegerValueField(event, kCGMouseEventDeltaY, dY);
to set the relative coordinates of the mouse move. I think this is because the game was warping the mouse to the center of the game window, and my application wasn't getting the mouse move events from that.
I'm currently writing a c++ console application that grabs the mouse position at regular intervals and sends it to another visual application where it is used to drive some 3d graphics in real time. The visual app is closed source and cannot be altered outside it's limited plug-in functionality.
Currently I'm using the GetCursorPos() function which is easy and fast enough, but I'm running into the issue that all of the data is clipped based on the current screen resolution of 1920x1600 so that all x values are between 0 and 1920 and all y values are between 0 and 1600 no matter how far the mouse is physically moved.
I need to get the mouse position before it's clipped at the edge of the screen, or possibly the deltas which I could use to calculate the current position.
I've seen some references to the windows MouseMove event but I would really not want to implement a window to make it work or especially have it as the active to receive those events.
I'm working in a windows environment and a language change is not feasible.
I might be wrong, but in Win32 land you don't get mouse move messages when the mouse is at the edge of the screen because, well, the mouse isn't moving. The usual way to get an infinite mouse area is to do the following:
Hide the mouse, get exclusive access and record position
Centre mouse to window
When mouse moves, get delta from centre of screen to current position
Centre mouse to window again
The next mouse move should have a delta of (0,0), so ignore it
Go to 3 until end of mouse move operation
Reset position, show the mouse and release exclusive access
If you didn't hide the mouse, then you'd see the mouse moving a small distance and then snapping back to the centre position, which looks nasty.
This method does require a message pump for the mouse move messages so the console application idea probably won't work with this. Can you create a full screen invisible window for grabbing the mouse?
Just get the position, and move it to the center and return the delta yourself
This is how FPS games do it
I don't have any direct experience with raw input, which is probably what you need to tap into. According to MSDN, you have to register the device, then setup your winproc to accept the WM_INPUT messages and then do your calculations based on the raw data.
Here's another relevant link.