JBox2D Coordinates Don't Match - java

Working on a Jbox2D program I created 2 objects a rectangle at (0,10) meters and 10 Meters Wide and 1 meter wide, and a Ball at (1,0) that has a radius of 0.5f Meters
//in RectangleObject Class
PolygonShape cs = new PolygonShape();
cs.setAsBox(width, height);
//In CircleObject Class
CircleShape cs = new CircleShape();
cs.m_radius = radius;
When my program runs the ball moves toward the platform and hits the rectangle like I expected but the numbers I get back are not what I expect
BallX[0] : 1
BallY[0] : 7.9964995
RectX[0] : 1
RectY[0] : 10
If the X and Y are calculated from the center of the ball then the ball should only be 0.5 away from the box at Y = 9.5. even if it uses the Diameter it should still be at most 1 meter away at Y = 9.
anyone know why its calculating the Y to be 2 meters away when the Radius is only 0.5?

The arguments for the polygon shape are "half-width" and "half-height". It's one of the strange carry-overs from box2d (see the manual here), and not the most intuitive behavior. Try:
cs.setAsBox(width / 2, height / 2);

Related

How to calculate a point out of an angle and a distance?

I searched and implemented things from this forum, it doesn't come out right.
What I'm trying to achieve is to calculate a spawnPoint for player bullets relative to his position and rotation.
The spawnPoint should be and his X + his width (the player is set to point to the right by default) and y + height/2 (to spawn from his center on the Y axis).
This is what I got from this forum:
this.bulletSpawn.x = (float)(this.position.x + this.width/2 + this.width * Math.cos(rotation));
this.bulletSpawn.y = (float)(this.position.y + this.height/2 + this.height/2 * Math.sin(rotation));
The rotation is in Radians. The this is the Player class.
Images showing what I expect to happen:
Original Position
Expected Behaviour
The red dot is the spawnPoint I'm trying to calculate knowing the player position and rotation.
The player Sprite is what rotates, and it rotates related to his center x and y, which is done with a lib, i do not have these variables. The entire arrow would be the player , the arrow direction is where the player is pointing at, and the red dot would be the bulletSpawn point (or the expected one)
Using the code I posted, the bullets seem to be spawning from somewhere else. Even at the beggining they have an offset and when I rotate the player the spawnPoint seems to be relative to a different origin than what I'm expecting.
This is the bullet position code:
position.x = holder.bulletSpawn.x - (float)(this.width/2 * holder.rotation);
position.y = holder.bulletSpawn.y - (float)(this.height/2 * holder.rotation);
This is inside the Bullet class. The position variable is a Vector2 of bullet, and holder is the player instance. This code is merely to give an offset for the bullet to spawn at the center of its own size
I added some fixes related to the comments, but the bullets still have a tiny offset that looks wrong at certain angles.
Basically the distance i want to get is the width of the player, and his center y which is height/2.
Let's initial position is X0, Y0, rotation is about center point CX, CY, and rotation angle is Theta. So new position after rotation is:
NX = CX + (X0-CX) * Cos(Theta) - (Y0-CY) * Sin(Theta)
NY = CY + (X0-CX) * Sin(Theta) + (Y0-CY) * Cos(Theta)
This equations describe affine transformation of rotation of arbitrary point about center point, and affine matrix is combination of translation, rotation, and back translation matrices.
About center CX, CY - you wrote
it rotates related to his x and y origin at his bottom left
About initial point coordinate - for bullet it seems to be
X + Width, Y + Height/2
Swift extension:
extension CGSize {
static func offsetFrom(angle:CGFloat, distance:CGFloat) -> CGSize {
let rad = angle * CGFloat.pi / 180
return CGSize(width: sin(rad) * distance, height: cos(rad) * distance)
}
}

libGDX cone rotation while maintaing location in X,Y,Z

I am trying to create some sort of "lighthouse" effect by creating a cone and rotating it around the X/Y. The result "runs off" on the Z axis and is also wrong on the Y/X axis if there is a combination of both a Yaw and Pitch degrees.
(The Z axis goes from right to left, X towards the screen, Y upwards).
The yellow cone is the effect. it starts as the see-through cone.
This is hoe the x,y,z locations of the cone are set:
float c = this.height/2;
this.locationX = player.getPosition().x - c*((float)Math.sin(Math.toRadians(tiltOnY)));
this.locationY = player.getPosition().y + c*((float)Math.sin(Math.toRadians(tiltOnX)));
this.locationZ = player.getPosition().z-c;
where height is the height of the cone, and tilt starts at 0 and is added or reduced (as a result of input) with module of 360 degrees.
This is the code in render:
inst = new ModelInstance(this._game_.viewConeModel);
inst.transform.setToTranslation(cone.getX(),cone.getY(),cone.getZ())
.rotate(Vector3.Y,cone.getTiltOnY()).rotate(Vector3.X,cone.getTiltOnX()).rotate(Vector3.X,90);
this._game_.modelBatch.render(inst,this._game_.environment);
The desired result is that the point of the cone remains in the same location, but the cone itself rotates by the tilts on X and Y axis.

How to make a circle move in circles?

