Libgdx Player rotation messing up - java

I'm trying to program a player that rotates towards the mouse and travels towards the mouse at a certain speed. I am using an orthographic camera, however as soon as I set the camera's position to equal the players position, the player rotation stops working and goes all over the place. I believe it might have something to do with the mouse coordinates using the screen and not the world x and y. I have tried unprojecting Gdx.inout.getY/X to no prevail. Any help is much appreciated.
I am using this code to follow player:
cam.position.x = player.getX();
cam.position.y = player.getY();
cam.update();
And this code for rotation:
float mouseX = Gdx.input.getX();
float mouseY = (480 - Gdx.input.getY());
float originX = getWidth() / 2 + position.x;
float originY = getHeight() / 2 + position.y;
double angle = Math.atan2(mouseY - originY, mouseX - originX) * (180/Math.PI) + 90;
if (angle < 0)
angle += 360;
rotation = (float) angle;
direction.x = mouseX - position.x;
direction.y = mouseY - position.y;
double hyp = Math.sqrt(direction.x * direction.x + direction.y * direction.y);
direction.x /= hyp;
direction.y /= hyp;
position.x += direction.x * 2;
position.y += direction.y * 2;

Have you tried projecting (or unprojecting) the points?
ViewPort viewPort = new ... // which ever ViewPort you're using
Vector2 worldPoint = new Vector2(x, y);
Vector2 projected = viewPort.project(worldPoint);
or
Vector2 screenPoint = new Vector2(x, y);
Vector2 unprojected = viewPort.unproject(screenPoint);

Related

Orbit controls make scene disappear after a while

I am using JOGL to build a point cloud viewer and I have implemented my own orbit controls. It works very well for a while, but at some point (I think after dragging the mouse left and right very quickly) the scene completely disappears. Here is my code:
public void mouseDragged(MouseEvent e) {
if (oldX < 0.0005 && oldY < 0.0005) {
// when the mouse drag starts initially
oldX = e.getX();
oldY = e.getY();
} else {
float differenceX = e.getX() - oldX;
float differenceY = e.getY() - oldY;
oldX = e.getX();
oldY = e.getY();
float speedX = differenceX / 2;
float speedY = differenceY / 2;
Vector3f velocityX = new Vector3f();
Vector3f velocityY = new Vector3f();
Vector3f oldTarget = camera.getTarget();
Vector3f cameraRight = new Vector3f();
// getting right vector of the camera in the world space
camera.getDirection().cross(camera.getWorldUp(), cameraRight);
/* moving the camera first along its right vector
* then setting its target to what it was originally
* looking at */
cameraRight.mul(-speedX, velocityX);
camera.translate(velocityX);
camera.setTarget(oldTarget);
/* moving the camera second along its up vector
* then setting its target to what it was originally
* looking at */
camera.getUp().mul(-speedY, velocityY);
camera.translate(velocityY);
camera.setTarget(oldTarget);
}
}
I first thought that it would be because when the camera direction vector and the world up vector are identical, the camera right vector (cross product between the two) would be zero, but that would only mean for the controls to lose one dimension of movement; this should not cause the entire scene to go away.
The idea I originally came up with distanced the camera from its point of focus with each rotation (at some point beyod the far plane). The solution to this problem is to implement the orbit controls using the polar coordinate system. As such, in your mouseDragged() method:
if (oldX < 0.0005 && oldY < 0.0005) {
oldX = e.getX();
oldY = e.getY();
} else {
float differenceX = e.getX() - oldX;
float differenceY = e.getY() - oldY;
oldX = e.getX();
oldY = e.getY();
// getting the current position of the camera in the spherical coordinate system
Vector3f sphericalCoords = MathUtils.toSphericalCoords(camera.getPosition());
float speedY = (float)Math.toRadians(differenceY / 4.0f);
float speedX = (float)Math.toRadians(differenceX / 4.0f);
// adding speedY to the theta angle and speedX to the phi angle
sphericalCoords.add(new Vector3f(0, speedY, speedX));
// making sure the angles are not outside the [0, 2 * PI] interval
polarCoords.y = MathUtils.wrapTo2Pi(sphericalCoords.y);
polarCoords.z = MathUtils.wrapTo2Pi(sphericalCoords.z);
// updating the position of the camera
camera.setPosition(MathUtils.toCartesianCoords(sphericalCoords));
}

Rotate line by specified angle (Java/ Android)

