4

So, to collide two ships together, I currently use:

if (distancex < 10 && distancez < 20 && distancex > -10 && distancez > -20){

Which obviously, is a box around the ship. Since the ship is very boxy, then that works well.

distancex, distancez are simply the distance from one ship to another.

So, let me draw some diagrams.

enter image description here

The above works fine, because that is the default rotation of the ship, and so the red ship can easily collide.

However, enter image description here if the ship is rotated at an angle like that, I cannot work out how to have the same or similar line of code but still have it working.

Sure, I know my rotation matrices, however either I am just being dumb or I don't see how they help here.

For any programmers (I know we are not all programmers here), here is my entire code:

for (Clients cl : GameServer.players){
                if (cl.backOff < 1){
                for (Clients can : GameServer.players){
                    if (can != cl){
                        if (!(can.y < 45)){
                        Vector3f b = new Vector3f(cl.x + (Math.sin(Math.toRadians(cl.x)) * 20), cl.y, cl.z + (Math.cos(Math.toRadians(cl.z)) * 20));
                            int distancex = (int) (b.x - can.x); //Reverse? 
                            int distancez = (int) (b.z - can.z); //Reverse?

                            if (distancex < 10 && distancez < 20 && distancex > -10 && distancez > -20){

                                System.out.println("X: " + distancex + " Z: " + distancez);
                                can.damage-=100 * cl.speed;
                                if (can.damage < 1){
                                    can.sinking = true;
                                }
                                cl.speed = 0;
                                cl.backOff = 1000;
                            }
                        }
                    }
                }
                }
  • What exactly are distancex and distancez? "The distance from one ship to another" is ambiguous, because it depends which reference points you use on the ships. The centers? The corners? Also, what are the dimensions of the ships? – Jack M Aug 10 '14 at 09:59

1 Answers1

3

I'd say you should not rotate the ship itself, rotate the whole world (or the coordinate system) so that the ship is again in the same orientation as in the first image. In the first image the ship points into the diretion of $a = (-1,0)^t$ (The $^t$ means just that I wrote a row vector but I mean a column vector.) In the 2nd image it is roughly in direction of $b = \frac{1}{\sqrt{2}} (-1,1)^t$. The angle between those is $\alpha = \cos^{-1}\left( \frac{\langle a,b\rangle}{\vert a \vert \cdot \vert b \vert} \right) $ where $\langle a, b \rangle = a_1b_1+a_2b_2$ is the standard scalar product of two 2-dimensional vectors, and $\vert a \vert = \sqrt{a_1^2+a_2^2}$ is the length (norm) of the vector. Now for rotating vectors we can use a rotation matrix:

$$ v_{rot} = \begin{pmatrix} \cos(\alpha) & -\sin(\alpha) \\ \sin(\alpha) & \cos(\alpha)\end{pmatrix} \cdot v = \begin{pmatrix} \cos(\alpha) v_1 - \sin(\alpha) v_2 \\ \sin(\alpha) v_1 + \cos(\alpha) v_2\end{pmatrix}$$

So in our case $$ a = \begin{pmatrix} \cos(\alpha) & -\sin(\alpha) \\ \sin(\alpha) & \cos(\alpha)\end{pmatrix} \cdot b = \begin{pmatrix} \cos(\alpha) b_1 - \sin(\alpha) b_2 \\ \sin(\alpha) b_1 + \cos(\alpha) b_2\end{pmatrix} = \begin{pmatrix} \frac{1}{\sqrt{2}} \frac{-1}{\sqrt{2}} - \frac{1}{\sqrt{2}} \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}}\frac{-1}{\sqrt{2}}+\frac{1}{\sqrt{2}}\frac{1}{\sqrt{2}}\end{pmatrix} = \begin{pmatrix} -1 \\ 0 \end{pmatrix}$$

If you now have the true distance vector $d = (d_1, d_2)$ between the two ships, you can apply the same rotation to $d$ and get $d_{rot}$ and then apply your normal collision check on the vector $d_{rot}$, so:

$$ d_{rot} = \begin{pmatrix} \cos(\alpha) & -\sin(\alpha) \\ \sin(\alpha) & \cos(\alpha)\end{pmatrix} \cdot d = \begin{pmatrix} \cos(\alpha) d_1 - \sin(\alpha) d_2 \\ \sin(\alpha) d_1 + \cos(\alpha) d_2\end{pmatrix} $$

PS: If the two ships are not in a nice right angle relative to each other, I'd calculate the four corners of the box of one ship (and not the distance which is - I assume - just the distance to the center of each ship), and check whether they are within the box of the other ship using the mentioned method.

UPDATE: Ah ok, I did not know about your knowledge. I now assume that you know about basic trigonometry ($\sin \cos \tan$) You can conventionally imagine vectors in 2d ord 3d, now I simplyfy things: Lets talk about 2d: A vector is basically a point in space: A vector has 2 coordinates, one in x-direction one in y-direction, for example $a = (3,5)$. The thing is when you call something a vector, you can do things you cannot do with points: You can for example multiply a vector by a value: $5 \cdot (-1,4) = (-5,20)$ or $-0.2\cdot (20,0) = (-4,0)$ (That means you strech a vector by that amount). You can also add vectors: Like $(2,5)+(-1,2) = (1,7)$ (Make a drawing: You can interpret vectors as arows that begin in $(0,0)$ and end with the head of the arrows in the given coordinates. Adding two vectors means appending one vectors 'tail' to the others head.)

