I need to draw parallel lines between two squares. They can be placed at angle. I need to find out 6 points (3 on square A and 3 on square B) so that lines drawn between them are equally spaced. Thanks
Best you get acquainted with a bit of vector math.
Ideally the lines would orient themselves to the vector between the centers of the two squares (x0, y0) - (x1, y1).
The direction of the three lines is:
x = (x1 - x0)
y = (y1 - y0)
A vector 90° to (x, y), and with size 1:
vn = (y, - x) / sqrt(x² + y²)
So a line 10 px from the center would be
(x0, y0) + 10.vn + µ.(x, y)
Use -10.vn, 0, +10.vn for the three lines.
Determine intersection points with square's edges (µ > 0 for first square).
As it is rewarding for ones self-consciousness, I leave the solution to you. It also is not as readable anymore.
Related
If I have 2 points in 3d space how can I determine if a rectangular prism lies between those 2 points? Also the only information I have about the the rectangular prism is its min and max x, y, and z value. I know I could iterate down the line between those 2 points checking to see if that point is within the rectangular prism but that seems very resource heavy. What I really need is a way to check if a line segment intersects the prism but I am not sure how to do that any ideas?
I found these two resources that seem similar to my question
https://math.stackexchange.com/questions/2134505/how-to-check-if-an-infinite-line-intersects-a-rectangular-prism-in-3d-space
How to check if an infinite line intersects a rectangular prism in 3d space?
Looking at that bottom link it just simply says to find parameters t that intersects the rectangular prism which is obvious but the problem is I dont know how to do that any thoughts?
project your line points and prism edges onto 2D plane that is perpendicular to your line.
On the 2D plane, the two points of line will be just one point and prism edges is just a bunch of connected vertices forming a closed region. check if the one point is within the closed region, this will be easy to do for 2D.
If your point is within then the line intersects the prism in 3D, if not then no.
now there is a case where it is a line segment where the two ends don't touch the prism. In this case you just check point to prism surface distance, there is a equation for that.
Let line segment is defined by two points (X1, Y1) and (X2, Y2).
Let box is defined by ranges xmin..xmax, ymin..ymax, zmin..zmax.
We can write parametric eqiation for line segment, where t is in range 0..1:
X = X1 + t * (X2 - X1)
Y = Y1 + t * (Y2 - Y1)
Z = Z1 + t * (Z2 - Z1)
Box has 6 facets. Let the first one is at xmin. We can substitute xmin in the first equation and find parameter t where line intersects this facet.
xmin = X1 + t1 * (X2 - X1)
t1 = (xmin - X1) / (X2 - X1)
Now check that t1 is in range 0..1. If yes, substitute this t1 value in the second and third equations
Y = Y1 + t1 * (Y2 - Y1)
Z = Z1 + t1 * (Z2 - Z1)
and check that resulting Y and Z lie in ranges ymin..ymax and zmin..zmax respectively.
If yes - line segment does intersect the box
If no, repeat for other faces xmax, ymin and so on.
P.S. Also you can consider special case when line segment is fully inside the box (just check if X1,Y1,Z1 is in box range)
P.P.S. When line is parallel to some coordinate plane, don't check intersections with corresponding faces (for example, if X2-X1==0, you cannot divide by zero, but you just don't need check xmin and xmax faces)
Quick-made Python-like pseudocode for reference:
def DoesSegmentIntersectBox(x1,y1,z1,x2,y2,z2,xmin,xmax,yin,ymax,zmin,zmax):
if zmin<=z1<=zmax and ymin<=y1<=ymax and xmin<=x1<=xmax:
return True #end inside the box
if (x2-x1):
t = (xmin-x1) / (x2-x1)
if 0<=t<=1: #line intersects plane in segment range
y = y1+t*(y2-y1)
if ymin<=y<=ymax: #segment intersects face in y range
z = z1+t*(z2-z1)
if zmin<=z<=zmax: #segment intersects face in z range
return True #segment does intersect face xmin
t = (xmax-x1) / (x2-x1)
#same 6 lines
if (y2-y1):
t = (ymin-y1) / (y2-y1)
if 0<=t<=1:
x = x1+t*(x2-x1)
if xmin<=x<=xmax:
z = z1+t*(z2-z1)
if zmin<=z<=zmax:
return True
t = (ymax-y1) / (y2-y1)
#same 6 lines
if (z2-z1):
t = (zmin-z1) / (z2-z1)
if 0<=t<=1:
x = x1+t*(x2-x1)
if xmin<=x<=xmax:
y = y1+t*(y2-y1)
if ymin<=y<=ymax:
return True
t = (zmax-z1) / (z2-z1)
#same 6 lines
return False
So I have made the following game:
The player moves around freely and shoot bullets which bounce off the walls . I am trying to implement auto aiming. I have tried to implement this using lines, which go around the player.
Now what I am having problems with is calculating where the lines intersect with the walls. I am unsure of how to do this.
I can't use getBounds() as the lines are not 2DRectangles. If anyone has any idea on how I can calculate where the lines intersect with a wall, and return that position, it would be very helpful.
You just need to do the math here.
Suppose your line has start at (startX, startY) and end at (endX, endY). Then using basic grade-school geometry, any point (x,y) on the line satisfies the equation
(y-startY) / (x-startX) = (endY - startY) / (endX - startX)
Of course,
(endY - startY) / (endX - startX)
is just the slope of the line, so set
slope = (endY - startY) / (endX - startX)
and then you have
(y-startY) / (x-startX) = slope
This might be more convenient if you know the starting point (startX and startY for the line) and the angle, as you can just do slope = Math.tan(angle).
For the example of the intersection with a horizontal wall, all points on the edge of the wall have the same y-coordinate, call it wallY. So if x is the x-coordinate of the intersection, you have
(wallY-startY) / (x-startX) = slope
which you can rearrange to
x = startX + (wallY-startY) / slope
so the intersection point is (x, wallY) with x as in the last equation.
If the wall is finite (i.e. it has start and end x points), then the check to see if the line actually intersects the wall is simply x >= wallStartX && x <= wallEndX, assuming wallStartX is the left end of the wall and wallEndX the right end.
If the wall is vertical, then the math is basically the same, except you know the x coordinate on the wall (say x = wallX), and you want to find the y coordinate. So just substitute wallX for x in the first (or fourth) equation and solve for y.
If the wall is not horizontal or vertical, then the math is a little more complicated, though not much. (Left as an exercise for the reader.)
You can use the well tested JTS library for doing such things.
I have seen similar questions on here but just cannot get the math to work.
I have a circle, with two known points on the circumference (x1,y1,x2,y2) with the center of the circle as cx,cy
If I am stood at cx,cy and looking at point x1,y1 how can I tell which way I need to turn to face x2,y2?
So far I am working out the angle to each point
Atan((cx-x1) / (cy-y1))
Atan((cx-x2) / (cy-y2))
I have then tried a simple subtraction, using mod to ensure both are between -2pi and 2pi but I just get some strange answers. It appears the odd results occur when the two points lie above and below the horizontal line drawn through the center point.
But ill be honest I have tried so many things now my head hurts! It does not have to be a computationally fast solution as its only done once. Thanks in advance.
The answer is given to you by the sign of (x1-cx)(y2-cy) - (y1-cy)(x2-cx).
Proof:
Let A be the direction from C to (x1,y1), expressed as an angle measured anticlockwise from the X axis; B be the direction from C to (x2,y2), expressed the same way; and r be the radius of the circle. Then (x2,y2) is to the right of (x1,y1), as seen from C, if A-B lies between 0 and pi or between -2pi and -pi (that is, if sin(A-B) is positive), and to the left if A-B lies between -pi and 0 or between pi and 2pi (that is, if sin(A-B) is negative).
Now,
(x1,y1)=(Cx + r cos A, Cy + r sin A)
(x2,y2)=(Cx + r cos B, Cy + r sin B)
So
(x1-Cx)(y2-Cy) - (y1-Cy)(x2-Cy)
= (r cos A)(r sin B) - (r sin A)(r cos B)
= - r^2 (sin A cos B - cos A sin B)
= - r^2 (sin (A-B))
which has the opposite sign to sin (A-B).
Let's say A1 is the angle between the vector from (cx, cy) to (x1, y1) and the horizontal axis, and A2 is the angle between the vector from (cx, cy) to (x2, y2) and the horizontal axis. When you sit at (cx, cy) and look at the point (x1, y1), the point (x2, y2) is on your right if and only if the angle between the two vectors is less than pi and on your left if and only if the angle is more than pi.
Since the sine of a positive angle is positive from 0 to pi and negative from pi to 2*pi, then it follows that the point is on your right iff sin(A2-A1) > 0 and on your left iff sin(A2-A1) < 0.
If we use the usual trigonometric identity, we have that
sin(A2-A1) = sin(A2) * cos(A1) - sin(A1) * cos(A2)
Then you just have to replace the sine and cosine by their formula with the cartesian coordinates. The denominator is factored out because the points sit on a circle.
Therefore the sign of sin(A2-A1) is the same as the sign of (x2-cx)*(y1-cy) - (x1-cx)*(y2-cy).
I'm not all that good with Maths, so i was hoping some of you guys could help?
I'm trying to make a function to convert mouse coordiantes into a particular tile in an isometric view.
It won't let me post images for a stupid reason, so ill just link the image:
Link
All of the algorithms i have seen so far work with the X & Y axes going diagonal, my game is currently set up like this, and i would like to keep it so.
Is there an algorithm so that if the mouse was at the red dot, it would return the coordinates of the tile that it is sitting on? (6,2)
Thanks in advance!
There is a good start : http://www.java-gaming.org/index.php?topic=23656.0
Enjoy :)
EDIT
Full-trusted "DrDobb's" website, full article on this : http://www.drdobbs.com/parallel/designing-isometric-game-environments/184410055
<0;4>
x <0;3> <1;4>
<0;2> <1;3> <2;4>
<0;1> <1;2> <2;3> <3;4>
<0;0> <1;1> <2;2> <3;3> <4;4>
<1;0> <2;1> <3;2> <4;3>
<2;0> <3;1> <4;2>
y <3;0> <4;1>
<4;0>
I rendered the tiles like above.
the sollution is VERY simple!
first thing:
my Tile width and height are both = 32 this means that in isometric view, the width = 32 and height = 16! Mapheight in this case is 5 (max. Y value)
y_iso & x_iso == 0 when y_mouse=MapHeight/tilewidth/2 and x_mouse = 0
when x_mouse +=1, y_iso -=1
so first of all I calculate the "per-pixel transformation"
TileY = ((y_mouse*2)-((MapHeight*tilewidth)/2)+x_mouse/2;
TileX = x_mouse-TileY;
to find the tile coordinates I just devide both by tilewidth
TileY = TileY/32; TileX = TileX/32;
DONE!! never had any problems!
It's quite easy actually once you get your head wrapped around it. All you do is find out where your mouse is relative to the map and then reverse to how you are drawing the tiles.
I draw my map in the double "for" loop like this:
For x coord: x * (TileWidth / 2) - (y * (TileWidth / 2))
For y coord: x * (TileHeight / 2) + (y * (TileHeight / 2))
So my x goes from top left to bottom right and my y goes from top right to bottom left. Mind though, like for the first tile the world coord will be 0,0 but the top pixel starts at x=0 + (tilewidth / 2) so we have to compensate for that when we are looking to find which tile the mouse is over. (or we could do that for the whole world itself by giving it a offset).
Now first we have to find the mouse position in relation to the world since you probably want a moving camera. My camera's centre starts as 0,0 so i have to compensate the mouse by half the screen width like so:
mouseWorldPosX = mouse.x + cam.x - (screen.width / 2)
mouseWorldPosY = mouse.y + cam.y - (screen.height / 2)
This is all we need to calculate the mouse position back to tile position.
For X:
tileX = (mouseWorldPosX + (2 * mouseWorldPosY) - (tileWidth / 2)) / tileWidth
As you can see we divide the whole thing by the tilewidth since we multiplied it in the draw method. The (tileWidth / 2) is just there to compensate for the offset i mentioned earlier.
For Y:
tileY = (mouseWorldPosX - (2 * mouseWorldPosY) - (tileHeight / 2) / -tileWidth
It's practically the same but the other way around. We subtract the Y world position since the Y axis runs the other way around. This time we compensate the offset for the height of the tile and we divide the whole thing by negative tilewidth, again since it runs the other way.
I hope this helps below is a working example of a method i looked up, it returns a vector with the tile coordinates:
public Vector2 MouseTilePosition(Camera cam, GraphicsDevice device)
{
float mPosX = newMouseState.X + (cam.Position.X - (device.Viewport.Width / 2));
float mPosY = newMouseState.Y + (cam.Position.Y - (device.Viewport.Height / 2));
float posx = (mPosX + (2 * mPosY) - (Map.TileWidth / 2)) / Map.TileWidth;
float posy = (mPosX - (2 * mPosY) - (Map.TileHeight / 2)) / -Map.TileWidth;
return new Vector2((int)posx, (int)posy);
}
So I'm trying to make my first game on android. The thing is I have a small moving ball and I want it to bounce from a line that I drew. For that I need to find if the x,y of the ball are also coordinates of one dot from the line.
I tried to implement these equations about lines
x=a1 + t*u1
y=a2 + t*u2 => (x-a1)/u1=(y-a2)/u2 (t=t which has to be if the point is on the line)
where x and y are the coordinates I'm testing, dot[a1,a2] is a dot that is on the line and
u(u1,u2) is the vector of the line.
heres the code:
public boolean Collided()
{
float u1 =Math.abs(Math.round(begin_X)-Math.round(end_X));
float u2 =Math.abs(Math.round(begin_Y)-Math.round(end_Y));
float t_x =Math.round((elect_X - begin_X)/u1);
float t_y =Math.round((elect_Y - begin_Y)/u2);
if(t_x==t_y)
{
return true;
}
else
{
return false;
}
}
points [begin_X,end_X] and [begin_Y,end_Y] are the two points from the line and [elect_X,elect_Y] are the coordinates of the ball
theoretically it should work, but in the reality the ball most of the time just goes straight through the line or bounces somewhere else where it shouldn't
I'm not sure what your code is doing, but looks weird
you do some operations on x coordinates of your data, then on y, and at the end you want them to be equal;
go and try hereShortest distance between a point and a line segment and then if distance == 0 (or smaller on equal to radius of your ball) you will have collision
The issue lies in the fact that you're testing whether the dot 'hits' the line that you want it to bounce from. I'm assuming that you're incrementing the position of your dot every frame with a small amount.
Say your dot is placed at [1,1], your line runs from [0,0] to [5,0], the velocity of your dot is 1 unit per second and the direction is [-1,0]. I'm assuming your calculating the increment based on the time per frame to allow for smoother animation.
What's happening is the following:
Dot at [1,1]
Time per frame = 0,7
Dot is moved to [0.3,0]
Test intersection = false
--- next frame ---
Dot at [0.3,0]
Time per frame = 0.5 (this usually varies per frame)
Dot is moved to [0.2,0]
Test intersection = false
So the tests say there hasn't been an intersection because your testing discrete positions of your dot.
As Aki Suihkonen suggests you want to test for line intersection between a line formed by the last position + the current position and the line that you want your dot to collide with.
java.awt.geom.Line2D.linesIntersect(double X1, double Y1, double X2, double Y2, double X3, double Y3, double X4, double Y4) allows you to check for these intersections easily.
Your math is OK, but you the code isn't.
It's simpler to use the genearl line equation y = y1 + a(x - x1) where a = (y2 - y1) / ( x2 - x1) , being (x1,y1) and (x2,y2) to points from the line.
To get ball the distance from the line when the ball is at point (bx,by)use:
double a = (y2 - y1) / (x2 - x1);
double distance = (by - y1 - a * (bx - x1)) * Math.cos(Math.atan(a));
Now you can compare if Math.abs(distance) is bellow a specific value (i.e. ball diameter) to confirm collision.
Note: this only works for non vertical lines. If you have a vertical line just use:
double distance = bx - x1;
good luck.