It is so close, but it just won't work (that last bit). Something is wrong with the reflection. Because somehow I need to apply it to both of the object who collide, but when I do they act crazy. This shouldn't be that hard to solve so I ask anyone, please help me!
I pasted all code into one file, to run this just copy and paste.
I pasted all code into one file, to run this just copy and paste.
Global Gravity:Vector2D = CreateVector( 0, 0.05 ) Type TBall Global list:TList = New TList Field Color Field Position:Vector2D Field Velocity:Vector2D = CreateVector() Field Circle:Circle2D Method New() List.Addlast( Self ) color = Rand(1,5) EndMethod Function Create:TBall( Circle:Circle2D ) Local Ball:TBall = New TBall Ball.Circle = Circle Ball.Position = Circle.Position Return Ball EndFunction Method Draw() Circle.Draw() EndMethod Method SetBallColor() Select Color Case 1 SetColor 255,0,0 Case 2 SetColor 0,255,0 Case 3 SetColor 0,0,255 Case 4 SetColor 0,255,255 Case 5 SetColor 255,255,0 EndSelect EndMethod Function DrawAll() For Local Ball:TBall = EachIn List Ball.SetBallColor() Ball.Draw() Ball.Velocity.Add( Gravity ) Ball.Position.Add( Ball.Velocity ) If Ball.Position.Y > GraphicsHeight() Then Ball.Velocity.Y:*-1 Next EndFunction Function Collision() For Local BallA:TBall = EachIn List For Local BallB:TBall = EachIn List If BallA <> BallB Local Reflection:Vector2D = BallA.Circle.CollideCircleReflect( BallB.Circle ) 'If BallA and BallB does not collide Reflection = null 'If they do collide then Reflection is a vector From BallA to BallB 'The Length of Reflection is the amount BallA has passed into/over BallB If Reflection Reflection.Draw( BallA.Position ) 'Divide the reflection in two depending on mass and velocity ' Local AReflect:Vector2D = Reflection.Copy() ' AReflect.Multiply( 0.5 ) ' Local BReflect:Vector2D = Reflection.Copy() ' BReflect.Reverse() ' AReflect.Multiply( 0.5 ) 'BallA.Position.Add( AReflect ) BallB.Position.Add( Reflection ) Local MassA = BallA.Circle.Radius Local MassB = BallB.Circle.Radius Local MomentumA:Vector2D = BallA.Velocity.Copy() Local MomentumB:Vector2D = BallB.Velocity.Copy() MomentumA.Multiply( MassA ) MomentumB.Multiply( MassB ) 'If A and B stick together ( like mud ) Local NewVelocity:Vector2D = MomentumA.Copy() NewVelocity.Add( MomentumB ) NewVelocity.Multiply( 1/(MassA + MassB) ) 'BallB.Velocity = NewVelocity.Copy() BallA.Velocity = NewVelocity.Copy() 'ApplyResponse( BallA.Velocity, Reflection, 0.0, 1 )'Slide ApplyResponse( BallB.Velocity, Reflection, 0.0, 0.998 )'Slide EndIf EndIf Next Next EndFunction EndType Local A:TBall = TBall.Create( Circle2D.Create( 20 , 30, 50 ) ) Local B:TBall = TBall.Create( Circle2D.Create( 500, 30, 50 ) ) A.Velocity.Set( 1 , 0 ) B.Velocity.Set( -1.1 , 0 ) Graphics 640 , 480 , 0 While Not KeyDown(Key_Escape) DrawText "Use the Mouse, Left-Click to Create Balls",10,10 If MouseHit(1) TBall.Create( Circle2D.Create( MouseX(), MouseY(), Rand(2,20) ) ) TBall.DrawAll() TBall.Collision() Flip;Cls Wend'REST of THIS FILE IS VECTOR2D.bmx and CIRCLE2D.bmx Rem File: "Vector2D.bmx" 2D Vector Module The Vector Module which is a part of the Public MaxPhysics PROJECT VERSION HISTORY: ADDITIONS: Added Mirror Method! Added Reflection and Projection methods! Added some more function commands (these should be in a aseparate file..) Added a DrawPoint Function Added methods for converting and creating perpendicular vectors (normals) ' \__ Commands see: CreateLeftNormal() Added a method: Plus( value!) - increases a vectors leangth with a scalar FIXES: Fixed: CreateField, it was using ints and not doubles - choppy movement as result Fixed: Now using the real cartesian coordinate system Fixed: Replaced floats with doubles. TO DO: Add methods and functions from the PollyCode Vector Each method should have a equivalent function only 3-4 are done. EndRem ' / / / / / / / / / / / / / / / / ' T V E C T O R '------------------------------------------------------------------------ Type Vector2D Field X!,Y! '=============== ' BASIC COMMANDS '=============== ' C R E A T E V E C T O R '----------------------------------------------- Function Create:Vector2D( X!, Y! ) Local Vector:Vector2D Vector = New Vector2D Vector.X! = X! Vector.Y! = Y! Return Vector End Function ' C R E A T E V E C T O R F R O M '---------------------------------------------- Function CreateFrom:Vector2D( Position1:Vector2D , Position2:Vector2D ) Local Vector:Vector2D = Create(0,0) Vector.VectorFrom( Position1, Position2 ) Return Vector EndFunction ' C R E A T E /w D I E C T I O N '---------------------------------------------- ' I don't know any good name for this method Function CreateField:Vector2D( Length! , Direction! ) Local Vector:Vector2D = Create(1,0) Vector.SetLength( Length ) Vector.SetDirection( Direction ) Return Vector EndFunction ' C O P Y V E C T O R '---------------------------------------------- Method Copy:Vector2D()' Return Create( X , Y ) End Method ' S E T V E C T O R '---------------------------------------------- Method Set( newX! , newY! )' X! = newX! Y! = newY! End Method ' S E T D I R E C T I O N '---------------------------------------------- Method SetDirection( Angle! )' Local Length! = Length() X = Cos( Angle! )*Length Y = -Sin( Angle! )*Length End Method Method SetDir( Angle! ) SetDirection( Angle ) EndMethod ' S E T L E N G T H '---------------------------------------------- Method SetLength( Length! ) 'If we want to set vector to zero If Length = 0 Set(0,0);Return 'If the new length is negative assume we want to If Length < 0 Turn180() 'Reverse Local Angle! = Angle()'Of this Vector X = Cos(Angle) * Length Y = -Sin(Angle) * Length EndMethod Method SetMagnitude( Length! ) SetLength( Length ) EndMethod ' G E T L E N G T H '---------------------------------------------- Method Length!() Return Sqr( X*X + Y*Y )' EndMethod 'Alternative Names - Use whatever you like Method Magnitude!() Return Length() EndMethod Method GetLength!() Return Length() EndMethod Method GetMagnitude!() Return Length() EndMethod ' G E T L E N G T H S Q U A R E D '---------------------------------------------- Method LengthSquared() Return ( X*X + Y*Y )' EndMethod ' G E T D I R E C T I O N '---------------------------------------------- Method Direction!() Return ATan2(-y , x) End Method 'Also Alternative Names - Use whatever you like Method GetDirection!() Return Direction() EndMethod Method Dir!() Return Direction() EndMethod Method GetAngle!() Return Direction() EndMethod Method Angle!() Return Direction() EndMethod 'And alternative to get 0<= Angle <360 Method Dir360!() Local Angle! = Direction!() If Angle < 0 Then Angle:+360 Return Angle End Method ' G E T A N G L E B E T W E E N '---------------------------------------------- Method AngleBetween( Vector:Vector2D ) Local DT! = Self.Dot( Vector ) Local DB! = Length()*Vector.Length() If DB = 0 Return Return ACos( DT / DB ) EndMethod ' C R E A T E L E F T N O R M A L '---------------------------------------------- ' This is a a Perpendicular Vector! 'As if you would rotate it 90 degrees Method CreateLeftNormal:Vector2D( ) Return Create( Y, -X ) EndMethod ' C R E A T E R I G H T N O R M A L '---------------------------------------------- ' This is a a Perpendicular Vector! Method CreateRightNormal:Vector2D( ) Return Create( -Y, X ) EndMethod ' M A K E L E F T N O R M A L '---------------------------------------------- Method MakeLeftNormal( ) Return Set( Y, -X ) EndMethod ' M A K E R I G H T N O R M A L '---------------------------------------------- Method MakeRightNormal() Return Set( -Y, X ) EndMethod ' M A K E L E F T N O R M A L F R O M '---------------------------------------------- Method MakeLeftNormalFrom( Vector:Vector2D ) Return Set( Vector.Y, -Vector.X ) EndMethod ' M A K E R I G H T N O R M A L F R O M '---------------------------------------------- Method MakeRightNormalFrom( Vector:Vector2D ) Return Set( -Vector.Y, Vector.X ) EndMethod ' R E V E R S E V E C T O R '---------------------------------------------- Method Reverse() 'or Turn 180 Degrees X = -X Y = -Y End Method Method Turn180() Reverse() EndMethod ' V E C T O R F R O M '---------------------------------------------- Method VectorFrom( Position1:Vector2D , Position2:Vector2D) X = ( Position2.X - Position1.X ) Y = ( Position2.Y - Position1.Y ) 'Change the vector into a vector from Position1 to Position2 EndMethod '=============== ' MATH COMMANDS '=============== ' A D D '---------------------------------------------- Method Add( Vector:Vector2D ) X:+ Vector.X Y:+ Vector.Y EndMethod ' A D D C O P Y '---------------------------------------------- ' Add two Vectors and return the result as a ' third vector. Method AddCopy:Vector2D( Vector:Vector2D ) Local NewVector:Vector2D NewVector = Self.Copy() NewVector.Add( Vector ) Return NewVector EndMethod ' I N C R E A S E '---------------------------------------------- Method Increase( Value! )'Add a value to the vectors length Local Angle# = GetAngle() X:+ Cos( Angle ) * Value Y:- Sin( Angle ) * Value End Method Method Plus( Value! ) Increase( Value ) EndMethod ' P R O J E C T I O N '---------------------------------------------- ' ' Returns: Self vector projected on the Input Vector ' Method ProjectOn( Vector:Vector2D ) 'Self = A 'Vector = B Local DotAB! = Dot( Vector)'A*B Local DotBB! = Vector.Dot( Vector)'B*B X = ( DotAB / DotBB )*Vector.X 'Ab.x = ( A*B / B*B ) B.x Y = ( DotAB / DotBB )*Vector.Y 'Ab = A projected on B EndMethod Method ProjectionOf( VectorA:Vector2D, VectorB:Vector2D ) X = VectorA.X 'Copy Y = VectorA.Y Self.ProjectOn( VectorB ) EndMethod Method CreateProjection:Vector2D( VectorA:Vector2D, VectorB:Vector2D ) Local ProjectVector:Vector2D = VectorA.Copy() ProjectVector.ProjectOn( VectorB ) Return ProjectVector EndMethod ' R E F L E C T I O N - AGAINST SURFACE '---------------------------------------------------------- ' ' Mainly used for Velocity vectors that collide against surfaces ' Self = Incoming Vector to be reflected (or vector you want to reflect at surface) ' Surface = Surface normal ( any vector perpendicular to the surface ) ' ' This would be the same as reversing and then mirroring the vector in the ' surface normal! Method Reflect:Vector2D( SurfaceNormal:Vector2D ) Local Reflect:Vector2D = Create(0,0) SurfaceNormal.Normalize()'Make its length = 1 Reflect.Mirror( SurfaceNormal ) Return Reflect EndMethod ' M I R R O R 'Surface must be a unit vector! Method Mirror( Normal:Vector2D ) Local Dotprod# = -X * Normal.X - Y * Normal.Y X=X+2 * Normal.X * dotprod Y=Y+2 * Normal.Y * dotprod ' Self.Reverse() ' Local Angle! = AngleBetween( Surface ) ' Self.SetDirection( Angle*2 ) 'X = Surface.X* Surface.DOT( Self ) - X 'Y = Surface.Y* Surface.DOT( Self ) - Y EndMethod ' R O T A T E '---------------------------------------------- Method Rotate( Angle! ) Local CurrentAngle! = Direction() Local Length! = Length() X = Cos( CurrentAngle + Angle ) * Length Y = -Sin( CurrentAngle + Angle ) * Length EndMethod Method AddAngle( Angle! ) Rotate( Angle ) EndMethod ' S U B T R A C T '---------------------------------------------- Method Subtract( Vector:Vector2D ) X:- Vector.X Y:- Vector.Y 'This would also work 'Self.Add( Vector.Copy().Reverse() ) EndMethod ' D O T P R O D U C T '---------------------------------------------- Method DOT!( Vector:Vector2D ) Return ( X * Vector.X + Y * Vector.Y) EndMethod 'Alternative Name Method DotProduct!( Vector:Vector2D ) Return Self.DOT( Vector ) EndMethod ' M U L T I P L Y V E C T O R '---------------------------------------------- Method Multiply( Value! ) X:*Value Y:*Value EndMethod ' N O R M A L I Z E '---------------------------------------------- Method Normalize() Local Length! = Length() If Length = 0 Return'Don't divide by zero Set( (X / Length), ( Y / Length) ) 'Make length = 1 End Method ' U N I T V E C T O R '---------------------------------------------- Method Unit:Vector2D() Local Vector:Vector2D Vector = Self.Copy() Vector.Normalize() Return Vector'Returns a New vector with length = 1 End Method ' D I S T A N C E '---------------------------------------------- 'The Distance between the end points of two vectors Method DistanceTo!( Other:Vector2D ) Local dx! = Other.X - X Local dy! = Other.Y - Y Return Sqr( dx*dx + dy*dy ) EndMethod 'Calculates the perpendicular distance from a point to a line (or vector) 'If the vector returned is smaller than the radius of your round object (circle) 'then you have collided and if you then add this vector to your position you 'will move out of collision, then you are free to change velocity: (bounce or slide) Method ToLine:Vector2D( LineStart:Vector2D, LineEnd:Vector2D ) Return PointToLineVector( X, Y, LineStart.X, LineStart.Y, LineEnd.X, LineEnd.Y ) EndMethod Function PointToLineVector:Vector2D( px!, py!, x1!, y1!, x2!, y2! ) If x1 = x2 And y1 = y2 Then Return Vector2D.Create( x1-px, y1-py ) Local sx! = x2-x1 Local sy! = y2-y1 If sx = 0 And sy = 0 Then Return Local q! = ((px-x1) * (x2-x1) + (py - y1) * (y2-y1)) / (sx*sx + sy*sy) If q < 0.0 Then q = 0.0 If q > 1.0 Then q = 1.0 Local Xx! = (1-q)*x1 + q*x2 Local Xy! = (1-q)*y1 + q*y2 Return Vector2D.Create(Xx - Px, Xy - Py ) End Function '=============== ' DEBUG COMMANDS '=============== ' D R A W V E C T O R '-------------------------------------------------- Method DrawModify( From:Vector2D , Multiply! , Xtra ) 'DrawLine From.X + Xtra, From.Y, From.X + Xtra + X* Multiply , From.Y + Y* Multiply DrawArrow From.X + Xtra, From.Y, From.X + Xtra + X* Multiply , From.Y + Y* Multiply EndMethod Method DrawXY( FromX, FromY, Multiply! , Xtra ) DrawModify( Point(FromX, FromY) , Multiply! , Xtra ) End Method ' D R A W R E A L V E C T O R '-------------------------------------------------- Method Draw( Origin:Vector2D =Null ) If Origin = Null Origin = Create( 0, 0 ) DrawModify( Origin , 1 , 0 ) EndMethod ' D R A W V E C T O R D A T A '----------------------------------------------- Method DrawData( sLen, sDir, X, Y ) Local Row = 0 If sLen DrawText "Length : "+Length(),X,Y +Row*15; Row:+1 If sDir DrawText "Dir : " +Dir360(),X,Y +Row*15; Row:+1 End Method Function DrawArrow(x1%, y1%, x2%, y2%, _arrowHeadLength% = 10, _arrowHeadWidth% = 5) Local dx = x1 - x2 Local dy = y1 - y2 If Sqr( dX*dX + dY*dY ) = 0 Then Return DrawLine x1, y1, x2, y2 Local lineAngle% = ATan2( dx , dy ) lineAngle:+ 180 DrawLine x2, y2, (x2 + (Sin(lineAngle * -1) * _arrowHeadLength%)) + (Cos(lineAngle) * _arrowHeadWidth%), (y2 - (Cos(lineAngle * -1) * _arrowHeadLength%)) - (Sin(lineAngle) * _arrowHeadWidth%) DrawLine x2, y2, (x2 + (Sin(lineAngle * -1) * _arrowHeadLength%)) - (Cos(lineAngle) * _arrowHeadWidth%), (y2 - (Cos(lineAngle * -1) * _arrowHeadLength%)) + (Sin(lineAngle) * _arrowHeadWidth%) End Function EndType ' / / / / / / / / / / / / / / / / '------------------------------------------------------------------------ ' C R E A T E V E C T O R '----------------------------------------------- 'Purpose: Creates a New Vector 'Parameters: X = Vectors X value ' Same For Y 'Returns: New Vector Type '----------------------------------------------- Function CreateVector:Vector2D( X!=0, Y!=0 ) Return Vector2D.Create( X, Y ) EndFunction ' C O P Y V E C T O R '---------------------------------------------- 'Purpose: Copies a Vector into a New vector 'Parameters: VECTOR 'Returns: a VECTOR, exact copy of first VECTOR '----------------------------------------------- Function CopyVector:Vector2D( Vector:Vector2D ) Return Vector.Copy() EndFunction ' V E C T O R D I R E C T I O N '---------------------------------------------------- 'Purpose: Calculates the direction of a vector 'Parameters: VECTOR 'Returns: Degrees 'Note on Angel: 0 is Left, 90 is down (BlitzStyle) 'Note LastDir: If Length = 0 this Function returns LastDir '--------------------------------------------------------- Function VectorDirection!( Vector:Vector2D ) If Vector = Null Return Return Vector.Direction() EndFunction ' S E T V E C T O R '---------------------------------------------- Function SetVector( Vector:Vector2D, X!=0, Y!=0 ) If Vector = Null Return Vector.Set( X, Y ) EndFunction ' M A K E L E F T N O R M A L '---------------------------------------------- ' Creates Vector that is perpendicular to the first ' Fast way to rotate it 90 degrees. ' Function CreateLeftNormal:Vector2D( Vector:Vector2D ) Return Vector.CreateLeftNormal() EndFunction ' D O T P R O D U C T '--------------------------------------------------- 'Purpose: Calculated the Dot-Product of Two Vectors 'Parameters: Two vectors you want to "Dot" 'Returns: The result '--------------------------------------------------- Function Dot!(Vector:Vector2D,Vector2:Vector2D) If Vector = Null Return Return Vector.DOT( Vector2 ) End Function 'Alternative Naming (Both these works the same) Function DotProduct!(Vector:Vector2D,Vector2:Vector2D) If Vector = Null Return Return Vector.DOT( Vector2 ) End Function ' N O R M A L I Z E '---------------------------------------------- 'Purpose: Sets Vector length To ONE but keeps ' it's direction 'Parameters: VECTOR to normalize '----------------------------------------------- Function NormalizeVector( Vector:Vector2D ) If Vector = Null Return Vector.Normalize() EndFunction ' R O T A T E '---------------------------------------------- ' Rotates the Vector by this much. ' Possitive numbers for clockwise movement ' Negative for Anit-Clockwise =) ' 'Note: Don't confuse this command with SetVectorDirection() Function RotateVector( Vector:Vector2D, Angle! ) If Vector = Null Return Vector.Rotate( Angle! ) EndFunction ' U N I T V E C T O R '---------------------------------------------- 'Note: This is same as Normalizing a vector ' except that this function does not alter the ' original vector. Instead it return a new vector Function CreateUnitVector:Vector2D( Vector:Vector2D ) If Vector Return Vector.Unit() EndIf EndFunction ' D R A W V E C T O R '__________________________________________________ 'Purpose: Draws the vector from the specifed point 'Parameters: X,Y location '-------------------------------------------------- Function DrawVector( Vector:Vector2D, From:Vector2D , Multiply!=1 , Xtra=0 ) Vector.DrawModify( From , Multiply! , Xtra ) EndFunction ' D R A W V E C T O R D A T A '----------------------------------------------- 'Purpose: Prints the data of a vector 'Parameters: sLen=ShowLength, SDir=ShowDirection ' X and Y = Where to start draw the data (text) '----------------------------------------------- Function DrawVectorData( Vector:Vector2D, X=10, Y=20, sLen=True, sDir=False ) Vector.DrawData( sLen, sDir, X, Y ) EndFunction Function DrawVectorInfo( Vector:Vector2D, X=10, Y=20, sLen=True, sDir=False) Vector.DrawData( sLen, sDir, X, Y ) EndFunction Rem If you ever need a function to check something of a point you can use the vector to check against (position vector for example) Ex drawline( Point(50,100), ShipPosition:Vector ) EndRem Function Point:Vector2D( X! , Y! ) Local Vector:Vector2D= New Vector2D Vector.X = X Vector.Y = Y Return Vector EndFunction Function DrawPoint( Point:Vector2D, Radius) DrawOval Point.X-Radius, Point.Y-Radius, Radius*2, Radius*2' Center Point! EndFunction Function DrawLineToPointFromOrigin( Start:Vector2D, Origin:Vector2D ) DrawLine Start.X, Start.Y, Start.X + Origin.X , Start.Y + Origin.Y EndFunction 'Import "vector2D.bmx" Type Shape2D Abstract Field Position:Vector2D = Point(0,0)'Center position! Method ShapesOverlap( Shape:Shape2D ) EndMethod Method ShapesCollide:Vector2D( Shape:Shape2D ) 'A Shape Collides Against another Shape EndMethod EndType Type Circle2D Extends Shape2D Field Radius! = 1 Function Create:Circle2D( X, Y, Radius! ) Local Circle:Circle2D = New Circle2D Circle.Position.Set(X,Y) Circle.Radius = Radius Return Circle End Function 'Circle vs another Shape 'Returns the projected vector required to push us out of collision Method ShapesCollide:Vector2D( Shape:Shape2D ) Select Shape Case Circle2D( Shape ) Return CollideCircleReflect( Circle2D( Shape) ) 'Case Line2D( Shape ) ' Return CollideLineReflect( Line2D( Shape ) ) 'Case Polygon2D( Shape ) ' Return CollidePolygonReflect( Polygon2D( Shape ) ) EndSelect EndMethod 'Circle vs another Shape Method ShapesOverlap( Shape:Shape2D ) Select Shape Case Circle2D( Shape ) Return CollideCircle( Circle2D( Shape) ) 'Case Line2D( Shape ) ' Return CollideLine( Line2D( Shape ) ) 'Case Polygon2D( Shape ) ' Return CollidePolygon( Polygon2D( Shape ) ) EndSelect EndMethod 'Just check collision - Quick version Method CollideCircle( Circle:Circle2D) Local Distance! = Distance( Position, Circle.Position ) Local Amount! = ( Radius + Circle.Radius ) - Distance If Amount > 0 Then Return Amount Else Return False EndMethod Method GetAngleToCircle!( Circle:Circle2D ) Local Reflect:Vector2D = Vector2D.CreateFrom( Position, Circle.Position ) Return Reflect.Dir360() 'Or Angle() - depends on the form you want EndMethod '------------------------------------------------------------------------ 'Check for collisions, if collision detecte it return a reflection vector 'The reflection vector has the same length and direction required to push 'the circle out-of collision with the other circle '------------------------------------------------------------------------ Method CollideCircleReflect:Vector2D( Circle:Circle2D ) Local Magnitude! = CollideCircle( Circle ) If Magnitude = False Then Return Null Local ReflectAngle = GetAngleToCircle!( Circle ) Return Vector2D.CreateField( Magnitude!, ReflectAngle ) EndMethod Rem UNDER CONTRUCTION Method CollideLineReflect:Vector2D( Circle:Circle2D ) Local FromPointToLine:Vector2D = See solution in File: "CircleTesting5.bmx" VectorToLine.Reverse() Local Dist = VectorToLine.Length() VectorToLine.Normalize() VectorToLine.Multiply( Ball.Radius - Dist ) Ball.Position.Add( VectorToLine ) EndRem Method Draw() DrawOval Position.X - Radius, Position.Y - Radius, Radius*2, Radius*2 EndMethod EndType Function Distance!( Position1:Vector2D, Position2:Vector2D ) Local DX! = Position2.X - Position1.X Local DY! = Position2.Y - Position1.Y Return Sqr(DX*DX + DY*DY) EndFunction Rem Local CircleA:Circle2D = Circle2D.Create(100 , 100 , 100) Local CircleB:Circle2D = Circle2D.Create(320 , 240 , 50) Local CircleB_Mobile = False 'Can we move B? Graphics 640 , 480 , 0 While Not KeyDown(Key_Escape) DrawText "Move around, Press SPACE to make the RED circle MOBILE.",10,10 SetColor 0 , 200 , 0 'Green CircleA.Draw SetColor 200 , 0 , 0' Red CircleB.Draw If KeyHit( Key_Space ) If CircleB_Mobile = True Then CircleB_Mobile = False Else CircleB_Mobile = True EndIf SetColor 0 , 0 , 255' Blue 'Local OverlapDist = CircleA.CollideCircle( CircleB ) 'Local OverlapAng = CircleA.GetAngleToCircle( CircleB ) 'If OverlapDist 'DrawText "COLLIDING! by : "+OverlapDist+", Angle: "+OverlapAng ,50,50 Local Reflection:Vector2D = CircleA.CollideCircleReflect( CircleB ) If Reflection Reflection.Draw( CircleA.Position ) If CircleB_Mobile = True CircleB.Position.Add( Reflection ) EndIf ApplyResponse( BallVelocity, SurfaceNormal, 0.00, 0.2 ) 'EndIf CircleA.Position.Set( MouseX(), MouseY() ) Flip;Cls Wend EndRem Rem Friction! from 0 to 1 ; 1 = Total Friction (get stuck), 0 = No Friction Elasticy! from 0 to 1 ; 1 = Perfect Bounce, 0 = No Bounce USE: If CollideSurface( SurfaceNormal,....) ApplyResponse( Tank.Velocity, SurfaceNormal, 0, 0.5 ) Endif EndRem Function ApplyResponse( Velocity:Vector2D Var, SurfaceNormal:Vector2D, Friction!, Elasticity! ) SurfaceNormal.Normalize() Velocity.Mirror( SurfaceNormal ) If Elasticity < 0 Then Elasticity = 0'Slide If Elasticity > 1 Then Elasticity = 1'Perfect Bounce Local Bounce:Vector2D = CreateVector(0,0) Bounce.ProjectionOf( Velocity, SurfaceNormal ) Bounce.Multiply( Elasticity ) ' Apply Elasticy, to the perpendicular part of velocity If Friction < 0 Then Friction = 0 If Friction > 1 Then Friction = 1 Friction = 1 - Friction'' Case 1, now: 0, Case 0, now: 1 Local Slide:Vector2D = CreateVector() SurfaceNormal.MakeLeftNormal()'Convert the normal to the surface! Slide.ProjectionOf( Velocity, SurfaceNormal )' Project to surface Slide.Multiply( Friction ) ' Apply Friction, to the parallel part of velocity Velocity.Set(0,0) Velocity.Add( Slide ) Velocity.Add( Bounce ) 'FOR DEBUGGING ONLY ' SetColor 0,0,255'GREEN ' Slide.Draw ( Ball.Position ) ' SetColor 255,255,0'YELLOW ' Bounce.Draw ( Ball.Position ) EndFunction