this is a more math related question.
In my android app I have a canvas that draws a line from start to endpoint.
I also have an angle attribute to rotate the line.
I tried to apply the code bellow to my cocept, but it jumps around weirdly, not pointing in the direction it is supposed to. (0deg = horizontal line)
//Coordinates for P1 and P2
int startx = 0;
int starty = 66;
int endx = 420;
int endy = 66;
//Alpha
float angle = 0.000F;
final float radius = 209.500F;
final float extra_radius = 20.000F; //required later - don't mind it
private void reCal(float[] vals) {
float xAcc = vals[0]*(-1);
float yAcc = vals[1]*(-1);
angle = yAcc / 10.000F * 90.000F;
final float rRadius = radius + extra_radius;
startx = (int) (radius - Math.cos(angle) * rRadius); //left
endx = (int) (radius + Math.cos(angle) * rRadius); //right
starty = 66 + (int) (Math.sin(angle) * rRadius); //top
endy = 66 - (int) (Math.sin(angle) * rRadius); //bot
}
Are their any type conversions that might cause this, or is my math wrong?
UPDATE:
I looked at Math.cos(angle) and Math.sin(angle) at runtime.They jump around between 0 and 1, even if angle is only changed by a little amount.
Now I am wondering: DO THE METHODS TAKE RAD OR DEG AS PARAMETER? (I need deg, obviously)
if you want to rotate a line starting at [cx, cy] and length of dx, use that code snippet:
canvas.save();
canvas.rotate(angle, cx, cy);
canvas.drawLine(cx, cy, cx + dx, cy, paint);
canvas.restore();

Rendering 3-d lines in Java?

Ok, I have a little problem: I'm trying to code an engine capable of rendering 3d lines onto a 2d plane, but I'm having some trouble with it.
I have a point3d class, which takes x y and z coords, a line3d class, which takes two point3d endpoints, and I have a world object containing an arraylist of line3d's. I also have point2d and line2d, which are just like their 3d counterparts, except that they lack a z coordinate.
Here's the render method:
public void render(){
for(Line3d line : world.lines){ //for every 3d line in the world
panel.l3d(line, world.main); //render that line
}
panel.repaint(); //repaint the graphic
}
Which calls upon the l3d method:
public void l3d(Line3d line, Camera view){
Point2d start = p3Top2(line.start, view), end = p3Top2(line.end, view); //convert 3d points to 2d points
if(start==null || end==null)return; //if either is null, return
lineAbs(new Line2d(start, end)); //draw the line
}
Which calls upon p3Top2:
public Point2d p3Top2(Point3d point, Camera view){ //convert 3d point to 2d point on screen
int relativeZed = point.z - view.z; //difference in z values between camera and point
if(relativeZed <= 0)return null; //if it's behind the camera, return
int sx, sy, ex, ey, tx, ty; //begin declaring rectangle formed from extending camera angle to the z coord of the point(angle of 1 = 90 degrees)
sx = (int) (view.x - (width / 2) - relativeZed * (width * view.angle)); //starting x of rectangle
ex = (int) (view.x + (width / 2) + relativeZed * (width * view.angle)); //ending x
sy = (int) (view.y - (height / 2) - relativeZed * (height * view.angle)); //starting y
ey = (int) (view.y + (height / 2) + relativeZed * (height * view.angle)); //ending y
tx = point.x - sx; //difference between point's x and start of rectangle
ty = point.y - sy; //same for y
float px = (float)tx / (float)(ex - sx), py = (float)ty / (float)(ey - sy); //px and py are the ratios of the point's x/y coords compared to the x/y of the rectangle their in
return new Point2d((int)(px * width), (int)(py * height)); //multiply it by the width and height to get positions on screen
}
And also on lineAbs:
public void lineAbs(Line2d line){
Point2d start = line.start;
Point2d end = line.end;
if(start.x>end.x){
start = line.end;
end = line.start;
}
int y = start.y; //starting y point
int white = 0xffffff;
for(int x = start.x; x<end.x; x++){ //for each x in the line
if(x < 0 || y < 0 || x > canvas.getWidth() || y > canvas.getHeight())continue; //if the point is outside of the screen, continue
y += line.getSlope().slope; //increment y by the slope
canvas.setRGB(x, y, white); //draw the point to the canvas
}
}
'canvas' is a BufferedImage being drawn to the screen. With an arbitrary camera and angle of 1, as well as a few arbitrary lines thrown in, I do see each line, but they don't appear to be rendered properly. For example, when I have three point3d's as vertices, and three lines, each with a different combination of two of the points, the lines don't appear to meet at all, although each one is visible.
I suspect the issue is in my p3Top2, but I'm not sure where, can you tell?

