I was wondering if anyone could help me with some code, essentially I've made a small function that moves the mouse cursor relative to the mouse cursor's current position, however the cursor teleports; I'd like to find a way to make it 'glide', smoothly so it looks a little more natural.
Here is the code below:
#import <Windows.h>
void MouseXY(int x, int y) {
POINT p;
if (GetCursorPos(&p)) {
SetCursorPos(p.x + x, p.y + y);
}
}
Any help would be greatly appreciated.
If you want the cursor to slide smoothly instead of teleporting, I would suggest using while loop, some delta value, and Sleep function...
What you are basically doing there is instantaneously moving the cursor.
What you probably want is to move the cursor with smaller steps.
Related
I added touch input for my game's character. The camera moves when a player's finger is dragged across the screen. However, when the joysticks are used to move, the camera doesn't move at the same time.
When I do the same code with Blueprints the code works and the camera still moves. When I drag the touch while pressing the joystick to move, I think that there is a problem in the ETouchIndex::Type. This is because in the BP when I use the finger index given in the touch event, it works. However, when I only use touch 1 as the finger index, it does not work. I think if I put that index in my CPP code it will work too, but where can I find the finger index? Can anyone please help me?
//here's my touch code that executes every tick.
FVector2D TouchLocation;
APlayerController* ActivePlayerController = UGameplayStatics::GetPlayerController(this, 0);
ActivePlayerController->GetInputTouchState(TouchType, TouchLocation.X, TouchLocation.Y, IsTouched);
if (!IsTouched)
{
DidOnce = false;
}
if (IsTouchMoved())
{
if (!DidOnce)
{
ActivePlayerController->GetInputTouchState(TouchType, PrevX, PrevY, IsTouched);
DidOnce = true;
}
ActivePlayerController->GetInputTouchState(TouchType, X, Y, IsTouched);
float FinalRotYaw = (X - PrevX) * UGameplayStatics::GetWorldDeltaSeconds(this) * 20;
float FinalRotPitch = (Y - PrevY) * UGameplayStatics::GetWorldDeltaSeconds(this) * 20;
AddControllerYawInput(FinalRotYaw);
AddControllerPitchInput(FinalRotPitch);
ActivePlayerController->GetInputTouchState(TouchType, PrevX, PrevY, IsTouched);
}
I'm trying to detect horizontal mouse motion with OpenGL, so, when detected, execute a glutPostRedisplay(). Problem is that scene is also redrawed on vertical mouse movement.
This is the code of the registered callbacks (note mouse_inix and mouse_iniy are global (double) variables):
void mouse(int button, int state, int x, int y)
{
if (state == GLUT_DOWN) {
mouse_inix = (double)x;
mouse_iniy = (double)y;
}
}
void motion(int x, int y)
{
if (((double)x) != mouse_inix) {
angle += 20.0;
glutPostRedisplay();
}
}
Are you sure? It doesn't look like from the code you've posted that vertical mouse movement will trigger the glutPostRedisplay() call.
BUT, you've defined "horizontal mouse movement" very narrowly here. If you move the mouse up and down, you're almost sure to get a few pixels of horizontal movement. Maybe you could put a dead zone around the mouse to keep it from moving on every pixel. Something like:
void motion(int x, int y)
{
if ((abs(x - (int)mouse_inix) > 10) {
angle += 20.0;
glutPostRedisplay();
}
}
That's one thing that's going on here. Another is the use of "double". Since glut is returning mouse coordinates as ints, you're better off sticking with that. Trying to compare "(double)x != mouse_inix" will almost certainly be true because of the precision issues with doubles. You generally don't want to compare for exactly equal to or not equal to using floating point numbers. The use of the dead zone will negate that issue, but still, why convert to doubles if you don't need them?
I don't know if "20" is degrees or radians, but it could result in some pretty jumpy moves either way. Consider scaling the size of the move to the size of the mouse move:
void motion(int x, int y)
{
int deltaX = (abs(x - (int)mouse_inix);
if (deltaX > 10) {
angle += (double)deltaX; // or "deltaX/scaleFactor" to make it move more/less
glutPostRedisplay();
}
}
It will still only rotate one way. If you used the sign of "deltaX", you would be able to rotated both directions depending on how you moved the mouse.
I'm using glut for a game right now and I'm trying to keep the mouse inside the window. This isn't a first person shooter so locking it in the center is no good. I already know about glutWarpPointer(int, int); and I've trying things that work (kinda).
I've tried having the mouse warp back to the nearest edge of the window when it leaves, this works, but for a split second you see the mouse outside of the window and teleport back in. I don't want that, I want it to seem like the mouse just hits the edge of the window and stops going any further in that direction, while keeping movement in any other available direction. Like you would expect it to work.
This is not exactly an answer to your question, but it is an answer to your problem!
Almost every game has its own cursors. They would hide the mouse, and draw the cursor manually where the mouse should be positioned.
If you get your own cursor image and do as I said, you can simply draw the curser at the edge of the screen, even though the mouse position reads out of boundaries. Then you can warp the mouse back in.
Tried to search and figure this out and couldn't find an answer, so I implemented it myself. Here is what worked for my first person camera case:
callback from glutPassiveMotion
CODE SAMPLE
void Game::passiveMouseMotion(int x, int y)
{
//of my code for doing the cam, yours is may be different, this is based on the example from https://learnopengl.com/Getting-started/Camera
if (firstMouse) {
lastX = x;
lastY = y;
firstMouse = false;
}
float xoffset = x - lastX;
float yoffset = lastY - y; // reversed since y-coordinates go from bottom to top
lastX = x;
lastY = y;
camera->ProcessMouseMovement(xoffset, yoffset);
glutPostRedisplay();
//this is the main thing that keeps it from leaving the screen
if ( x < 100 || x > win_w - 100 ) { //you can use values other than 100 for the screen edges if you like, kind of seems to depend on your mouse sensitivity for what ends up working best
lastX = win_w/2; //centers the last known position, this way there isn't an odd jump with your cam as it resets
lastY = win_h/2;
glutWarpPointer(win_w/2, win_h/2); //centers the cursor
} else if (y < 100 || y > win_h - 100) {
lastX = win_w/2;
lastY = win_h/2;
glutWarpPointer(win_w/2, win_h/2);
}
}
Hope this helps!
In my application I need to return the relative mouse position from an SDL_Surface, the problem is the mouse position that gets returned is relative to the SDL window and not the SDL_Surface. I guess my question is what is the easiest / most effective way of doing this. Any questions just ask. Thanks.
EDIT: Sorry I should have explained better, I have SDL_Surface* Surf_Display; on Surf_display there is an Image say its 1000 x 1000, So in order to see the image on a 600 x 600 window I have a camera that I can move around ( really its the surface that moves not the camera ) for instance to look right of the image I move the surface -1 left if that makes sense. So my problem is when I click my mouse on a part of the surface(image) my mouse returns the position that the mouse compared to where the cursor is in the window, what i'm wanting is so that it returns the position of the cursor compared to where it is on the surface(image)
I hope that better explains the situation. Thanks again
Just add(or subtract, depending on how you look at it) the offset to the mouse coordinates. So you're drawing the surface something like this:
SDL_Rect dest_rect = { -camera.x, -camera.y };
SDL_BlitSurface(image_surface, NULL, screen_surface, &dest_rect);
I don't know if you're using event based mouse handling, or if you're using SDL_GetMouseState, but either way, you would simply add camera.x and camera.y to the mouse position, for example:
int x, y;
SDL_GetMouseState(&x, &y);
x += camera.x;
y += camera.y;
I'm using GLUT and developing a FPS game. I need a way to trap the mouse so that the camera continues to move because right now when the mouse position exceeds the monitor limit, there is no way to calculate change in X or change in Y. How can I 'trap' the mouse with GLUT?
Thanks
I'd recommend using a ready-made engine like OGRE 3D instead, but if you really want to reinvent the wheel, here's how...
In all cases I'm aware of, PC FPS games "trap" the pointer by registering a mouse motion callback, noting the relative motion, and then warping the pointer back to the center of the window.
Here's some code I wrote to add mouse input to a sample ping-pong table in an OpenGL with C++ course a year or two ago:
void resetPointer() {
glutWarpPointer(TABLE_X/2, TABLE_Y/2);
lastMousePos = TABLE_Y/2;
}
void mouseFunc(int sx, int sy) {
if (!started) { return; }
int vertMotion = lastMousePos - sy;
lastMousePos = sy;
player1.move(vertMotion);
// Keep the pointer from leaving the window.
if (fabs(TABLE_X/2 - sx) > 25 || fabs(TABLE_Y/2 - sy) > 25) {
resetPointer();
}
}
// This goes in with your "start new game" code if you want a menu
resetPointer();
glutSetCursor(GLUT_CURSOR_NONE);
glutPassiveMotionFunc(mouseFunc);
It only tracks vertical motion, but adding horizontal is trivial.