I am making a game engine in Java. I am trying to add box collision to my game and this box needs to have the ability to rotate with the player. I have searched and found a formula which is supposed to calculate the new point of a rotated point, however, when I rotate my points they seem to follow a weird out of proportion figure 8 path instead of a circle around the center of my box.
for (Point p : points) {
//Loops through every point on the box (Square)
//top, left, bottom, right
float pointX = p.getX();
float pointY = p.getY();
//rotation as radians
float cos = (float) Math.cos(rotation);
float sin = (float) Math.sin(rotation);
pointX = centerX +(pointX-centerX) * cos + (pointY-centerY) * sin;
pointY = centerY -(pointY-centerY) * cos + (pointX-centerX) * sin;
p.setPos(pointX, pointY);
}
Here is what happens to the box as I rotate my player:
https://gyazo.com/ff801ce8458269c2385e24b2dc5404f5
Any help would be greatly appreciated, I have been tackling this for almost a week now with the same results.
The problem is that you calculate pointY with the new value of pointX.
Thanks to #Imus answer for the proper calculation.
Try:
float pointX = p.getX();
float pointY = p.getY();
//rotation as radians
float cos = (float) Math.cos(rotation);
float sin = (float) Math.sin(rotation);
float newPointX = centerX +(pointX-centerX) * cos + (pointY-centerY) * sin;
float newPointY = centerY +(pointY-centerY) * cos - (pointX-centerX) * sin;
p.setPos(newPointX, newPointY);
Remember that in java the Y axis is pointing downwards.
Not tested myself but you could try the following lines:
pointX = centerX +(pointX-centerX) * cos + (pointY-centerY) * sin;
pointY = centerY +(pointY-centerY) * cos - (pointX-centerX) * sin;
Related
I'm trying to add some distance (e.g. 10px) between a segment (arc) of the pie chart and it's center without success, here's what i've tried so far:
int value = 20; // example
double arcAngle = (value * 360 / 100);
double angle = 360 - (arcAngle / 2); // direction to add the distance to (center of arc)
double newX = pieCenterX + Math.cos(angle * Math.PI / 180.0) * 10;
double newY = pieCenterY + Math.sin(angle * Math.PI / 180.0) * 10;
// then drawing the arc with new x and y
g.fill(new Arc2D.Double(newX, newY, bounds.getWidth(), bounds.getHeight(), startAngle, arcAngle, Arc2D.PIE));
Ideally i should end up with something like that:
I don't know much on how to approach this, so my code was taken from examples i found elsewhere.
Usually zero angle is OX direction (right). So you have to make correction by 90 degrees (if your coordinate system is counterclockwise)
double angle = 90 + 360 - (arcAngle / 2);
I have a method in my android app that looks like this:
//get point after rotation
public static PointF getRotatedPoint(PointF pt,PointF center, float degrees)
{
double angleInRadians = degrees * (Math.PI / 180);
pt.x = (float) (Math.cos(angleInRadians) * (pt.x-center.x) - Math.sin(angleInRadians) * (pt.y-center.y) + center.x);
pt.y = (float) (Math.sin(angleInRadians) * (pt.x-center.x) + Math.cos(angleInRadians) * (pt.y-center.y) + center.y);
return pt;
}
I have a rectangle that I rotate by 45 degrees. I can touch any point on the rotated rectangle and it gives me the touched point I want to get the coordinates of the point if the rectangle wasn't rotated. So I pass in -45 in the degrees argument. Here is how I call it:
getRotatedPoint(touchedPoint, centerOfRectangle,-45);
When I draw the point on the rectangle before it gets rotated, it gives me a result close to the position I touched on the rotated rectangle but off by a pretty big difference.
Here is a picture to explain my problem:
I think this might be a problem with my math so any answers are greatly appreciated.
You are mixing initial and final values in the calculations. You re-assign pt.x:
pt.x = (float) (Math.cos(angleInRadians) * (pt.x-center.x) - Math.sin(angleInRadians) * (pt.y-center.y) + center.x);
which doesn't immediately pose any problems. But the calculation for pt.y relies on the original value of pt.x, not the rotated value:
pt.y = (float) (Math.sin(angleInRadians) * (pt.x-center.x) + Math.cos(angleInRadians) * (pt.y-center.y) + center.y);
Thus just use some temporary variables to hold the initial values.
public static PointF getRotatedPoint(PointF pt,PointF center, float degrees)
{
double x0 = pt.x;
double y0 = pt.y;
double angleInRadians = degrees * (Math.PI / 180);
pt.x = (float) (Math.cos(angleInRadians) * (x0-center.x) - Math.sin(angleInRadians) * (y0-center.y) + center.x);
pt.y = (float) (Math.sin(angleInRadians) * (x0-center.x) + Math.cos(angleInRadians) * (y0-center.y) + center.y);
return pt;
}
does anyone have any tips/ideas on how to calculate Round line joins?
The device I'm working on only supports single width lines.
I am trying to implement basic stroking with only round line joins.
Some things I'm messing with are below.
It's not much, but I hope to get some ideas on how to handle the different cases when two lines join, based on any replies.
Thanks in advance for any help.
I have had some progress with the outer join:
a. Get clockwise order vertices (I get these from flattened glyphs)
b. Grab 3 vertices
c. Compute normal of line A (prevX, prevY) -> (currentX, currentY)
d. Compute normal of line B (currentX, currentY) -> (nextX, nextY)
I compute normals using a left turn on the current clockwise vertices
normal = (deltaY, -deltaX) // Thanks Andreas
Vec2[] computeNormals(float prevX, float prevY, float x, float y, float nextX, float nextY) {
float dx1 = x - prevX;
float dy1 = y - prevY;
float dx2 = x - nextX;
float dy2 = y - nextY;
Vec2 normal1 = new Vec2(dy1, -dx1).normalize();
Vec2 normal2 = new Vec2(dy2, -dx2).normalize();
if (normal1.angleDeg() > normal2.angleDeg()) {
normal2.rot((float) Math.PI);
}
return (new Vec2[] { normal1, normal2 });
}
e. Determine outer join arc angle from atan2(deltaY, -deltaX)
void computeArc(VertexBuffer dest, float x, float y, float arcRadius, Vec2 normal1, Vec2 normal2) {
// Angle from Vecto2D is atan2(y, x)
float angleStart = normal1.angle();
float angleEnd = normal2.angle();
float angleInc = (float) Math.PI / 4f; // Temporary, need to find a way to determine numVertices for a Pen of a given width
while (angleStart > angleEnd) {
angleStart -= (float) (2f * Math.PI);
}
for (float a = angleStart; a <= angleEnd; a += angleInc) {
float vx = x + ((float) Math.cos(a) * arcRadius);
float vy = y + ((float) Math.sin(a) * arcRadius);
dest.addVertex(vx, vy);
}
}
If your device can draw filled circles, you could put a filled circle at the 2 end points, and one at every line joint.
I searched on internet and I saw lots of posts about how to rotate a matrix or an image by 90 or 180 degrees.But how can I rotate a matrix with 12 degrees or 162 degrees?
From:
To:
This image is rotated with ~35 degrees.
As you can see my matrix is the horse image and the circle is the rotation path, and the big rectangle is the new matrix created after rotation.
How can i achieve this? Thanks!
PS: This does not work
int angle=35*Math.PI/180;
int x1 = (int)(x * cos(angle)) - (y * sin(angle));
int y1 = (int)(y * cos(angle)) + (x * sin(angle));
Maybe your code would work if you saved x value before using it to compute y.
deg should be in radian not in degrees: 35*PI/180
you shouldn't compute with integers since cos and sin are between [0,1], think about floats.
float angle = 35*Math.PI/180;
int x1 = round(x * cos(angle) - y * sin(angle));
int y1 = round(y * cos(angle) + x * sin(angle));
Note: casting is huggly.
I'm using swt gc for drawing images. One of the option of my program is to rotate the image. I'm also drawing a rectangle as a border. To rotate I'm using following code:
Transform oldTransform = new Transform(gc.getDevice());
gc.getTransform(oldTransform);
Transform transform = new Transform(GCController.getCanvas().getDisplay());
transform.translate(this.x+width/2, this.y+height/2);
transform.rotate(rotation);
transform.scale(this.scaleX, this.scaleY);
transform.getElements(elements);
transform.translate(-this.x-width/2, -this.y-height/2);
gc.setTransform(transform);
gc.drawImage(image, this.x, this.y);
gc.setTransform(oldTransform);
transform.dispose();
After rotation I would like to calculate positions of corners of my rectangle.
I was trying something like this:
int tx = (this.x+width/2);
int ty = (this.y+height/2);
double rot = rotation * Math.PI/180;
double newX = tx*Math.cos(rot) - ty*Math.sin(rot);
double newY = tx*Math.sin(rot) + ty*Math.cos(rot);
But it does not working as I expected.
I've also tried using transformation matrix which I'm geting into elements array after each transformation:
int tx = (this.x+width/2);
int ty = (this.y+height/2);
double newX = this.x * elements[0] + this.y * elements[2];
double newY = this.x * elements[1] + this.y * elements[3];
But it gives same results as using equations for rotation. Any ideas ?
I've solved it:
int tx = (-width/2);
int ty = (-height/2);
double rot = rotation * Math.PI/180;
double newX = (tx)*Math.cos(rot) - (ty)*Math.sin(rot) + this.x + width/2;
double newY = (tx)*Math.sin(rot) + (ty)*Math.cos(rot) + this.y + height/2;
I had back to 0,0. Make rotation and after rotation translate it back.
You just need to multiply the transformation matrix by the position vector for each of the points of your rectangle.
The Transform class presumably has a method for doing this (would make sense), but I can't find readable "swt gc" API documentation, so I can't tell you what it is.