I'm working on a basic program where 2 players on a 2D board of size 30x30 have to reach a smaller grid of size A*A (let's call it rug) somewhere on the 2D board. I need to calculate which of the players is closer to the rug. I know how to calculate the distance to the top left corner of the rug (as i use x and y coordinates to draw it), but don't know how to calculate the distance to the nearest point of the rug, which could also e.g be the middle of the bottom of the rug.
This is more of an algorithms question than java. Could you clarify the information we have about the rug? Do we have the rug's coordinates? Do we have the player's coordinates?
Assuming you had the coordinates of the corners of a square A*A rug, you could simply compute which player has a shorter Euclidean distance to the rug corners, or its sides. This can be done by creating a list of coordinates the rug owns.
Bear in mind this is psuedo code, please do not just copy the code into your IDE and be upset it didn't pass your tests.
So again the steps are:
Create a list of square rug's coordinates
Add corners to that list
Compute the points along the sides of the rug to be added to the list
Compare the minimum euclidean distance between the players and ALL coordinates in the list. The lower distance is closest.
Let's suppose you had a unit square rug with corners at (1,1), (-1,1), (-1,-1), (1,-1).
ArrayList<String> rugCoordinates = new ArrayList<String>();
//first add all corners
rugCoordinates.add("(1,1)");
rugCoordinates.add("(-1,1)");
rugCoordinates.add("(-1,-1)");
rugCoordinates.add("(1,-1)");
Now you need to add the points along the line to the list. You can get the slope between the points via rise/run for example, between (-1,1) and (1,1) = 0 slope.
slope = (yCoordTarget-yCoordSource)/(xCoordTarget-xCoordSource);
for(int i = xCoordSource; i < xCoordTarget, i++){
rugCoordinates.add(i, i+slope);
}
Finally compare the min distances of players.
if (findMinEuclideanDistance(player1) < findMinEuclideanDistance(player2)){
return player1;
else{
return player2;
}
Related
Consider the following:
Currently, I'm programming a very basic dungeon generator. Right now, it works like this:
Generate an int[][] hyperarray of arbritrary lengths.
Place rooms at random coordinates in this hyperarray (we'll call it maze for now.) using a for loop that fills the heigth and width of the room with 1's in maze. For game engine purposes 0 means not traversable (a wall.) and 1 means traversable by the player/enemies.
Start a perfect maze generator at 0,0 and run until all the space inbetween the rooms is filled with corridors.
Connect rooms to corridors, remove dead ends, you're left with a system of interconnected rooms.
Like this
Now I'd like to jazz up these rooms because they're just flat rectangles. What I now need to do is find a way to generate a polygon inside the int hyperarray (coordinates will probably do fine, this isn't the problem) and then fill the space of the polygon in the hyperarray with 1's (the part I'm having trouble with).
I'm trying to figure out how to "draw lines within a integer array" right now.
what i found out was, i could draw a line from one point to another, by doing the following:
find the width and height of point 1 and point 2 (absolute value of x1-x2 and y1-y2,
divide width by (height-1) and from point 1 to point 2, along the y axis move towards point 2 by single steps, and on the x axis by width / height steps.
Example:
01000
01000
00100
00100
00010
00001
here i have a line from (1,0) as (x,y) to (4,5)
if i take the width and height i end up with
width = 3
height = 5
if i divide 3/5 i end up with 0.6
and so for every single step along the y axis, i take a 0.6 step along the x axis (and floor the resulting value, since we can only use integers as positions)
and end up with the koordinates
(1,0)
(1.6,1) -> (1,1)
(2.2,2) -> (2,2)
(2.8,3) -> (2,3)
(3.4,4) -> (3,4)
(4,5) -> (4,5)
with this you could draw those lines for every coordinate pair of the polygon using this line function
x = x1 + (|(y1-y)| * ( |(x1-x2)| / |(y1-y2)| ) * sign(x2-x1))
where x is the current x of every iteration, following the line along the y axis
and x1 beeing your start x position, x2 beeing your end position
y beeing the current y of every iteration (the actual counter during the loop to be specific)
y1 and y2 beeing the start y and end y positions repectively.
and sign(x2-x1) to help figure out, wether you are going to the left or right from the start position.
with this you should be able to draw the outline of your polygon, and hopefully it should become easier to fill it afterwards.
i hope this helps you a bit
regards
EDIT:
we draw lines for every consecutive pair of coordinates, not EVERY SINGLE pair.
meaning if you would draw a polygon from points p1,p2,p3,p4,p5
you would draw a line from p1 to p2, p2 to p3, p3 to p4, p4 to p5 and p5 to p1
just a quick sidenote
I am making my own implementation of a raycaster in a game I am making, and I have come across a very hard problem. I have a player (the black dot), and I need to find the intersection nearest to the player. In the image below, the arrow is pointing to the intersection point I need.
What I guess I am trying to say is that I need a function something like this:
// Each line would take in 2 map values for it's 2 points
// In turn, the map would have to have an even number of points
public Point getNearestIntersection(int playerX, int playerY, int lineDir, Point[] map) {
// whatever goes here
}
I am going to have to do this about 50 times every frame, with about 100 lines. I would like to get 40 fps at the least if possible... Even if I divide it up into threads I still feel that it would cause a lot of lag.
The class Point has a method called distance which calculates the distance of two points. You then could loop all points to get the nearest. Could be something like this:
Point currentNearestIntersection;
double smallestDistance;
for (Point inter : intersections) {
double distance = player.distance(inter );
if (distance < smallestDistance) {
currentNearestIntersection= inter;
smallestDistance = distance;
}
}
axis/line intersection is in reality solving:
p(t)=p0+dp*t
q(u)=q0+(q1-q0)*u
p(t)=q(u)
t=? u=?
where:
p0 is your ray start point (vector)
dp is ray direction (vector)
q0,q1 are line endpoints (vectors)
p(t),q(u) are points on axis,line
t,u are line parameters (scalars)
This is simple system of 2 linear equations (but in vectors) so it lead to N solutions where N is the dimensionality of the problem so choose the one that is not division by zero ... Valid result is if:
t>=0 and u=<0.0,1.0>
if you use unit dp vector for direction of your ray then from computing intersection between axis and line the t parameter is directly distance from the ray start point. So you can directly use that ...
if you need to speed up the intersections computation see
brute force line/line intersection with area subdivision
And instead of remebering all intersections store always the one with smallest but non negative t ...
[Notes]
if you got some lines as a grid then you can compute that even faster exploiting DDA algorithm and use real line/line intersection only for the iregular rest... nice example of this is Wolfenstein pseudo 3D raycaster problem like this
I have a dynamic rectangle in which 4 subtriangles (t0-t3) are created (by adding the diagonals from the vertices). When given a certain x|y coordinate what is the fastest way to find the corresponding triangle?. The rectangle has a specific position and dimension. I only need the right "id" so not the vertices of the triangle, so for example in the graphic when p1 is given as position 0 should be returned, 3 at p2 and 2 at p3, ...
One possible solution of course would be to create the triangles and query if the point is contained in one of them, but it feels like a very complicated solution for something that simple.
I also thought about creating a vector from the center and measuring the angle but it also seems complicated in a rectangle with varying dimensions.
Example Rectangle
Consider the following:
Let the bottom left corner of the rectangle be (0,0) and the top right corner be (1,1). Now, the two lines that form the triangles are defined as:
y = x and y = 1-x
For every point except (.5,.5) we have a ternary conditional for a given x or y. For example, given that x = .2, we know that:
if y < .2, we're in the bottom triangle (t2),
elif .2 < y < .8, we're in the left triangle (t3),
else, we're in the top triangle (t0).
Hopefully this helps without explicitly giving you the code.
Sorry about the bad title, but I could not think of anything else.
Let me explain: I have got 2 ships. The ship in the collision world, and the ship in the real world.
Now the ship in the real world is rotating, however I am unable to rotate the ship in the collision world (Or move it), which means that the collision objects must be rotated around the ship in the collision world.
When a CannonBall is near the ship, I get the distance from the CannonBall to the ship (for x, y, and z) and then compare that to a triple array of coordinates which are the collision points (About 2000+) - If the result from the triple array is "1", then they have collided. In other words, the collision ship does not move, but in the collision code the CannonBall's location is the same as the distance to the real-world ship and the real-world CannonBall.
Now here is the problem: If the ship is rotated, I need to rotate the CannonBall around the ship, because the ship cannot rotate.
How would I do this? What sort of mathematical formula?
Note: I have - Ship's rotation, x, y, and z coordinates, and the CannonBall's x, y, and z coordinates.
Thanks if anybody can give me an answer!
Edit: Lets make this more clear.
In the real world, ship1 could fire a CannonBall at ship2. If I refer to "The ship", I mean ship2.
When the CannonBall gets near to the ship, I want it to check for collisions. To do this,(Physics world) I check if array[CannonBall.distance(ship).x][CannonBall.distance(ship).y][CannonBall.distance(ship).z] returns a "1", and if it does, it collides.
However, because I cannot change an array without a large amount of processing, I cannot change the ship's rotation. Therefore, I must rotate the CannonBall around it so that it is relative to the CannonBall's true rotation compared to the ship.
If I got you right, then you are having a ship (e.g. in the middle of the screen) that has a canon ball rotating around it in order to aim towards another ship that is movable. All of that in 3D(?). Assuming that is what you mean, here is an answer ;) :
Lets do that in a 2 Dimensional Space first. What you need first is a formula to calculate a circle. As a function can only have one y-Value for each x-Value, you will actually need two. The smartest thing to do would probably divide the direction your canon ball is facing from the static ship into the common 360°, then have the formula calculate x and y coordinates. One approach could work with the formula for a circle (+/-r²=x²+y², with r being the radius), but I think a approach with cos and sin would be easier. Therefore:
You might want to have an input of an angle. If this angle is 90°, then your cannon ball is to the right of the ship. 180° would be underneath your ship, and 270° to the left, 0°/360° would be above. I would then take that input and add 90° to it, so that you can start to the left of your ship (IMPORTANT for cos and sin to work!). What we know now is the angle of the cannon ball, and the radius of the circle. Assuming that you know the coordinates of the middle of the ship, you can then imagine yourself in a coordinate system, with your ship being the origin. Now you need to calculate x. This can be done by:
x = -cos^-1(ANGLE)*radius. The result will be your x-Coordinate, that you have to subtract from the middle of the ship coordinate. Then, with x and the Angle being known, you can calculate y= x/tan-1(ANGLE). If the original angle is greater then 90°, you have to multiply the y coordinate with -1.
The method for this would be:
public void calculateCordinates(int degrees, int r){
degrees = degrees+90;
while(degrees>=360){degrees=degrees-360;}//ensures that degree < 360°
double x;
double y;
x = Math.acos(Math.toRadians((double)degrees))*r;
y = x/Math.atan(Math.toRadians((double)degrees));
}
The Coordinates are now in double as the results are most of the time not going to be whole numbers. Round them to ints before you subtract them from the origin coordinates.
If you want to do this in 3D, you can calculate the y coordinate by using the same method. This time, the angle you enter is your 3rd Dimension angle, so "the angle that you look at as in into the screen, out of the screen, with your right ear on the screen and so on" (sorry, didn't know how to describe that better). Of course you can combine the Methods to one as well, would look something like that:
public void calculateCordinates(int degrees, int degrees3D, int r){
degrees = degrees+90;
while(degrees>=360){degrees=degrees-360;}
double x;
double y;
double z;
x = Math.acos(Math.toRadians((double)degrees))*r;
y = x/Math.atan(Math.toRadians((double)degrees));
z = x/Math.atan(Math.toRadians((double)degrees3D));
}
I hope this is what you asked for, and I hope it helps!
So, I'm working on a 2D physics engine, and I have an issue. I'm having a hard time conceptualizing how you would calculate this:
Take two squares:They move, collide, and at some vector based off of the velocity of the two + the shape of them.
I have two vector lists(2D double lists) that represent these two shapes, how does one get the normal vector?
The hit vector is just (s1 is the first shape, s2 the second) s2 - s1 in terms of the position of the center of mass.
Now, I know a normal vector is one perpendicular to an edge, and I know that you can get the perpendicular vector of a line by 90 degrees, but what edge?
I read in several places, it is the edge a corner collided on. How do you determine this?
It just makes no sense to me, how you would mathematically or programmatically determine what edge.
Can anyone point out what I'm doing wrong in my understanding? Sorry for providing no code to explain this, as I'm having an issue writing the code for it in the first place.
Figure1: In 2D the normal vector is perpendicular to the tangent line:
Figure2: In 3D the normal vector is perpindicular to the tangent plane
Figure3: For a square the normal vector is easy if you are not at a corner; It is just perpendicular to the side of the square (in the image above, n = 1 i + 0 j, for any point along the right side of the square).
However, at a corner it becomes a little more difficult because the tangent is not well-defined (in terms of derivatives, the tangent is discontinuous at the corner, so perpendicular is ambiguous).
Even though the normal vector is not defined at a corner, it is defined directly to the left and right of it. Therefore, you can use the average of those two normals (n1 and n2) as the normal at a corner.
To be less technical, the normal vector will be in the direction from the center of the square to the corner of the collision.
EDIT: To answer the OP's further questions in the chat below: "How do you calculate the normal vector for a generic collision between two polygons s1 and s2 by only knowing the intersecting vertices."
In general, you can calculate the norm like this (N is total verts, m is verts inside collision):
vcenter = (∑N vi) / N
vcollision = (∑m vi) / m
n = vcollision - vcenter
Fig. 1 - vcollision is only a single vertex.
Fig. 2 - vcollision is avg of two verts.
Fig. 3 - vcollision for generic polygon intersection.