View Full Version : More Collision (again)
Iceman
2002.07.26, 10:54 PM
I'm having trouble calculating collision between a laser and a rock. This is what I'm doing now:
distance = sqrt((x2 -x1 * x2 - x1) + (y2 - y1* y2 - y1));
if (distance < 10) {
// collision action here
}
As you can see using the distance formula sometimes doesn't detect the collision and it runs pretty slow. Is there some better equation that can detect a line colliding with a circle? The hard part is how to detect when a rock has collided with the side of a laser.
Thanks,
Iceman
codemattic
2002.07.26, 11:38 PM
Originally posted by Iceman
distance = sqrt((x2 -x1 * x2 - x1) + (y2 - y1* y2 - y1));
the first thing I notice is that you need more parens. Your formula as it is now is parsed:
distance = sqrt((x2 -(x1 * x2) - x1) + (y2 - (y1* y2) - y1));
because mults/divs take precidence over adds/subtracts. So try:
distance = sqrt(((x2 -x1) * (x2 - x1)) + ((y2 - y1)*( y2 - y1)));
I dont know why you find this slow - it is one of the fastest ways to collide two spheres. AABB is the only faster code! Is your laser shot a sphere or a point?
One of the problems is that you are checking if there is a collision only on this frame. Its possible that there was a collision between frames - even though there isnt a collision in each surrounding frame. In frame 0 the bullet is on the south side of an object, while in frame 1 the bullet is north of the object. The collision happened sometime between 0 and 1 but your code wont catch it.
There are many articles on handling these collisions on gamasutra.com (I can find the articles if you cant find them doing a search). Also Dave Eberly's book has a lot of good info on how to do this (but be warned - your algebra skills need to be up to snuff). Also if you buy the book you can download his code to handle these kinds of interactions.
hth,
Codemattic
codemattic
2002.07.27, 04:31 AM
Originally posted by Iceman
distance = sqrt((x2 -x1 * x2 - x1) + (y2 - y1* y2 - y1));
if (distance < 10) {
// collision action here
}
also - you probably dont need to use sqrt. Lets say your bullet has a radius of 1.5 and your meteor has a radius of 20.0
bullet_radius_squared=1.5*1.5;
meteor_radius_squared=20.0*20.0;
distance_squared = ((x2 -x1 )* (x2 - x1)) + ((y2 - y1)* (y2 - y1));
if (distance_squared < (bullet_radius_squared+meteor_radius_squared)) {
// collision action here
}
So you can avoid the expensive squareroot. If you need the squareroot to get the actual distance - but somehow find it too slow there are fast squareroot functions that use Newton's method.
hth,
Codemattic
hokan
2002.07.27, 11:14 AM
Originally posted by Iceman
distance = sqrt((x2 -x1 * x2 - x1) + (y2 - y1* y2 - y1));
Some performance can be gaind by reducing the number of subtractions (from 4 to 2):
xd = x2 - x1;
yd = y2 - y1;
distance = sqrt((xd * xd) + (yd * yd))
This might be especialy usefull if you run a version that doesn't use sqrt.
Iceman
2002.07.27, 04:10 PM
Ok sorry I guess I didn't make this clear I'm trying to test a collision with a line segment (the laser) and a circle (the rock). The reason I used the distance formula is because I have no clue how to detect a collision between a line segment and a circle. Although, the distance formulas you gave above will work great for my ship and rock collision. Also I suspect the reason the collision is slower is because the laser is traveling very fast over a big area of the map. Finally don't I have to pay for a membership or something at gamasutra.com? Every time I try to access an article there it says I have to sign up :-(.
Thanks,
Iceman
Ice Cream Joe
2002.07.27, 05:42 PM
Ok sorry I guess I didn't make this clear I'm trying to test a collision with a line segment (the laser) and a circle (the rock). The reason I used the distance formula is because I have no clue how to detect a collision between a line segment and a circle.
There are two ways of doing this, depending on how your laser behaves. Does your laser fire out of the cannon like a projectile (Star Wars style) or does it "blink" on when you fire and "blink" off when you release the trigger (a la old school Star Trek phasers or the lightning gun in Quake 3)?
The first method is to trace a ray from your ship along the path of the laser. As you trace the ray, you can check individual points along the way, using the distance formula you already have. If you find a collision, you can either stop the checking or continue along the ray for penetrating lasers. I would do it this way if you have Star Wars style lasers.
The other method would be to mathematically figure out the shortest distance between the center of the rock (a point) and the laser (the line.) You'll want to find the point on the line that is closest to your rock. Say your line starts at (x1, y1) and ends at (x2, y2), and the center of your rock is at (x3, y3.) We can represent any point on the line by
x = x1 + u(x2 - x1) and
y = y1 + u(y2- y1),
where u is between 0 and 1. The value of u for which the point given by that formula is closest to the center of the rock is given by
u = ((x3 - x1) * (x2 - x1) + (y3 - y1) * (y2 - y1)) / ((x2 - x1)^2 + (y2 - y1)^2)
Plug that into the equations for x and y above, and you'll have the point on the line that's closest to the rock. Now you can check the distance with the regular distance formula. This method is probably better if you have the Star Trek/Quake 3 style laser.
The mathematical explanation for all that is given here (http://astronomy.swin.edu.au/~pbourke/geometry/pointline/) and also contains a link to C code that performs these calculations in 3D.
Good luck,
Joe
Ice Cream Joe
2002.07.27, 06:05 PM
Finally don't I have to pay for a membership or something at gamasutra.com? Every time I try to access an article there it says I have to sign up :-(.
Nope, they have a free membership that you can join. All it requires is an email address, to which you can have them send weekly updates on the game industry. The free membership will also let you check out their features and articles, as well as things like job searching. Good stuff :D
ICJ
Iceman
2002.07.27, 08:23 PM
Wow gamasutra sounds pretty nice :cool: . Also I'm using star wars type lasers.
Thanks,
Iceman
Carlos Camacho
2002.07.28, 10:03 AM
Yep, and after signing up you'll get more SPAM even when you say don't SELL my address. It took me forever to finally get removed from their membership group. Ug! Good luck.
BTW.. Mark's book as info on collision detection.
Cheers
Iceman
2002.07.28, 10:52 PM
Oh well I already signed up hehe :eek:. I found some good articles anyway, so it's worth it. Also I found out why the lasers were firing so slow; I forgot to put the return NO; for -(BOOL)resignsFirstResponder; :rolleyes:. Mark's game programming book sounds interesting; I'll check it out.
Thanks,
Iceman
codemattic
2002.07.29, 03:30 AM
Iceman -
Im glad you solved your slowdown problem - I didnt think it could be because of the math.
Carlos is right - they do send you stuff by email. However I havent found it to be the problem that he has. They send text mail - not html mail - so they dont take up much space/download time. They send out a weekly mailing - which usually spotlights articles I want to read anyway. I havent tried to cancel mine - but I dont doubt that Carlos got the runaround. Its really amazing - I dont expect MLM schemers to take me off their mailing list if I ask (in fact I assume they would take my response as a sign that the email address is 'active' and spam me even worse) - but Im always surprised at the number of 'legitimate' companies that refuse to take you off their mailing lists. I tried to get off of MP3.com and Discovery.com's as well as some others email lists with varying pain-in-the-ass results. Gamasutra.com might very well be the same way. Ive never tried to cancel because I dont mind their email - and I take it as a resonable intrusion in my life to have access to all their great articles. You can always get a free bogus hotmail email address and use that when you sign up.
Anyway - they article to check out is http://www.gamasutra.com/features/20020118/vandenhuevel_pfv.htm - it will handle sphere/sphere interactions as well as your laser beam interactions (a laser beam is just a sphere with a really small radius - or a zero radius - and a very very fast speed). It correctly handles interactions with both objects moving - even if they collide only mid-frame.
hth,
Codemattic
Iceman
2002.07.29, 06:49 PM
Thanks for the link. Yeah I guess you're going to get spamed one way or another. You wouldn't believe how much yahoo spams there own e-mail accounts :rolleyes: .
Iceman
Update:
u = ((x3 - x1) * (x2 - x1) + (y3 - y1) * (y2 - y1)) / ((x2 - x1)^2 + (y2 - y1)^2
what are the keyboard commands to make "^"?
Johan
2002.07.29, 07:32 PM
Originally posted by Iceman
u = ((x3 - x1) * (x2 - x1) + (y3 - y1) * (y2 - y1)) / ((x2 - x1)^2 + (y2 - y1)^2
what are the keyboard commands to make "^"?
The keybord command is [ shift + 6 ], but i assume that ^ means squared (eg 4^2 = 4*4). If you compile this code "^" will mean XOR (bitwise eXlusive OR) and not give you the results you are looking for.
.johan
Iceman
2002.07.29, 07:44 PM
Sorry yeah I just looked at my keyboard :rolleyes:. I was thinking it was an option+shift or option font.
Thanks,
Iceman
Iceman
2002.07.30, 06:30 PM
I'm still having some problems. Ok this is what I'm doing now:
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
OneSadCookie
2002.07.30, 06:43 PM
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
2002.07.30, 11:38 PM
Originally posted by Iceman
I'm still having some problems. Ok this is what I'm doing now:
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? =)
Why not do this instead?
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!!
geezusfreeek
2002.07.31, 12:55 AM
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:
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.
if (distanceFromFrontOfLaser < 13 || distanceFromBackOfLaser < 13) {
// delete rock
}
There may be some optimizations possible, but I'm about to go to bed. G'night.
geezusfreeek
2002.07.31, 01:00 AM
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
2002.07.31, 09:22 AM
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
2002.07.31, 09:24 AM
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.
geezusfreeek
2002.07.31, 02:09 PM
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.
Iceman
2002.07.31, 08:23 PM
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
geezusfreeek
2002.07.31, 09:28 PM
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).
// 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
}
Iceman
2002.07.31, 09:45 PM
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
geezusfreeek
2002.07.31, 09:57 PM
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.
Johan
2002.08.01, 05:30 AM
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:
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/Documentation/IntersectionLin2Cir2.pdf
Iceman
2002.08.02, 09:48 PM
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.
geezusfreeek
2002.08.02, 09:53 PM
Short answer:
http://chortle.ccsu.ctstateu.edu/vectorLessons/vectorIndex.html
Long answer:
I don't have one. I need to learn some of this stuff myself.
geezusfreeek
2002.08.02, 09:56 PM
Aw man. I don't think that even really answers you question at all. I just looked at my bookmarks and thought that looked right, but now that I looked at the actual site, all it does is show some matrix math without saying how to use it.
I'll just say that you need matrices to do the rotation.
codemattic
2002.08.03, 08:13 AM
Iceman,
I can understand you not wanting to throw out code that you have already written and start again from scratch, but...
>>
Ok I have one last problem and my collision should work. here's the code:
<<
Im not sure your code is going to work because you arent attacking the problem fully. I dont think its simply a matter of rejiggering your code to fix 'one last thing' - unless you are planning to only test the front pt and back pt of the laser for collision and leave it at that.
>>
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?
<<
right - b/c you should do all your collisions in *world* coordinates. You are mixing object coordinates and world coordinates.
>>
distance1b = sqrt(((bullet[j].x - rockx1[k])*(bullet[j].x - rockx1[k])) +
(((bullet[j].y - 45) - rocky1[k])*((bullet[j].y -45) - rocky1[k])));
<<
You do *not* have to use oop if you dont want to. I think its the bees knees personally but YMMV. Define structs. bullet[j].x - rockx1[k] ??? These are two points and they are defined differently - why? You are asking for many many headaches Ice. Define Point/Vector/Matrix structure/objects types and use them consistently. Then define some functions/methods for adding vectors, subtracting points, dot products, cross products etc... You need to have this library down before you can go forward. I know you want to just dive right in to the code - but your code will just get more and more confusing. Define a method/function that takes two points and gives you the distance between them - then you can use that function over and over instead of copying and pasting the formula over and over for each situation.
Even better download one of the many many math libraries and use that. If you dont want to use oop - download PLIB and use the SG library http://www.woodsoup.org/projs/plib/sg/index.html and look at the SG sourcecode (sg.h, sg.cxx files). All the math is there in regular non-oop c. If you do want to use oop - Eberly's free-magic is an excellent c++ library (thats what I use), or if you want objective-c check out 3dkit (used to be at 3dkit.org - but that isnt responding for me right now so I cant be sure of the url)
Eberly has two versions. Free-magic which is free to anyone (you must give him some credit in the about... dialog) - or wild-magic (which adds a scene renderer) which you have to purchase his book to use. Free-magic has lots of useful 'find' methods - as in find the first point of collision between a ray and a circle.
>>
P.S. The reason I'm moving the ground is because I'm using a nanosaur type camera view.
<<
moving the ground around the camera - or moving the camera around the ground... same thing, same math.
OK - so how would I solve this problem?
Option 1: The correct way (but harder)
In my laser object/struct I would store a point for the location of the laser (the beginning part - in world coords), a unit vector for its direction (in world coords), a scalar for its length, a vector for its velocity. Each frame I would update the point for the location by += it with its velocity vector. A rock object/struct would have a point for the center of its location (in world coords), a scalar for its radius, a vector for its velocity. To collide them I would use a method/function that returned the first point of intersection between a ray (defined by the laser location point and the unit vector for its direction) and a circle (using the rock's center point and radius). If there is an intersection point - and the distance to it from the laser location point is <= the laser's length then I would have a hit.
Or - I could use the gamasutra article I linked to earlier. It showed how to collide between two moving spheres/circles. A laser is just a fast moving circle with a tiny (or zero) radius. This would work better since it is a more generic solution - and accounts for movement between frames.
But to do the ray/circle test you need to understand parametric equations for the ray/circle test. The only thing you need to understand the gamasutra article is some point/vector math including dot-product.
In fact what I would do - is make an abstract class called generic_sprite_object which stored location, direction, etc... and all the methods to manage and collide that - and then derive my lasers, rocks, and ships, from that abstract class.
Option 2; The easy way and still mostly accurate.
While I still would draw my laser as one object on screen - mathematically I would keep it as a set of points. Each laser shot would store 20 points (in world coords) along the length of the shot - then do a simple 'is this point inside the circle' test for all 20 points. Use enough points that a rock cant fit between - the more points, the more accurate the collision test will be - but the more cpu the collision test will take. It wont slow you down as much as you think - point-within-a-circle test is pretty fast and you can afford to do many of them. No matter how many points you test for 10, 20, 40, 1,000 - you can still technically miss a collision that should of taken place - but you quickly get to the point where you are accurate enough that no one will notice or care.
- or - you can keep hacking away at the code you have. Maybe you will find a solution that I cant see. Good luck,
hth,
Codemattic
codemattic
2002.08.03, 12:04 PM
>>
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?
<<
what I mean by world vs object coordinates is that with respect to the laser the vector (0,-45) always points from the back to the tip of the laser - wrt the laser's coords. However in world coords - the laser might be pointed in any direction, and wrt the world's coords its a different vector each time. A quick way to transform the vector into world coords is to use the 2d rotation formulas.
x' = (x*cos(theta))+(y*sin(theta))
y' = (-x*sin(theta))+(y*cos(theta))
where theta is the direction the laser is pointed. The vector (x',y') will now get you from the back to the tip of the laser in world coordinates.
Also - this might be clearer. If you d/l the plib library and look at the sg code - its made to model opengl functions as closely as possible. So make a vector (0,-45,0). Then make an equivalent transformation matrix to what you are using to transform the laser. Then use sgXformVec3 to transform the vector from object to world coords.
hth,
Codemattic
2d ray-circle collision is relatively easy:
given a parametric line:
{x0+t*x1, y0+t*y1} (t=0 to 1)
and there is a circle at the origin of radius r
the line to the center of the circle is the same as the line's position:
{x0+t*x1, y0+t*y1}
The length of this vector squared is:
(x0+t*x1)^2 + (y0+t*y1)^2
= x0^2 + y0^2 + x0*t*x1 + y0*t*y1 + (t*x1)^2 + (t*y1)^2
= x0^2 + y0^2 + t*(x0*x1 + y0*y1) + t^2 * (x1^2 + y1^2)
To find the single local minima for this function, we take the derivative:
x0*x1 + y0*y1 + 2*t*(x1^2 + y1^2)
and solve for zero:
x0*x1 + y0*y1 + 2*t*(x1^2 + y1^2) = 0
t = -(x0*x1 + y0*y1) / (2*(x1^2 + y1^2))
calculate this and check if it's between 0 and 1. If it is, plug it into the length squared formula and check if the reslt is less than r^2. If it isn't, check if the endpoints are inside the circle.
now, more useful is the ray intersection test. that means:
x0^2 + y0^2 + t*(x0*x1 + y0*y1) + t^2 * (x1^2 + y1^2) = r^2
x0^2 + y0^2 - r^2 + t*(x0*x1 + y0*y1) + t^2 * (x1^2 + y1^2) = 0
To solve this you use the quadratic equation, which I can't remember off the top of my head right now. It gives you a quicker check for line intersection by just testing whether what's inside the radical is >0. If it is, you have two solutions - one where the line enters, the other where it exits. Figuring out which is which is fairly trivial.
Iceman
2002.08.04, 02:48 PM
Ok so it's the vector that is my problem. Here's the vector that I'm using:
note: xpos and ypos are the vectors of xtrans and ytrans.
laserx = -xtrans;
lasery = -ytrans;
laserz = 0.0;
laserxv = -xpos + 15.0 * sin(2 * M_PI * angle / 360.0);
laseryv = -ypos + 15.0 * cos(2 * M_PI * angle / 360.0);
laserx += laserxv;
lasery += laseryv;
glRotatef(angle, 0.0, 0.0, 1.0);
glTranslatef( xtrans, ytrans, -14.9); // ground movement
glTranslatef( laserx, lasery, laserz);
glRotatef(angle, 0.0, 0.0,-1.0);
[self laser];
Replacing angle with 0 and removing the glRotatefs almost fixes the problem except that it looks like the lasers are following the ship instead of flying off in the direction they were shot at originally. What do I need to add or subtract to get the glRotatef(angle, 0.0, 0.0,-1.0); in the vectors or wherever they need to be? B.t.w. codematic I couldn't find any source code (except for some header code) for that plib thing.
Thanks,
Iceman
codemattic
2002.08.05, 08:29 PM
hmmm strange - check http://plib.sourceforge.net/download.html. After you expand the .tar.gz file look in the src/sg/ folder. The files you want to take a look at are sg.cxx and sg.h - actually most of it is in the sg.h file because most of the functions are inlined. Its a great non-oop library that mimics OpenGLs functions and more. Even if you are going to write your own library you should at least take a look.
As for your code - I dont really understand all of it (why two rotates? for example). But I outlined earlier how I would write the code. If you want to post your code I will take a look. Remember - I solved the last problem you had with getting multiple shots to work - but it was only after looking through the source code that I could see where the problem was - I never would of got it with snippets alone.
I should warn you that one of the things Im working on is something vaguely similar - except its more 2d and an overhead view.
cheers,
Codemattic
Iceman
2002.08.06, 05:19 PM
Ok I started a new post called "laser collision" since this is getting long. Also Codematic do you mean similar as in using bouncing walls?
Iceman
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.