## More Collision (again)

Luminary
Posts: 5,139
Joined: 2002.04
Post: #16
It seems highly unlikely that distance + 45 would be less than 13... and if it were, distance most certainly would be less than 13.

What are you trying to do?
Mars_999
Unregistered

Post: #17
Quote:Originally posted by Iceman
I'm still having some problems. Ok this is what I'm doing now:
Code:
```if (distance < 13 && distance + 45 < 13) { // delete rock }```
Is there any way I can have distance be a continuous bubble like "if ( (0.0 < distance < 45) < 13 ?) {}" instead of having two collision bubbles where one adds 45?

Iceman

For some reason that if() statement looks like its confused like me? =)

Code:
```if(distance < 13) { //do stuff }```
To me it looks like you want to delete the rock if its less than 13 and if distance was 0 it wouldn't delete. Maybe you want to use a || instead of a &&??? I am probably not making any sense due to me being very tired!!! =) Please forgive me!!
Member
Posts: 201
Joined: 2002.06
Post: #18
I don't understand what you are trying to do either. Are you trying something from that Gamasutra article? I didn't read it.

Right now, it looks like what your code says can be simplified to:

Code:
```if (distance < -32) { // delete rock }```

I know that that cannot be right....

I just thought of something. Are you attempting to compensate for the length of your laser beam as it shows for each frame, as in the beam is 45 units long? If this is the case, which I am becoming more and more sure of as I type this, then try computing the distance from each end of the laser beam to the target separately and then making your conditional statement.

Code:
```if (distanceFromFrontOfLaser < 13 || distanceFromBackOfLaser < 13) { // delete rock }```

There may be some optimizations possible, but I'm about to go to bed. G'night.
Member
Posts: 201
Joined: 2002.06
Post: #19
Wait, my code above wouldn't even detect the collision if the rock was halfway down the beam as I imagined it.... Either ignore that stuff, or, if I was correct in my assumption about the length of the laser, adapt it to your own stuff with different numbers so that it is sure to detect the collision.
ylaporte
Unregistered

Post: #20
Since your laser beam is a segment of a line, and you are checking for intersection with a point, it is natural that you miss a collision happening midway through the beam. You would have to check for a collision with every point on your laser segment (or maybe just a few representative ones).
However you can check for a collision between a line and a sphere . I don't remember everything by heart and don't have time to calculate it right now but here is the idea.

You have the parametric equation for a line which is
Point=PointOfOrigin+var+OrientationVector
and the one for a sphere x^2+y^2+z^2=r^2

Now the trick is to insert the equation for each of the x,y and z components of a point on the line in place of the x,y,z components in the sphere equation... after that you isolate var (most likely a quadratic equation) then you can just use the equation for the line to retrieve the exact point of intersection (Well, two of them since it is a quadratic).

You can now check if it is in the laser segment of the line...

This is just a suggestion... I know it works mathematically but not how effective it can be in a game setting. Of course there are probably tons of optimizations to be done once you are done resolving these equations...
ylaporte
Unregistered

Post: #21
Since your laser beam is a segment of a line, and you are checking for intersection with a point, it is natural that you miss a collision happening midway through the beam. You would have to check for a collision with every point on your laser segment (or maybe just a few representative ones).
However you can check for a collision between a line and a sphere . I don't remember everything by heart and don't have time to calculate it right now but here is the idea.

You have the parametric equation for a line which is
Point=PointOfOrigin+var+OrientationVector
and the one for a sphere x^2+y^2+z^2=r^2

Now the trick is to insert the equation for each of the x,y and z components of a point on the line in place of the x,y,z components in the sphere equation... after that you isolate var (most likely a quadratic equation) then you can just use the equation for the line to retrieve the exact point of intersection (Well, two of them since it is a quadratic).

You can now check if it is in the laser segment of the line...

This is just a suggestion... I know it works mathematically but not how effective it can be in a game setting. Of course there are probably tons of optimizations to be done once you are done resolving these equations...

Ah.. I forgot to say... but if the equation for var doesn't have any roots, then it means there is no intersection... since it is much easier to find this than to resolve var completely (at least less expensive in CPU time) I believe it could be pretty fast.
Member
Posts: 201
Joined: 2002.06
Post: #22
You could do that, or, if you are really lazy, you could just shorten the line segment so that it would detect a collision whether from the front or the back if the target happened to be in the middle of the beam.... Only if you're lazy.
Member
Posts: 196
Joined: 2002.04
Post: #23
Sorry I was a little confused on how to mathematically explain what I was trying to get. Yes geezusfreeek the distance + 45 is the end of the segment and distance is the beginning. The reason I'm using this is because the laser is pretty long and the rocks usually travel right through the back end of the laser since it's not a quake style flash . Ok I think I can explain it this time:

