|
-
Professional Air Guitarist
[HELP] Circle/Line Collision & Reaction
I can do it when testing several points along the line, but there has to be a better way.
Raigan, I've read through your tutorials several times, and examined your code, but it's more like a lecture for geniuses than average programmers looking for help with collision 
Any help would be greatly appreciated. Once I have this down there is nothing stopping me from making a killer track for the bike with super physics!
-
ism
you can test for ball/line collision using localtoglobal if you want. just try the following;
1. create an mc that contains a horizontal line. the lines y pos must be 0
2. place it on the stage (you can rotate it if you want)
3. when you move the ball add the following code (within the actions for the ball);
Code:
var p = { x: 0, y: 0 };
localToGlobal(p);
_root.line.globalToLocal(p);
if (p.y < 0) {
// the ball has collided with the line
}
Last edited by BlinkOk; 12-27-2004 at 07:58 PM.
Graphics Attract, Motion Engages, Gameplay Addicts
XP Pro | P4 2.8Ghz | 2Gb | 80Gb,40Gb | 128Mb DDR ATI Radeon 9800 Pro
-
Professional Air Guitarist
Thanks, but I'm looking for a more mathematic approach, one that could be used in other languages.
-
~yarr Frag - check your pm box
-
Feeling adventurous?
Originally posted by token 3
~yarr Frag - check your pm box
Please post it here if it's something about this thread. I'm interested too! =)
-
hey,
well.. i didn't know if you needed vs. line, lineseg, or one-sided line, so.. here's all three 
Code:
//circle (x,y,r) vs. two-sided line ([x0,y0]->[x1,y1])
function CircleVsLine(x,y,r,x0,y0,x1,y1)
{
var lx = x1 - x0;//lx,ly is a vector parallel to the line
var ly = y1 - y0;
var nx = -ly;//nx,ny is a vector perpendicular to the line
var ny = lx;
var len = Math.sqrt(nx*nx + ny*ny);
if(len == 0)
{
return;
}
nx /= len;//nx,ny is now the unit (righthand) normal of the line
ny /= len;
var dx = x - x0;//dx,dy is the vector from the line to the circle
var dy = y - y0;
var dp = dx*nx + dy*ny;//dp is length of dx,dy when measured/projected onto the line's normal
var pen = Math.abs(dp) - r;
if(pen < 0)
{
//circle is inside the line; project it out along the normal
if(0 < dp)
{
//circle is on the RHside of the line, should be projected out the +ve normal
pen *= -1;
}
var px = nx*pen;//px,py is the penetration vector which pushes the circle out of the line
var py = ny*pen;
//DEBUG
_root.lineStyle(0, 0x882222, 100);
_root.moveTo(x,y);
_root.lineTo(x+px, y+py);
}
}
//circle (x,y,r) vs. one-sided line ([x0,y0]->[x1,y1])
function CircleVsHalfspace(x,y,r,x0,y0,x1,y1)
{
var lx = x1 - x0;//lx,ly is a vector parallel to the line
var ly = y1 - y0;
var nx = -ly;//nx,ny is a vector perpendicular to the line
var ny = lx;
var len = Math.sqrt(nx*nx + ny*ny);
if(len == 0)
{
return;
}
nx /= len;//nx,ny is now the unit (righthand) normal of the line
ny /= len;
var dx = x - x0;//dx,dy is the vector from the line to the circle
var dy = y - y0;
var dp = dx*nx + dy*ny;//dp is length of dx,dy when measured/projected onto the line's normal
var pen = dp - r;
if(pen < 0)
{
//circle is on the RHside of the line, should be projected out the +ve normal
pen *= -1;
var px = nx*pen;//px,py is the penetration vector which pushes the circle out of the line
var py = ny*pen;
//DEBUG
_root.lineStyle(0, 0x882222, 100);
_root.moveTo(x,y);
_root.lineTo(x+px, y+py);
}
}
//circle (x,y,r) vs. lineseg ([x0,y0]->[x1,y1])
function CircleVsLineSeg(x,y,r,x0,y0,x1,y1)
{
var lx = x1 - x0;//lx,ly is a vector parallel to the line
var ly = y1 - y0;
var len = Math.sqrt(lx*lx + ly*ly);
if(len == 0)
{
return;
}
var rx = lx/len;//rx,ry is the unit direction vector of the lineseg
var ry = ly/len;
var nx = -ry;//nx,ny is a vector perpendicular to the line
var ny = rx;
var dx = x - x0;//dx,dy is the vector from x0,y0 to the circle
var dy = y - y0;
var dpPerp = dx*rx + dy*ry;//length of dx,dy projected onto the lineseg's direction
if(dpPerp < 0)
{
//circle is closer to the endpoint x0,y0 than the line, project out of point x0,y0
var len = Math.sqrt(dx*dx + dy*dy);
var pen = r - len;
if(0 < pen)
{
//project out of the endpoint
dx /= len;
dy /= len;
var px = dx*pen;
var py = dy*pen;
}
}
else
{
if(len < dpPerp)
{
//circle is closer to the endpoint x1,y1 than the line, project out of point x1,y1
dx -= lx;//dx,dy is now the vector from x1,y1 to the circle
dy -= ly;
var len = Math.sqrt(dx*dx + dy*dy);
var pen = r - len;
if(0 < pen)
{
//project out of the endpoint
dx /= len;
dy /= len;
var px = dx*pen;
var py = dy*pen;
}
}
else
{
//circle is closer to the lineseg; project out of it
var dp = dx*nx + dy*ny;//dp is length of dx,dy when measured/projected onto the line's normal
var pen = Math.abs(dp) - r;
if(pen < 0)
{
//circle is inside the line; project it out along the normal
if(0 < dp)
{
//circle is on the RHside of the line, should be projected out the +ve normal
pen *= -1;
}
var px = nx*pen;//px,py is the penetration vector which pushes the circle out of the line
var py = ny*pen;
}
}
}
//DEBUG
_root.lineStyle(0, 0x882222, 100);
_root.moveTo(x,y);
_root.lineTo(x+px, y+py);
}
//------------- test code -----------------
lineX0 = 100;
lineX1 = 250;
lineY0 = 100;
lineY1 = 300;
colTest = CircleVsLine;
function TickTest()
{
//toggle between collision functions
if(Key.isDown(49))
{
colTest = CircleVsLine;
}
else if(Key.isDown(50))
{
colTest = CircleVsHalfspace;
}
else if(Key.isDown(51))
{
colTest = CircleVsLineseg;
}
_root.clear();
//draw the line
_root.lineStyle(0, 0x222288, 100);
_root.moveTo(lineX0, lineY0);
_root.lineTo(lineX1, lineY1);
//collide the mouse vs the line
colTest(_root._xmouse, _root._ymouse, 30, lineX0, lineY0, lineX1, lineY1);
}
_root.onEnterFrame = TickTest;
press 1/2/3 to toggle between line, onesided line, and lineseg.
in all the cases, px,py is the projection vector; for bounce/etc. you'll also need to unit normal, which differs, but you should be able to figure it out (i.e for vs. lienseg endpoints it's dx,dy, sometimes it's nx,ny.. basically it's the vector that's multiplied by the penetration to get the projection vector).
raigan
p.s - if you look at CircleVsLine(), this is a perfect example of what we're doing in the tutorial: the distance from one object to another (dx,dy) is measured along a potential seperating direction -- lines only have one of these, the direction perpendicular to the line. anyway, if the length of (dx,dy) when measurd along this axis is less than the radius, the circle is colliding with the line. does this make sense? it's important to understand the concept of seperating axes becausee they're very simple and fast, and a really powerful tool!
-
Professional Air Guitarist
YAY! I owe you one...more 
Ohh! I get it! I think
-
Professional Air Guitarist
http://www.gotcool.com/flash/?title=...ovieHeight=400
Now I just need to figure out Line Segment vs Line Segment.
-
hey,
i've never tried lineseg-lineseg myself using the "seperating axes" method, i've always used intersection-based code. the reason is that you need the position of the point of intersection; you _can_ get this out of the seperating axes, but it involves some extra work.
also, what do you need lineseg-lineseg for? most of those games don't model the body of the bike, just the wheels and the head of the player.. it seems like a lot of extra work 
perhaps try using a box for the bike frame? this will speed things up, and probably have better results (all of the lineseg-lineseg stuff i've tried has problems -- it pushes the linesegs apart, but it's not always the way you WANT it to be. for instance your bike frame (if it's made up of linesegs): if you find a lineseg colliding with a segment of the bike frame, you don't just want to push them apart -- you specifically want to push the lineseg "out" of the bike frame. since linesegs don't generally have sides, this gets messy -- better to use a convex shape to model the bike frame, as it's much faster than a bunch of linesegs, and behaves better.
really though, it seems that you should be able to design the game so that you donn't need a good model for the bike's body -- maybe even a couple circles would do.
raigan
p.s - i forget, did you already explain how you were doing the braking? if not, please explain! i'm still stuck on that..
-
Professional Air Guitarist
code:
function rW(p, nx, ny) {
w = p.w;
if (Key.isDown(Key.DOWN) && w == pL[0].w) {
w.ox = w.x;
w.oy = w.y;
p.ox = p.x;
p.oy = p.y;
w.s = 0;
} else {
rx = -w.y;
ry = w.x;
len = Math.sqrt(rx*rx+ry*ry);
rx /= len;
ry /= len;
sx = rx*w.s;
sy = ry*w.s;
tx = p.x-p.ox;
ty = p.y-p.oy;
vx = tx+sx;
vy = ty+sy;
dp = -ny*vx+nx*vy;
w.ox = w.x-dp*rx;
w.oy = w.y-dp*ry;
w0 = 1-w.w;
p.x += w0*w.s*-ny;
p.y += w0*w.s*nx;
w.s *= w.w;
}
}
Sorry I can't explain it right now, I'm leaving in 10 minutes! I'm sure you can figure it out, p is the point and w is the wheel (I think you used rim).
Good luck
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|