java intersecting 2dobject - java

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.

Related

How to check if a line lies between a prism

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

Rotating a hitbox and detect that rotation in a calculation

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

Java LWJGL - Vertical Shooting Bugs Out

So i've made my own FPS, graphics and guns and all of that cool stuff; When we fire, the bullet should take a random direction inside the crosshair, as defined by:
float randomX=(float)Math.random()*(0.08f*guns[currentWeapon].currAcc)-(0.04f*guns[currentWeapon].currAcc);
float randomY=(float)Math.random()*(0.08f*guns[currentWeapon].currAcc)-(0.04f*guns[currentWeapon].currAcc);
bulletList.add(new Bullet(new float[]{playerXpos, playerYpos, playerZpos}, new float[]{playerXrot+randomX, playerYrot+randomY}, (float) 0.5));
We calculate the randomness in X and Y (say you had a crosshair size (guns[currentWeapon].currAcc) of 10, then the bullet could go 0.4 to any side and it would remain inside the crosshair.
After that is calculated, we send the player position as the starting position of the bullet, along with the direction it's meant to take (its the player's direction with that extra randomness), and finally it's speed (not important atm, tho).
Now, each frame, the bullets have to move, so for each bullet we call:
position[0] -= (float)Math.sin(direction[1]*piover180) * (float)Math.cos(direction[0]*piover180) * speed;
position[2] -= (float)Math.cos(direction[1]*piover180) * (float)Math.cos(direction[0]*piover180) * speed;
position[1] += (float)Math.sin(direction[0]*piover180) * speed;
So, for X and Z positions, the bullet moves according to the player's rotation on the Y and X axis (say you were looking horizontally into Z, 0 degrees on X and 0 on Y; X would move 0*1*speed and Z would move 1*1*speed).
For Y position, the bullet moves according to the rotation on X axis (varies between -90 and 90), meaning it stays at the same height if the player's looking horizontally or moves completely up if the player is looking vertically.
Now, the problem stands as follows:
If i shoot horizontally, everything works beautifully. Bullets spread around the cross hair, as seen in https://dl.dropbox.com/u/16387578/horiz.jpg
The thing is, if i start looking up, the bullets start concentrating around the center, and make this vertical line the further into the sky i look.
https://dl.dropbox.com/u/16387578/verti.jpg
The 1st image is around 40º in the X axis, the 2nd is a little higher and the last is when i look vertically.
What am i doing wrong here? I designed this solution myself can im pretty sure im messing up somewhere, but i cant figure it out :/
Basicly the vertical offset calculation (float)Math.cos(direction[0]*piover180) was messing up the X and Z movement because they'd both get reduced to 0. The bullets would make a vertical line because they'd rotate on the X axis with the randomness. My solution was to add the randomness after that vertical offset calculation, so they still go left and right and up and down after you fire them.
I also had to add an extra random value otherwise you'd just draw a diagonal line or a cross.
float randomX=(float)Math.random()*(0.08f*guns[currentWeapon].currAcc)-(0.04f*guns[currentWeapon].currAcc);
float randomY=(float)Math.random()*(0.08f*guns[currentWeapon].currAcc)-(0.04f*guns[currentWeapon].currAcc);
float randomZ=(float)Math.random()*(0.08f*guns[currentWeapon].currAcc)-(0.04f*guns[currentWeapon].currAcc);
bulletList.add(new Bullet(new float[]{playerXpos, playerYpos, playerZpos}, new float[]{playerXrot, playerYrot}, new float[]{randomX,randomY, randomZ},(float) 0.5));
And the moving code...
vector[0]= -((float)Math.sin(dir[1]*piover180) * (float)Math.cos(dir[0]*piover180)+(float)Math.sin(random[1]*piover180)) * speed;
vector[1]= ((float)Math.sin(dir[0]*piover180)+(float)Math.sin(random[0]*piover180)) * speed;
vector[2]= -((float)Math.cos(dir[1]*piover180) * (float)Math.cos(dir[0]*piover180)+(float)Math.sin(random[2]*piover180)) * speed;
You didn't need to bust out any complex math, your problem was that when you were rotating the bullet around the y axis for gun spread, if you were looking directly up (that is, through the y axis, the bullet is being rotated around the path which its going, which means no rotation whatsoever (imagine the difference between sticking your arm out forwards towards a wall and spinning in a circle, and sticking you arm out towards the sky and spinning in a circle. Notice that your hand doesn't move at all when pointed towards the sky (the y-axis)) and so you get those "diagonal" bullet spreads.
The trick is to do the bullet spread before rotating by the direction the player is looking in, because that way you know that when you are rotating for spread, that the vector is guaranteed to be perpendicular to the x and y axes.
this.vel = new THREE.Vector3(0,0,-1);
var angle = Math.random() * Math.PI * 2;
var mag = Math.random() * this.gun.accuracy;
this.spread = new THREE.Vector2(Math.cos(angle) * mag,Math.sin(angle) * mag);
this.vel.applyAxisAngle(new THREE.Vector3(0,1,0),this.spread.y / 100); //rotate first when angle gaurenteed to be perpendicular to x and y axes
this.vel.applyAxisAngle(new THREE.Vector3(1,0,0),this.spread.x / 100);
this.vel.applyAxisAngle(new THREE.Vector3(1,0,0),player.looking.x); //then add player looking direction
this.vel.applyAxisAngle(new THREE.Vector3(0,1,0),player.looking.y);
this.offset = this.vel.clone()
I don't use java but I hope you get the main idea of what im doing by this javascript. I am rotating a vector going in the negative z direction (default direction of camera) by the spread.y, and spread.x, and then I am rotating by the pitch and yaw of the angle at which the player is facing.

Drawing parallel lines between two squares

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.

Collision of dot and line in 2D space

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.

Categories

Resources