laserSegment > 0.0;
laserSegment < 45.0;

if (distance + laserSegment < 13) {
// delete rock
}

Is this not possible? If so I guess I can make

if (distance < 13 && distance + 22.5 < 13 && distance + 45 < 13) {}

Iceman
Member
Posts: 201
Joined: 2002.06
Post: #24
By saying if(distance + laserSegment <13), you are taking the distance from the beginning of the laser beam to the rock and adding the length of the laser beam to it and hoping that it somehow will be less than 13. That is impossible. Your other code will not work either because you are just adding to the distance in the same way, not checking the distance from a different point in space.

To check multiple points on a segment, you will first have to find the coordinates of each one in space and get the distance from each point to the rock and test each one with if(distance<13).

Code:
```// Test distance from beginning of laser beam to rock // Test intermediate points (number of points to test determined by width of rock) ... ... // Test distance from end of laser beam to rock // The values in the conditional statement depend on how many points you tested.  Here is a sample for three points (not enough for your case). if(distanceFromBeginning<13 || distanceFromMiddle || distanceFromEnd<13) { // Delete rock }```
Member
Posts: 196
Joined: 2002.04
Post: #25
Oooh that was the problem all along! I just actually tried (for the first time) the "distance + 45 < 13" by its self and it didn't detect a collision. Ok sorry for my totally wacky math.

Iceman
Member
Posts: 201
Joined: 2002.06
Post: #26
I know how that goes. I remember one time when I was learning Java I was getting a bit crazy with it. This was before I knew C too. I assigned x to 0, then I put if(x){...}. It took me a few hours to finally figure out what was going on.

ylaporte's way would work too, BTW. In fact, his way is what I would use because it makes the code easier to understand. It seems that you already have it worked out the other way though. It probably wouldn't be worth changing it now.
Apprentice
Posts: 5
Joined: 2009.01
Post: #27
I would suggest doing a raytrace. It's not "that" slow and works like a charm. You do however need to modify your code to handle "LaserDistanceTraveled" insted of LaserPos (If you do not want "real" lasers that hits instantly).

To test if the laser hits an enemy:
Code:
```struct vec2{float x,y;}; // float testLaserHit(...) // Returns the distance to the hit point. If returned value is negative there is no hit. // ( note: ShipDirection needs to be normalized. ) float testLaserHit( vec2 ShipPosition, vec2 ShipDirection,                     vec2 EnemyPosition, float EnemyRadius ) {         float b = ShipDirection.x * (ShipPosition.x - EnemyPosition.x) +                ShipDirection.y * (ShipPosition.y - EnemyPosition.y);         float c = (ShipPosition.x - EnemyPosition.x) * (ShipPosition.x - EnemyPosition.x) +                            (ShipPosition.y - EnemyPosition.y) * (ShipPosition.y - EnemyPosition.y) -                      (EnemyRadius*EnemyRadius);         float d = b * b - c;         if (d < 0.0f) return -1.0f;         return -b - sqrtf(d); }```

Also if you check over mutiple frames (e.g ship moves after shooting slow laser), you need to save the original ship position and direction.

Cheers

.johan

edit: If you don't get the math check out: http://www.magic-software.com/Documentat...n2Cir2.pdf
Member
Posts: 196
Joined: 2002.04
Post: #28
Ok I have one last problem and my collision should work. here's the code:

distance1b = sqrt(((bullet[j].x - rockx1[k])*(bullet[j].x - rockx1[k])) +
(((bullet[j].y - 45) - rocky1[k])*((bullet[j].y -45) - rocky1[k])));

if (distance1b < 13) {
// delete rock
}

glPushMatrix();
glRotatef(angle, 0.0, 0.0, 1.0);
glTranslatef( xtrans, ytrans, -14.9); // ground movement

glTranslatef( bullet[j].x, bullet[j].y, bullet[j].z);
glRotatef(angle, 0.0, 0.0,-1.0);
[self laser];
glPopMatrix();

As you may notice the bullet[j].y -45 does not rotate with [self laser] so when you rotate the ground bullet[j].y -45 is to the left or right of the actual laser (instead of being behind it). What kind of formula do I need to calculate bullet[j].x and bullet[j].y as always being -45 behind the space ship?

Iceman

P.S. The reason I'm moving the ground is because I'm using a nanosaur type camera view.
Member
Posts: 201
Joined: 2002.06
Post: #29