I have a school assignment where I'm supposed to (among other things) rotate a polygon. I can not use any premade rotate functions, so I have an array of points. The array is set up like this:
intArray[2][amount_of_points] where intArray[0] equals the points x coordinate, and intArray[1] holds the y coordinates.
//x=pivot point x coordinate, y = pivot point y coordinate.
public int[][] rotate(int[][]matrix,int x, int y, double degrees){
double s=Math.sin(degrees);
double c=Math.cos(degrees);
for (int i=0;i<matrix.length;i++){
//translate to origin
int px=matrix[0][i]-x;
int py=matrix[1][i]-y;
//rotate
double xnew = (px*c)-(py*s);
double ynew = (px*s)+(py*c);
//translate back
px=(int)((xnew+x)+0.5);
py=(int)((ynew+y)+0.5);
matrix[0][i]=px;
matrix[1][i]=py;
}
This is my code so far, and it is definitely not working out for me. I tried to trim the code as much as I could. Any help would mean a lot!
edit: I'm not getting any errors when I run the code, no exceptions etc. The only problem is that the polygon isn't rotating the way I intend it to.
I've made a test polygon:
polyArray = new int [2][3];
polyArray[0][0]=400;
polyArray[1][0]=200;
polyArray[0][1]=300;
polyArray[1][1]=500;
polyArray[0][2]=500;
polyArray[1][2]=500;
Which I draw in a JPanel, then I run this array through the rotation method like this:
polyArray=mm.rotate(polyArray, polyArray[0][0], polyArray[1][0], Math.PI);
Using the top point as pivotpoint. The whole polygon is then deformed.
Although still not very clear on question, I feel your problem is with the loop.
matrix.length is 2. So, the code never uses these :
polyArray[0][2]=500;
polyArray[1][2]=500;
If you change the condition as below, it should work :
for (int i=0;i<matrix[0].length;i++)
Related
I am making a 3D Java game but i have got problems when rotating a hitbox. I, upon this point, only used a method which detects if a Vector3f is in a box.
But in my game I want to rotate houses, for example, so that method won't work. I could use circulair hitboxes but that wouldn't work for every instance of objects.
So far i have used this simple calculation to detect if a location is in a hitbox.
public boolean isinbox(Vector3f pos) {
Vector3f entPos = ent.getPosition();
float x1 = entPos.x + xOffset;
float z1 = entPos.z + zOffset;
float y1 = entPos.y + yOffset;
float x2 = entPos.x - xOffset;
float z2 = entPos.z - zOffset;
float y2 = entPos.y;
return pos.x < x1 && pos.x > x2 && pos.z < z1 && pos.z > z2 && pos.y > y2 && pos.y < y1;
}
This works in many ways, but I can't figure out how to rotate them and still be able to detect it. The xOffset is the ofset if side a to the center and negative side b to the center.
How would I be able to rotate a hitbox and detect if an Vector is in it?
There are a couple of ways of getting around this issue and one (or more) ways of solving this issue:
Solving It
SAT Collision
SAT Stands for Separating Axis Theorem.
TutsPlus and MetaSoftware are great websites to learn how it works and how to implement it.
The Separating Axis Theorem (SAT for short) essentially states if you are able to draw a line to separate two polygons, then they do not collide. It's that simple. (gamedevelopment.tutsplus.com)
Here is the basic idea:
It can also be used for more complex shapes:
Getting Around It
AABB Collision
This is done by assuming that collisions will only ever happen on the X/Y axis (never on an axis defined by an arbitrary line).
Here is an example of what this looks like:
Therefore, you must define this axis-aligned hitbox by using the minimum X-and-Y values and the maximum X-and-Y values of the original box.
Circle Collision
This is a much simpler collision check which only detects when two objects are within a certain distance of each other.
Here is an example of what this looks like:
The way this works is that if the distance between the two objects is less than the sum of each circle's radius, then the objects are colliding.
Using an External Library
Bullet Physics
Box2D
Im developing simple game. I have cca. 50 rectangles arranged in 10 columns and 5 rows. It wasn't problem to put them somehow to fit the whole screen. But when I rotate the canvas, let's say about 7° angle, the old coordinates does't fit in the new position of the coordinates. In constructor I already create and define the position of that rectangles, in onDraw method I'm drawing this rectangles (of course there are aready rotated) bud I need some method that colliding with the current rectangle. I tried to use something like this (i did rotation around the center point of the screen)
int newx = (int) ((x * Math.cos(ROTATE_ANGLE) - (y * Math.sin(ROTATE_ANGLE))) + width / 2);
int newy = (int) ((y * Math.cos(ROTATE_ANGLE) + (x * Math.sin(ROTATE_ANGLE))) + height / 2);
but it doesn't works (becuase it gives me absolute wrong new coordinates). x and y are coordinates of the touch that I'm trying to calculate new position in manner of rotation. ROTATE_ANGLE is the angle of rotation the screen.
Does anybody know how to solve this problem, I already go thorough many articles, wiki, wolframalpha categories but not luck. Maybe I just need some link to understand problem more.
Thank you
You use a rotation matrix.
Matrix mat = new Matrix(); //mat is identity
mat.postRotate(ROTATE_ANGLE); //mat is a rotation matrix of ROTATE_ANGLE degrees
float point[] = {10.0, 20.0}; //create a new float array representing the point (10, 20)
mat.mapPoints(point); //rotate the point by the requested amount
Ok, find the solution.
First it is important to convert from angle to radian
Then I personly need to negate that radian value.
That's all, this solution is correct
So I am making a tetris game and one of the problems I am running into is piece rotation. I know I can just hard code it but thats not the right way to do it. The way the system works is I have a 2d array of an object 'Tile' the 'Tile' object has x, y coords, boolean isActive, and color. The boolean isActive basically tells the computer which tiles are actually being used (Since tetris shapes are not perfect quadrilaterals).
Here is how I would make a shape in my system:
public static Tile[][] shapeJ() {
Tile[][] tile = new Tile[3][2];
for (int x = 0; x < 3; x++) {
for (int y = 0; y < 2; y++) {
tile[x][y] = new Tile(false, Color.blue);
}
}
tile[0][0].setActive(true);
tile[0][0].setX(0);
tile[0][0].setY(0);
tile[1][0].setActive(true);
tile[1][0].setX(50);
tile[1][0].setY(0);
tile[2][0].setActive(true);
tile[2][0].setX(100);
tile[2][0].setY(0);
tile[2][1].setActive(true);
tile[2][1].setX(100);
tile[2][1].setY(50);
return tile;
}
Now I need to rotate this object, I do not know how to do that without hard coding the positions. There has to be an algorithm for it. Can anyone offer some help?
A good way that I used when writing a tetris clone is to use rotational matrices:
http://en.wikipedia.org/wiki/Rotation_matrix
So the coordinates (x',y') of the point (x,y) after rotation are:
x' = x*cos(theta) - y*sin(theta);
y' = x*sin(theta) + y*cos(theta);
Where theta is the angle of rotation(+-90 degrees or +-PI/2 radians for the java functions that I know)
In this case the blocks are rotated around the origin (0, 0) so you either have to have the coordinates of the block in special "block space" that then gets transposed onto "field space" or you take away the offset of the block so that it is centered at the origin every iteration.
I hope that helps, I am happy to answer specific questions in the comments.
I'm trying to use this method to rotate a point:
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(90), 1, 2);
double[] pt = {0, 1};
at.transform(pt, 0, pt, 0, 1);
int x = (int)pt[0];
int y = (int)pt[1];
The expected result is x=0 and y=3 because we are rotating 90* clockwise, however the output is currently x=2 and y=1;
Why am I not getting the expected result?
The program is doing nothing wrong. By specifying Math.toRadians(90) as your theta, you are instructing it to rotate counter-clockwise, not clockwise. That is how rotation is defined in trigonometry.
Using -Math.toRadians(90) would get you the correct result.
Also, as a side note, casting the point values to int isn't the best idea for checking your code. Double-precision trigonometry is prone to very minor errors, and so a tiny bump in the wrong direction would get you the wrong integers. (I.e., 2.99999999995 would be cast to 2)
(int) Math.round(value) is much safer
Actually, you're rotating anti-clockwise. The Javadoc says:
Rotating by a positive angle theta rotates points on the positive X axis toward the positive Y axis
See the Javadoc
Im trying to get a rectangle to move from a fixed location, to a click point in my game. I have it working to the point that im getting good coordinates from the e.getX and e.getY methods in the mouse listener class. I also have the rectangle moving in straight lines to the side or up and down by increasing and decreasing the positionX and Y values but i need a way to move it to any point that i click on, basically i need to set the change in x and y. The way i was thinking is to compute the rise and run of the line from the click points and the start point and then set the x and y values to the rise and run. If i do it this way, i need a way to decrease the rise and run values down to their lowest terms so it moves fluidly. Or if there is a way im not thinking of that you can offer any guidence that would be helpfull.
How are you drawing it at the moment? Below is a method I used to shoot bullets in a little game that I made/really should finish sometime.
This is by no means all the code you will need, and in some places there are better ways to do things (which I'm sure people will start to tell me in the comments section after :) ) but it should give you a basis to work from.
The one thing missing from this is regulating the speed at which it repaints (fps), sorry but I can't remember the simple way to do this right now (need to get back to my actual job!) Hope it helps.
The barebones of it will be something like this:
//these set out the current position of your rectangle
double recX, reYy, recH, recW;
//this gives something to manage speed
int speed;
public void paintComponent(Graphics g) {
g.drawRectangle(recX,rexY,recH,recW);
}
//here we work out the movement
public void clickedScreen(double x, double y){
double newX = x;
double newY = y;
//calculate the speed to move at
vX = newX - recX;
vY = newY - recY;
//get the distance
length = Math.sqrt((v1*v1)+(v2*v2));
//make it a unit vector
v1 = v1/length;
v2 = v2/length;
}
public moveRec(){
recX = recX+(v1*speed);
recY = recY+(v2*speed);
}
while(true) {
moveRec();
repaint();
}