Shoot to the mouse direction

The problem:
I've got this "Shot" class. In the code, the target variables are the mouseX and mouseY.
So when i click the mouse button, my player class will create a new shot object.
But the shooting is inaccurate.
How can i calculate the correct dx and dy?
If i add the dx and dy to the "bullet's" x and y, the bullet will move to the mouse's direction.This is what i want. The mouse position is stored in targetX and targetY, when the object is created. This is the point what the oval wants to reach.
Links:
The game (finished)
The code (from Shot.java):
public class Shot extends Entity {
private float targetX, targetY;
public Shot(World world, float x, float y, int width, int height, Color color, float targetX, float targetY) {
super(world, x, y, width, height, color);
this.targetX = targetX;
this.targetY = targetY;
}
#Override
public void render(GameContainer gc, Graphics g, Camera camera) {
g.setColor(color);
g.fillOval(x - camera.getX(), y - camera.getY(), width, height);
}
#Override
public void update(GameContainer gc, int delta) {
float dx = targetX - x;
float dy = targetY - y;
x += dx * delta * .001f;
y += dy * delta * .001f;
}
}
I tried this, but still not work:
#Override
public void update(GameContainer gc, int delta) {
float length = (float) Math.sqrt((targetX - x) * (targetX - x) + (targetY - y) * (targetY - y));
double dx = (targetX - x) / length * delta;
double dy = (targetY - y) / length * delta;
x += dx;
y += dy;
}
I did it! Here is my solution:
The problem was that, the target was the window's mouse position, and not the world's mouse position.
This is how i calculated the world's mouse positions:
float mouseWorldX = x + (mouseX - screen_width / 2); // x = player's x position
float mouseWorldY = y + (mouseY - screen_height / 2); // y = player's y position
This is code from my game at the moment is used to move a unit to the mouse when the right mouse button is pressed:
length = Math.sqrt((target_X - player_X)*(target_X - player_X) + (target_Y - player_Y)*(target_Y - player_Y)); //calculates the distance between the two points
speed_X = (target_X - player_X) /length * player_Speed;
speed_Y = (target_Y - player_Y) /length * player_Speed;
This will move an object to the target in a line at a set speed.
Edit: this is the actual code right from my game
if(input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))
{
length = (float) Math.sqrt((player_waypoint_X - player_X)*(player_waypoint_X - player_X) + (player_waypoint_Y - player_Y)*(player_waypoint_Y - player_Y));
velocityX = (float) (player_waypoint_X - player_X) /length * (float) PlayerStats.player.db_player_Speed;
velocityY = (float) (player_waypoint_Y - player_Y) /length * (float) PlayerStats.player.db_player_Speed;
player_waypoint_X = input.getMouseX() - 2;
player_waypoint_Y = input.getMouseY() - 2;
}
For testing purposes the velocity's are defined in the init method along with length. Every time the right mouse is pressed the waypoints's X and Y are changed to the mouse location.
I learned this from this question
velocity calculation algorithm.
in order to make the bullets not all change direction every shot, create an array list so that each bullet fired has its own x and y velocity

Logic for analog stick produces a square instead of a circle

I'm trying to simulate an analog stick on a mobile platform.
I calculate a stick vector which based on the position of the finger and the radius of the stick returns a value from -1 to 1.
public void calcStickVector(float x, float y)
{
float cx = getCenterX();
float cy = getCenterY();
float distX = x - cx;
float distY = y - cy;
distX /= getRadius();
distY /= getRadius();
distX = JMath.clamp(-1.0f, 1.0f, distX);
distY = JMath.clamp(-1.0f, 1.0f, distY);
stickVector.x = distX;
stickVector.y = distY;
}
public RectF getInnerStickRect()
{
float r = getInnerRadius();
float cx = getCenterX() + (getRadius() * getStickVector().x);
float cy = getCenterY() + (getRadius() * getStickVector().y);
innerStickRect.left = cx - r;
innerStickRect.top = cy - r;
innerStickRect.right = cx + r;
innerStickRect.bottom = cy + r;
return innerStickRect;
}
It almost works, but visually the inner stick, when moved around seems to form a square rather than going around in a circle. Is there something wrong with my logic?
Thanks
As it is, you really are making a box with 1's as the corners. You need to normalize the vector(divide x and y by distance) instead of dividing by radius and clamping.
double dist = Math.sqrt(distX*distX) + (distY*distY));
distX /= dist;
distY /= dist;

Categories

Resources