Then we can talk about the length (a.k.a. norm indicated by $||$ around the vector.) of a vector. Thats simple: You use the pythagoras theorem: so if $a = (3,4)$ then $|a| = |(3,4)| = \sqrt(3^2+4^2)$.

Now the bit more challenging part: The matrices (singular 'matrix') are in our case 2x2 tables that represent a function that maps one 2d-coordinate system to another 2d-coordinate system. But this mapping has special properties, the so called linearity for example parallel lines will be still parallel after applying that mapping. That means basically you can use matrices to stretch the coordinate system in any direction or rotate it (or combine those two). If you now have a vector in the first coordinate system, you have to multiply it with the matrix, to get the coordinates of the vector in the second coordinate system.

But how can you multiply a 2x2 table with a vector?

For this purpose we do conventionally write the vectors vertically and not horizontally: $(1,3) = \begin{pmatrix} 1 \\ 3 \end{pmatrix}$ (The horizontal way is just convenient for writing the vectors within text but the vertical way is more convenient when calculating.)

So we have a matrix (normally written in big letters) $A = \begin{pmatrix} a & b \\ c & d \end{pmatrix}$ where $a,b,c,d$ are real values (like $0.5,100,-2.1345123,\sqrt{2}$) Now we have a vector $v = (v_1 , v_2) = \begin{pmatrix} v_1 \\ v_2 \end{pmatrix}$ that we want to map from the first oen to the second coordinate system. The mapped version of it in the second coordinate system I now call $w = (w_1 , w_2) = \begin{pmatrix} w_1 \\ w_2 \end{pmatrix}$. Now lets look how we multiply the matrix with the vector:

$$\begin{pmatrix} w_1 \\ w_2 \end{pmatrix} = w = A\cdot v = \begin{pmatrix} a & b \\ c & d \end{pmatrix} \cdot \begin{pmatrix} v_1 \\ v_2 \end{pmatrix} = \begin{pmatrix} a \cdot v_1 + b \cdot v_2 \\ c \cdot v_1 + d \cdot v_2 \end{pmatrix}$$

So now the new x-coordinate is $w_1 = a \cdot v_1 + b \cdot v_2$ and the new y-coordinate is $w_2 = c \cdot v_1 + d \cdot v_2$.

Now the last thing we need is calculating the angle between two vectors: If you have two vectors $a$ and $b$ you can construct the angle as follows: If you draw the points with the same coordinates as $a$ and $b$ and connect each point with a straight line with the point $(0,0)$ you can measure the angle between the two lines at $(0,0)$. This is the angle between the vectors. This is where the so called scalar product comes in: Thats a 'product' that 'multiplies' two vectors and returns a scalar value (sometimes also called 'dot product'. It is defined like follows: $\langle a , b \rangle = a_1\cdot b_1 + a_2 \cdot b_2$. It happens that if you divide that value by the length of both vectors, you get the cosine of the angle between those two: $\frac{\langle a , b\rangle}{|a|\cdot|b|} = \cos(\alpha)$ So if we have two vectors of the same length and want to determine how much we have to turn one (the pivot will always be $(0,0)$) to get the second one, we can solve this equation for $\alpha$. So if you now plug $\alpha$ into the rotation matrix you will get that exact mapping that rotates the whole coordinate system exactly that amount. That means if you now multiply the first vector with that matrix, you will get the rotated vector, the second one. (Thats what I have written first in the answer with the examples $a = (-1,0)$ and $b = \frac{1}{\sqrt{2}} (-1,1)$.

I know that has been a minimalist introduction to calculating with vectors. It is a pretty big topic but also a fun and useful one especially when you are into programming / games. I'd absolutely like to give you a recommendation for a book or a web resource for getting into this, but I know nothing like this in english. I hope that helped (and motivated) you.

flawr
  • 16,533
  • 5
  • 41
  • 66
  • Eh, give me a moment to actually translate this mathjax junk into code I can actually write and make work, and then I will accept the answer :).

    Just a quick question, where have D, DRot, VRot, and V come from?

    – user2722083 Aug 09 '14 at 11:49
  • $d$ and $v$ are basically any arbitrary vectors and $d_{rot}$ and $v_{rot}$ are the rotated versions. You can put any arbitrary vecotrs into $v$ and get the rotated vectors back. I just used $v$ / $v_{rot}$ as placeholders for the input / output of. (The same way you write $y = f(x)$ where $x$ is the input and $y$ the output.) Later I used $d$/$d_{rot}$ because I related to the distance. If something is unclear feel free to ask, thats what we are here for=) – flawr Aug 09 '14 at 15:51
  • I think my mind is going to explode. I am pretty novice at all the mathematical language, even though I would not say I am bad at actually knowing maths.

    For example, I don't even know what you mean by a vector. I know, I'm a complete idiot, but I mainly learn maths by subject, instead of maths on a whole, which means I never pick up the terminology.

    In java, a vector is just a thing that holds 3 variables. Which makes it very confusing when people say, for example, "multiply the vector".

    – user2722083 Aug 09 '14 at 17:07
  • 1
    Appended something in the main answer, I hope that helps. – flawr Aug 10 '14 at 08:38
  • Great! Thanks!! :) – user2722083 Aug 11 '14 at 17:34