Hmm, Ive have discovered the bug I had mentioned previously with my calculations. There was an error in returning the sign. But I fixed it, so here is the complete source file I used to make this. Play around with it, its pretty cool on its own, but if you can understand it, you will have to adapt it to you own vehicles, and then things should be pretty simple from there. I used an excellent source for help with the math.
[ http://softsurfer.com/Archive/algorithm_0102/algorithm_0102.htm
So I can't take all the credit.
Here is the code:
// Dark GDK - The Game Creators - www.thegamecreators.com
// the wizard has created a very simple project that uses Dark GDK
// it contains the basic code for a GDK application
// whenever using Dark GDK you must ensure you include the header file
#include "DarkGDK.h"
class pt
{
public:
float X, Y;
pt(){ X=0.0f; Y=0.0f; }
pt( float x, float y ){ X=x; Y=y; }
~pt(){}
};
pt operator +( pt pt1, pt pt2 ){ return pt(pt1.X+pt2.X,pt1.Y+pt2.Y); }
pt operator -( pt pt1, pt pt2 ){ return pt(pt1.X-pt2.X,pt1.Y-pt2.Y); }
pt operator /( pt pt1, pt pt2 ){ return pt(pt1.X/pt2.X,pt1.Y/pt2.Y); }
pt operator *( pt pt1, pt pt2 ){ return pt(pt1.X*pt2.X,pt1.Y*pt2.Y); }
pt operator +( pt pt1, float v ){ return pt(pt1.X+v,pt1.Y+v); }
pt operator -( pt pt1, float v ){ return pt(pt1.X-v,pt1.Y-v); }
pt operator *( pt pt1, float v ){ return pt(pt1.X*v,pt1.Y*v); }
pt operator /( pt pt1, float v ){ return pt(pt1.X/v,pt1.Y/v); }
pt operator -( pt pt1 ){ return pt(-pt1.X,-pt1.Y); }
#define slope(u,v) ( ((u).X-(v).X) / ((u).Y-(v).Y) )
#define dotProd(u,v) ((u).X * (v).X + (u).Y * (v).Y )
#define norm(v) dbSqrt(dotProd(v,v))
#define d(u,v) norm(u-v)
pt perp( pt p ){ return pt( -p.Y, p.X ); }
pt midPoint( pt pt1, pt pt2 ){ return pt( (pt1.X+pt2.X)/2, (pt1.Y+pt2.Y)/2 ); }
bool sign( float f ){ if( f>=0 )return false; else return true; }
class box
{
public:
pt UpLeft, UpRight, LowLeft, LowRight, Center;
box( pt upLeft, pt upRight, pt lowLeft, pt lowRight )
{
UpLeft = upLeft;
UpRight = upRight;
LowLeft = lowLeft;
LowRight = lowRight;
Center = GetCenter();
}
box( int width, int height, pt center )
{
Center = center;
UpLeft = pt(center.X-width/2,center.Y-height/2);
UpRight = pt(center.X+width/2,center.Y-height/2);
LowLeft = pt(center.X-width/2,center.Y+height/2);
LowRight = pt(center.X+width/2,center.Y+height/2);
}
~box(){}
pt GetCenter()
{
return pt( (UpLeft.X+UpRight.X+LowRight.X+LowLeft.X)/4, (UpLeft.Y+UpRight.Y+LowRight.Y+LowLeft.Y)/4 );
}
void Rotate( float ang )
{
// Height and Width , are Half the Vehicle / Sprite Height , Width , that is becouse im using an OffsetSprite XY to the Middle of the Sprite. that makes the rotation good.
float Width = d( UpLeft, UpRight ) / 2;
float Height = d( UpLeft, LowLeft ) / 2;
// Upper Line
// X = ( X * dbCos(ang) - Y * dbSin(ang) );
// Y = ( X * dbSin(ang) + Y * dbCos(ang) );
UpLeft.X = -Width * dbCos( ang ) - -Height * dbSin( ang ) ;
UpLeft.Y = -Width * dbSin( ang ) + -Height * dbCos( ang ) ;
UpRight.X = Width * dbCos( ang ) - -Height * dbSin( ang ) ;
UpRight.Y = Width * dbSin( ang ) + -Height * dbCos( ang ) ;
// Lower Line
LowLeft.X = -Width * dbCos( ang ) - Height * dbSin( ang ) ;
LowLeft.Y = -Width * dbSin( ang ) + Height * dbCos( ang ) ;
LowRight.X = Width * dbCos( ang ) - Height * dbSin( ang ) ;
LowRight.Y = Width * dbSin( ang ) + Height * dbCos( ang ) ;
// Make each relative to the center.
UpLeft.X += Center.X;
UpLeft.Y += Center.Y;
UpRight.X += Center.X;
UpRight.Y += Center.Y;
LowLeft.X += Center.X;
LowLeft.Y += Center.Y;
LowRight.X += Center.X;
LowRight.Y += Center.Y;
// Really no need to do this, because mathematically it should still be the same.
//Center = GetCenter();
}
void Draw( float ang )
{
Rotate( ang );
//cross corners
dbLine(Center.X,Center.Y, UpLeft.X,UpLeft.Y);
dbLine(Center.X,Center.Y, UpRight.X,UpRight.Y);
dbLine(Center.X,Center.Y, LowLeft.X,LowLeft.Y);
dbLine(Center.X,Center.Y, LowRight.X,LowRight.Y);
//bounding Lines
dbLine(UpLeft.X,UpLeft.Y,UpRight.X,UpRight.Y);
dbLine(UpRight.X,UpRight.Y,LowRight.X,LowRight.Y);
dbLine(LowRight.X,LowRight.Y,LowLeft.X,LowLeft.Y);
dbLine(LowLeft.X,LowLeft.Y,UpLeft.X,UpLeft.Y);
}
void PositionBox( pt pos )
{
Center = pos;
}
};
// Checks if the point is within an un-rotated box
bool BoundsCheck( pt pt1, pt Left, pt Right )
{
return pt1.X>=Left.X && pt1.X<=Right.X && pt1.Y>=Left.Y && pt1.Y<=Right.X ;
}
// dbLine Wrapper for two points
void DrawLine( pt p1, pt p2 )
{
dbLine( p1.X, p1.Y, p2.X, p2.Y );
}
// Returns a point where two lines intersect.
pt PointOfIntersection( pt p1, pt p2, pt p3, pt p4 )
{
pt I;
float m1, m2, b1, b2;
if( !( p1.X == p2.X ) && !( p3.X == p4.X ) )
{
//`find slope
m1 = (p2.Y - p1.Y)/(p2.X - p1.X);
m2 = (p4.Y - p3.Y)/(p2.Y - p1.Y);
//`find y-intercept
b1 = -(m1 * p1.X) + p1.Y;
b2 = -(m2 * p3.X) + p3.Y;
//`find solution to system
I.X = ( b2 - b1 )/( m1 - m2 );
I.Y = ( m2 * ( I.X )) + b2;
}else
{
//` for and vertical horizontal lines
if( ( p3.X == p4.X ) && !( p1.X == p2.X ) )
{
m1 = (p2.Y - p1.Y )/(p2.X - p1.X );
b1 = -(m1 * p1.X ) + p1.Y ;
I.X = p3.X;
I.Y = m1 * I.X + b1 ;
}
else if ( p1.X == p2.X )
{
m2 = (p4.Y - p3.Y )/(p4.X - p3.X );
b2 = -(m2 * p3.X ) + p3.Y ;
I.X = p1.X;
I.Y = m2 * I.X + b2;
}
}
return I;
}
//` Returns the point that is on the perpendicular of the line segment created by linePt1 and linePt2
// And that passes through point pt1
pt PointNormalIntersection( pt pt1, pt linePt1, pt linePt2 )
{
float l1 = dotProd( pt1-linePt1, linePt2-linePt1 );
float l2 = dotProd( linePt2-linePt1, linePt2-linePt1 );
float b = l1 / l2;
pt bb( linePt1.X + b*(linePt2.X - linePt1.X), linePt1.Y + b*(linePt2.Y - linePt1.Y) );
return bb;
}
// Returns the signed distance to the line created by the two vertexes and the point
float PointDistanceToLine( pt p, pt l1, pt l2 )
{
pt v = l1 - l2;
pt w = p - l1;
float c1 = dotProd(v,w);
float c2 = dotProd(v,v);
float b = c1 / c2;
float l = dotProd(perp(v),w) / c2;
pt Pb = l1 + v * b;
return d(p, Pb)*l/abs(l);
}
// The best way to test if a point is within a box, to see if the point is in front or behind
// each wall.
bool PointInsideBox( pt pt1, box box1 )
{
float b1, b2, b3, b4;
// For every line of the box check that this point is not behind all of them together
b1 = PointDistanceToLine( pt1, box1.UpLeft, box1.UpRight );
b2 = PointDistanceToLine( pt1, box1.UpRight, box1.LowRight );
b3 = PointDistanceToLine( pt1, box1.LowRight, box1.LowLeft );
b4 = PointDistanceToLine( pt1, box1.LowLeft, box1.UpLeft );
if( b1<=0 && b2<=0 && b3<=0 && b4<=0 )
return true;
return false;
}
// This is the function that tests if two boxes are colliding.
bool Collision( box box1, box box2 )
{
// check if each vertex is outside of the other box,
pt vert = box1.UpLeft;
if( PointInsideBox( vert, box2 ) ) return true;
vert = box1.UpRight;
if( PointInsideBox( vert, box2 ) ) return true;
vert = box1.LowLeft;
if( PointInsideBox( vert, box2 ) ) return true;
vert = box1.LowRight;
if( PointInsideBox( vert, box2 ) ) return true;
vert = box1.Center;
if( PointInsideBox( vert, box2 ) ) return true;
// check if each other boxs vertex is outside of this box,
vert = box2.UpLeft;
if( PointInsideBox( vert, box1 ) ) return true;
vert = box2.UpRight;
if( PointInsideBox( vert, box1 ) ) return true;
vert = box2.LowLeft;
if( PointInsideBox( vert, box1 ) ) return true;
vert = box2.LowRight;
if( PointInsideBox( vert, box1 ) ) return true;
vert = box2.Center;
if( PointInsideBox( vert, box1 ) ) return true;
// if it makes it here, no collision has occured.
return false;
}
// the main entry point for the application is this function
void DarkGDK ( void )
{
// turn on sync rate and set maximum rate to 60 fps
dbSyncOn ( );
dbSyncRate ( 60 );
// make two boxes
box box1(50,30,pt(200,150));
box box2(50,30,pt(300,320));
// for storing the mouse position
pt Mouse;
// for incrementing the angles.
float ang1 = 36.0f, ang2 = 0.0f;
// our main loop
while ( LoopGDK ( ) )
{
dbCLS();
Mouse.X = dbMouseX();
Mouse.Y = dbMouseY();
if( PointInsideBox( Mouse, box1 ) && dbMouseClick()==1 ) box1.PositionBox( Mouse );
if( PointInsideBox( Mouse, box2 ) && dbMouseClick()==1 ) box2.PositionBox( Mouse );
if( !Collision(box1, box2) )
{
// continuosly rotate box one
ang1++;
}
// user rotate box 2
ang2 += dbMouseMoveZ()/100.0f + dbKeyState( 18 ) - dbKeyState( 17 );
box1.Draw(ang1);
box2.Draw(ang2);
// update the screen
dbSync ( );
}
// return back to windows
return;
}