I wrote a mouse function for the camera.
It works good. But the only problem is at the start, when I do first move with mouse it jumps up-left and then it works good. I don't understand why it happens.
Here the mouse function.
float lastx = 0.0;
float lasty = 0.0;
void mouseMovement(int x, int y)
{
lastx = (float)x - lastx;
lasty = (float)y - lasty;
if((float)x > lastx)
Camera.RotateY((-lastx)*0.01);
else
Camera.RotateY(lastx*0.01);
if((float)y > lasty)
Camera.RotateX(lasty*0.01);
else
Camera.RotateX(-lasty*0.01);
lastx = (float)x;
lasty = (float)y;
Display();
}
I'm guessing, If you're tracking all mouse movement you'll need to either catch when the mouse enters or leaves the window, or simply discard any jumps larger than a certain amount.
Let's say that the mouse leaves the right edge of the window, and reenters the left edge of the window. The code you've shown is going to jump.
Unless there's a reason not to, I'd make the last variables static and add an if statement similar to this(not tested :) )...
void mouseMovement(int x, int y)
{
static float lastx = 0.0;
static float lasty = 0.0;
lastx = (float)x - lastx;
lasty = (float)y - lasty;
if((abs((int)lastx)>10)||(abs((int)lasty)>10)
{
lastx = (float)x;
lasty = (float)y;
return;
}
//the rest remains the same
The logic goes...
Any event it sees, that isn't near the last event it saw, just resets the variables and waits for another event.
That really isn't an elegant solution for a mouse control, but at this point in your coding it is probably understandable, and will do what you want.
Move the cursor to the middle of the screen before you start accepting data. And ensure that lastx and lasty are properly initialized.
I am 90% sure it's FPP camera, and you move the cursor to the middle of the screen manually. So it happens it starts in a down-right corner of the window, then is moved, which reports as a delta. It can also be the fact that lastx and lasty are initialized on first read, and prior to that they contain garbage.
Related
I'm working on Processing language for my assignment. It's an animation. The animation object(a ball) needs to go from top to bottom. I have declared variable as float x,y. Whenever I put if condition to increase size of it by 1 but it's not moving a single inch.
float x;
float y;
size(600, 400)
x = 0.4*width/8;
y = 0.4*height/8;
ellipse( width/2, x, 0.8*width/8, 0.8*width/8);
ellipse( y, height/2, 0.8*height/8, 0.8*height/8);
if(x < height){
x = x+1;
}
if(y < width){
y=y+1;
}
I am expecting the output as- the ball located on top moves towards down and stops at the bottom and the left ball moves to right and stops at the rightmost point.
You're using Processing in "static mode" which means your code runs once and then is done. Nothing happens after you reach the end of your code.
To take advantage of Processing's 60 FPS rendering loop, you need to specify setup() and draw() functions. Something like this:
float circleY;
void setup(){
size(200, 200);
circleY = height/2;
}
void draw(){
background(200);
ellipse(100, circleY, 20, 20);
circleY = circleY + 1;
}
Shameless self-promotion: here is a tutorial on animation in Processing.
I am a beginner in C++ and know SFML. I have read a lot of articles about Sprite rotation towards Mouse and have been able to calculate proper angle of rotation of Sprite using this code:
void Player::changeAngle(double Mx, double My) { // This is for making Player point towards Mouse
double dX = x - Mx; // x and y are global Varibales declared outside
double dY = y - My;
double magnitude = sqrt((dX*dX) + (dY*dY));
double normalizedX = dX / magnitude;
double normalizedY = dY / magnitude;
// This part is for Making Player move to Mouse
Xvelocity = normalizedX * speed; // Xvelocity, Yvelocity and speed are global variables
Yvelocity = normalizedY * speed;
// Rotate towards the Mouse
double angle = ( atan2(dY, dX) ) * 180 / M_PI;
entity.setRotation(angle); // entity is a sf::RectangleShape
}
And, this bit actually worked and the Sprite was rotating properly only before a few days. Now the Sprite is just frozen on the screen, nothing happens. I had not made any changes in that code but I had added a View from the main.cpp.
So here is how I call changeAngle() from the main.cpp :
case Event::MouseMoved : {
Vector2f worldPos = window.mapPixelToCoords(Mouse::getPosition(window), view);
double x = worldPos.x;
double y = worldPos.y;
player.changeAngle(x, y);
break;
}
I tried running the debugger and stepped through the code. I found that the angle is properly calculated and my mouse coordinates are also right. And, to my surprise, the sprite was Rotating now !
I could not understand why, but every time its in debugging mode, the Sprite will rotate. But, it won't rotate while running normally.
Can anyone tell me why and how to fix it so it rotates every time ? Tell me if there is any problem with my code.
Thanks !
How exactly would this be achieved? Here is the code I have so far which just rotates the ship based on where the mouse is, as well as the bullet:
xPos = ship.getPosition().x, yPos = ship.getPosition().y, mousex = sf::Mouse::getPosition(window).x, mousey = sf::Mouse::getPosition(window).y;
if (mousex > 800) mousex = 800; if (mousey > 600) mousey = 600; if (mousex < 0) mousex = 0; if (mousey < 0) mousey = 0;
double angle = atan2(mousey - yPos, mousex - xPos) * (180/3.14159);
ship.setRotation(90+angle);
bullet.setRotation(-90+angle);
So, how would I match the bullet's velocity to be the same as the direction the ship is facing? So that if I fire a bullet it should fire exactly where the ship is looking towards.
What I've tried so far is creating a distance vector from the bullet to the mouse position, and moving the bullet by that distance vector, but of course that would instantly move the bullet to the mouse's position in just 1 frame. It needs to be like a normal velocity that still goes towards the mouse position.
So, as you correctly described what you need is a normalized delta in the direction of the angle.
Either you use the properties of the unity circle and calculate it like
velocity_x = cos(angle)*speed;
velocity_y = sin(angle)*speed;
or you use the approach that you started and do
diff_x = mousex - xPos;
diff_y = mousey - yPos;
magnitude = sqrt(diff_x*diff_x + diff_y*diff_y);
velocity_x = diff_x/magnitude * speed;
velocity_y = diff_y/magnitude * speed;
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!
I am totally stumped on this one. I'm using C++ and SFML 1.6 for a game I'm developing, and I have no bloody idea. How do I make projectiles (like bullets)? I just don't understand it. It could be my lack of sleep but I don't know.
So my question is how do I create a Sprite that moves in a definite direction based on where the mouse is? (Think of a top down shooter with mouse aiming)
Easiest solution:
If the mouse is at Mx,My and the ship is at Sx,Sy then calculate the direction from the ship to the mouse:
Dx=Sx-Mx
Dy=Sy-My
Now normalise D (this means scale it so that it's length is one):
DLen=sqrt(Dx*Dx + Dy*Dy)
Dx/=DLen;
Dy/=DLen;
Now Dx is the distance you want to move the bullet on the x axis in order to get bullet speed of 1.
Thus each frame you move the bullet like so (position of bullet: Bx,By Speed of bullet: Bs [in pixels per millisec] Frame time Ft[in millisec])
Bx=Bx+Dx*Bs*Ft
By=By+Dy*Bs*Ft
This give you a bullet that moves towards the mouse position at a speed independent of the direction of the mouse or framerate of the game.
EDIT: As #MSalters says you need to check for the DLen==0 case when the mouse is directly above the ship to avoid division by zero errors on the normalise
One way to do it is to make the bullet face the mouse and then move it across the x and y axis by using trigonometry to find the hypotinuse from the angle. I don't think i explained this very well, so here the code to make a sprite move from its rotation:
void sMove(sf::Sprite& input,float toMove, int rotation){
bool negY = false;
bool negX = false;
int newRot = rotation;
if (rotation <= 90){
negY = true;
}
else if (rotation <= 180){
//newRot -= 90;
negY = true;
}
else if (rotation <= 360){
newRot -= 270;
negY = true;
negX = true;
}
float y = toMove*cos(newRot*PI/180);
float x = toMove*sin(newRot*PI/180);
if (negY){
y = y*-1;
}
if (negX){
x = x*-1
}
input.move(x, y);
}