Circle c1 = new Circle(20);
c1.relocate(200,200); //Set X and Y
What I want to do is make the circle move in circles around an invisible center of rotation. How can that be achieved?
Thanks.
Edit: I have extremely poor trigonometry skills.
You can use equations for a point on a circle using polar coordinates:
circle_x = rot_center_x + radius * cos(angle)
circle_y = rot_center_y + radius * sin(angle)
Using this you'll get a center point for your new circle. Then you just need to increase (counter clock wise) or decrease (clockwise) your angle, blank screen and draw the circle again.
The angle for trigonometric function is in radians, you have 2*pi radians in a full circle. So if you want angle zero degrees, put in 0. For 90 degrees, put in pi/2.0.
For any other angle use this conversion formula:
angle_rad = pi/180.0 * angle_degrees
If you want to time your rotation you have to choose the angular speed of rotation omega.
omega = 2*pi*f
where f is frequency of rotation, for example f=1Hz means your object will rotate in full circle after one seecond. Omega is in radians per second, so if you have omega 10 radians, then your object will rotate 10 radians during one second, or 100 radians during 10 seconds.
Now you have to determine how much angle you need to add each frame of animation:
ang_inc = omega / fps_avg;
ang += ang_inc;
where fps_avg is measured average of frames per second.

JSlider-Advice needed [duplicate]

I have a problem with JSlider in Java I have drawn a circle A, and I want to put ANOTHER circle B inside the first circle A. I want to place the CENTRE of the second circle B at the same coordinate with the centre of the first circle A, and then I want to use JSlider to INCREASE or DECREASE the radius of circle B. The trouble is, when you increase or decrease the slider, the CENTRE of circle B does not stay aligned with the centre of A. Basically, I want two circles with the SAME centre. Can someone point out my mistake, please?
slider1 = new JSlider(JSlider.HORIZONTAL,10,100,10);
window.add(slider1);
slider1.addChangeListener(this);
Graphics paper = panel.getGraphics();
int slider1Value = slider1.getValue();
paper.setColor(Color.white);
paper.fillRect(0, 0, 500, 500);
paper.setColor(Color.pink);
paper.fillOval(20,20,100,100); // this is circle A
paper.drawOval(60,60,slider1Value,slider1Value); // this is circle B slider
Because you have to change position of top-left "corner" of circle. If you change radius, the circle is bigger/smaller so it's obvious if you don't change position of top-left cornet, centers of 2 circles won't be aligned
Theory
From Graphics.drawOval() javadoc. When you draw a circle their (x,y) coordinates are not its center but its top-left corner. In order to make your B circle aligned with A circle, you need to calculate its (x,y) coordinates relatives to the last one:
Circle A: (x,y) = (20,20); diameter = 100 ==> radius = 50; center = (x + radius, y + radius) = (70,70)
Well, you have your center now: (70,70). Now, slider1Value is your new radius so you need to calculate circle B (x,y) coordinates:
Circle B: center = (70,70); (x,y) = (centerX - radius, centerY - radius) = (70 - slider1Value, 70 - slider1Value)
Finally, circle B width and height are equals to its diameter:radius * 2 = slider1Value * 2.
Facts
Make this change and it will work like a charm:
paper.drawOval(70 - slider1Value, 70 - slider1Value, 2*slider1Value, 2*slider1Value);

How to position a Node along a circular orbit around a fixed center based on mouse coordinates (JavaFX)?

Im trying to get into some basic JavaFX game development and I'm getting confused with some circle maths.
I have a circle at (x:250, y:250) with a radius of 50.
My objective is to make a smaller circle to be placed on the circumference of the above circle based on the position of the mouse.
Where Im getting confused is with the coordinate space and the Trig behind it all.
My issues come from the fact that the X/Y space on the screen is not centered at 0,0. But the top left of the screen is 0,0 and the bottom right is 500,500.
My calculations are:
var xpos:Number = mouseEvent.getX();
var ypos:Number = mouseEvent.getY();
var center_pos_x:Number = 250;
var center_pos_y:Number = 250;
var length = ypos - center_pos_y;
var height = xpos - center_pos_x;
var angle_deg = Math.toDegrees(Math.atan(height / length));
var angle_rad = Math.toRadians(angle_deg);
var radius = 50;
moving_circ_xpos = (radius * Math.cos(angle_rad)) + center_pos_x;
moving_circ_ypos = (radius * Math.sin(angle_rad)) + center_pos_y;
I made the app print out the angle (angle_deg) that I have calculated when I move the mouse and my output is below:
When the mouse is (in degrees moving anti-clockwise):
directly above the circle and horizontally inline with the center, the angle is -0
to the left and vertically centered, the angle is -90
directly below the circle and horizontally inline with the center, the angle is 0
to the right and vertically centered, the angle is 90
So, what can I do to make it 0, 90, 180, 270??
I know it must be something small, but I just cant think of what it is...
Thanks for any help
(and no, this is not an assignment)
atan(height/length) is not enough to get the angle. You need to compensate for each quadrant, as well as the possibility of "division-by-zero". Most programming language libraries supply a method called atan2 which take two arguments; y and x. This method does this calculation for you.
More information on Wikipedia: atan2
You can get away without calculating the angle. Instead, use the center of your circle (250,250) and the position of the mouse (xpos,ypos) to define a line. The line intersects your circle when its length is equal to the radius of your circle:
// Calculate distance from center to mouse.
xlen = xpos - x_center_pos;
ylen = ypos - y_center_pos;
line_len = sqrt(xlen*xlen + ylen*ylen); // Pythagoras: x^2 + y^2 = distance^2
// Find the intersection with the circle.
moving_circ_xpos = x_center_pos + (xlen * radius / line_len);
moving_circ_ypos = y_center_pos + (ylen * radius / line_len);
Just verify that the mouse isn't at the center of your circle, or the line_len will be zero and the mouse will be sucked into a black hole.
There's a great book called "Graphics Gems" that can help with this kind of problem. It is a cookbook of algorithms and source code (in C I think), and allows you to quickly solve a problem using tested functionality. I would totally recommend getting your hands on it - it saved me big time when I quickly needed to add code to do fairly complex operations with normals to surfaces, and collision detections.

Categories