VERSION 5.00
Begin VB.Form Form1 
   BorderStyle     =   1  'Fixed Single
   Caption         =   "Form1"
   ClientHeight    =   9210
   ClientLeft      =   45
   ClientTop       =   435
   ClientWidth     =   11595
   LinkTopic       =   "Form1"
   MaxButton       =   0   'False
   MinButton       =   0   'False
   ScaleHeight     =   9210
   ScaleWidth      =   11595
   StartUpPosition =   3  'Windows Default
   Begin VB.Timer MoveBall 
      Interval        =   10
      Left            =   10200
      Top             =   360
   End
   Begin VB.Shape Curve 
      Height          =   1455
      Index           =   3
      Left            =   5880
      Tag             =   "TL"
      Top             =   3960
      Width           =   1455
   End
   Begin VB.Shape Curve 
      Height          =   1455
      Index           =   2
      Left            =   7320
      Tag             =   "BL"
      Top             =   3960
      Width           =   1455
   End
   Begin VB.Shape shpBall 
      FillStyle       =   0  'Solid
      Height          =   255
      Left            =   600
      Shape           =   3  'Circle
      Top             =   2520
      Width           =   255
   End
   Begin VB.Shape Curve 
      Height          =   1455
      Index           =   1
      Left            =   5880
      Tag             =   "TR"
      Top             =   2520
      Width           =   1455
   End
   Begin VB.Shape Curve 
      Height          =   1455
      Index           =   0
      Left            =   7440
      Tag             =   "BR"
      Top             =   1440
      Width           =   1455
   End
   Begin VB.Shape Shape 
      FillStyle       =   0  'Solid
      Height          =   375
      Index           =   4
      Left            =   360
      Top             =   7320
      Width           =   1215
   End
   Begin VB.Shape Shape 
      FillStyle       =   0  'Solid
      Height          =   2175
      Index           =   3
      Left            =   120
      Top             =   4920
      Width           =   375
   End
   Begin VB.Shape Shape 
      FillStyle       =   0  'Solid
      Height          =   375
      Index           =   2
      Left            =   1920
      Top             =   5880
      Width           =   1455
   End
   Begin VB.Shape Shape 
      FillStyle       =   0  'Solid
      Height          =   735
      Index           =   1
      Left            =   2040
      Top             =   2520
      Width           =   2175
   End
   Begin VB.Shape Shape 
      FillStyle       =   0  'Solid
      Height          =   3255
      Index           =   0
      Left            =   4680
      Top             =   2520
      Width           =   1215
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Dim PredictedX As Double
Dim PredictedY As Double
Dim CheckU As Integer
Dim CheckD As Integer
Dim i As Integer
Dim j As Integer
Dim k As Integer
Private Const pi As Double = 3.14
Private Type typBall
    Mass As Double              'How Heavy is 1 unit (120 by 120) of this object?
    Height As Double            'The object's height
    Width As Double             'The object's width
    X As Double                 'X coordinate of the ball
    Y As Double                 'Y coordinate of the ball
    Speed(1 To 2) As Double     'Speed of the ball as a vector in X and Y (1=x, 2=y)
    Accel(1 To 2) As Double     'Accelleration of the ball as a vector in X and Y (1=x, 2=y)
    CoeffRestitution As Double  'General coefficient of restitution (different for each surface - based on contact with the form edges) (0-1)
    CoeffFriction As Double     'General coefficient of friction (different for each surface - based on contact with the form edges) (0-1)
    AirResistance As Double     'How much wind effects this object 0=none, 1 = fully
    State As String             'Used in code, do decide what physics to apply
End Type
Private Type typEnvironment
    WindStrength As Double      '0=none, 10=extreamly strong wind
    WindDirX As Double          'The resultant force of winddirx and winddiry should = 1
    WindDirY As Double          'The resultant force of winddirx and winddiry should = 1
    Gravity As Double           'Measured up. Earth is -9.8
End Type
Dim Ball As typBall
Dim Earth As typEnvironment
Dim EnvUsed As typEnvironment
Dim TimerTimeCoeff As Double
Dim AlreadyBounced As Boolean
Private Sub Form_Activate()
    'Set up the curve's pictures
    For i = 0 To Curve.Count - 1
        Curve(i).BorderStyle = 0
    Next i
    
    'For i = 0 To Curve.Count - 1
    '    Call MakeCurve(i)
    'Next i
    
    TimerTimeCoeff = 25 / MoveBall.Interval
    Ball.Mass = 0.5
    Ball.Height = shpBall.Height
    Ball.Width = shpBall.Width
    Ball.X = shpBall.Left + (Ball.Width / 2)
    Ball.Y = Form1.Height - shpBall.Top + (Ball.Height / 2)
    Ball.AirResistance = 0.5
    Ball.CoeffFriction = 0.1 'As it is a ball there won't be much friction
    Ball.CoeffRestitution = 0.9 'Quite Bouncy
    Ball.Speed(1) = 100
    Ball.Speed(2) = 100
    Ball.State = "F"
    
    Earth.Gravity = -9.8
    Earth.WindDirX = 1
    Earth.WindDirY = 0
    Earth.WindStrength = 1

    EnvUsed = Earth
End Sub
Private Sub MoveBall_Timer()
    shpBall.Left = Ball.X - (shpBall.Width / 2)
    shpBall.Top = Form1.Height - Ball.Y - (Ball.Height / 2)
    If Ball.State = "G" Then Call Check4Ground
    With EnvUsed
        Ball.Accel(1) = 0
        Ball.Accel(2) = 0
        'Gravity
        If Ball.State = "F" Then Ball.Accel(2) = Ball.Accel(2) + .Gravity
        'Wind
        Ball.Accel(1) = Ball.Accel(1) + (.WindDirX * .WindStrength * Ball.AirResistance)
        If Ball.State = "F" Then
            'Only apply verticle wind, and gravity if the ball is in the air
            Ball.Accel(2) = Ball.Accel(2) + (.WindDirY * .WindStrength * Ball.AirResistance)
        End If
        If Ball.State = "G" Then
            'Apply Friction
            If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * .Gravity * Ball.CoeffFriction)
            If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * .Gravity * Ball.CoeffFriction)
        End If
    End With

    With Ball
        'Check for collisions with the form
        Call CheckHitForm
        Call CheckHitShape
        'Call CheckHitCurve 'Doesn't work yet!
        
        'Apply all the physics to the ball
        .Speed(1) = .Speed(1) + (.Accel(1) / TimerTimeCoeff)
        .Speed(2) = .Speed(2) + (.Accel(2) / TimerTimeCoeff)
        If .State = "G" Then .Speed(2) = 0
        .X = .X + (.Speed(1) / TimerTimeCoeff)
        .Y = .Y + (.Speed(2) / TimerTimeCoeff)
    End With
End Sub
Private Sub CheckHitForm()
    CheckU = 100
    CheckD = 0
    
    'Check the bottom of the form
    Do While CheckU > CheckD + 1
        If Ball.Y + (Ball.Speed(2) * (((CheckU - CheckD) / 2) + CheckD) / 100) < (Ball.Height / 2) + 475 Then
            CheckD = ((CheckU - CheckD) / 2) + CheckD
        Else
            CheckU = ((CheckU - CheckD) / 2) + CheckD
        End If
    Loop
    
    If CheckD > 0 Then
        Ball.Speed(2) = Abs(Ball.Speed(2)) * Ball.CoeffRestitution
        If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * EnvUsed.Gravity * Ball.CoeffFriction)
        If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * EnvUsed.Gravity * Ball.CoeffFriction)
        If Ball.Speed(2) < Abs(EnvUsed.Gravity) Then Ball.State = "G"
    End If
    
    CheckU = 100
    CheckD = 0
    
    'Check the top of the form
    Do While CheckU > CheckD + 1
        If Ball.Y + (Ball.Speed(2) * (((CheckU - CheckD) / 2) + CheckD) / 100) > Form1.Height - (Ball.Height / 2) Then
            CheckD = ((CheckU - CheckD) / 2) + CheckD
        Else
            CheckU = ((CheckU - CheckD) / 2) + CheckD
        End If
    Loop
    
    If CheckD > 0 Then
        Ball.Speed(2) = -Abs(Ball.Speed(2)) * Ball.CoeffRestitution
        If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * EnvUsed.Gravity * Ball.CoeffFriction)
        If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * EnvUsed.Gravity * Ball.CoeffFriction)
    End If
    
    CheckU = 100
    CheckD = 0
    
    'Check the left of the form
    Do While CheckU > CheckD + 1
        If Ball.X + (Ball.Speed(1) * (((CheckU - CheckD) / 2) + CheckD) / 100) < (Ball.Width / 2) Then
            CheckD = ((CheckU - CheckD) / 2) + CheckD
        Else
            CheckU = ((CheckU - CheckD) / 2) + CheckD
        End If
    Loop
    
    If CheckD > 0 Then
        Ball.Speed(1) = Abs(Ball.Speed(1)) * Ball.CoeffRestitution
        If Ball.Speed(2) > 0 Then Ball.Speed(2) = Ball.Speed(2) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
        If Ball.Speed(2) < 0 Then Ball.Speed(2) = Ball.Speed(2) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
    End If
    
    CheckU = 100
    CheckD = 0
    
    'Check the right of the form
    Do While CheckU > CheckD + 1
        If Ball.X + (Ball.Speed(1) * (((CheckU - CheckD) / 2) + CheckD) / 100) > Form1.Width - (Ball.Width / 2) - 100 Then
            CheckD = ((CheckU - CheckD) / 2) + CheckD
        Else
            CheckU = ((CheckU - CheckD) / 2) + CheckD
        End If
    Loop
    
    If CheckD > 0 Then
        Ball.Speed(1) = -Abs(Ball.Speed(1)) * Ball.CoeffRestitution
        If Ball.Speed(2) > 0 Then Ball.Speed(2) = Ball.Speed(2) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
        If Ball.Speed(2) < 0 Then Ball.Speed(2) = Ball.Speed(2) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
    End If
    
    
End Sub
Private Sub Check4Ground()
    'Check the form
    Ball.State = "F"
    If Ball.Y - (Ball.Height / 2) <= 475 Then Ball.State = "G"
    
    'Check the various shapes
    
    For i = 0 To Shape.Count - 1
        CheckU = 100
        CheckD = 0
        
        'Check the bottom of the box
        Do While CheckU > CheckD + 1
            PredictedX = Ball.X + (Ball.Speed(1) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            PredictedY = Ball.Y + (Ball.Speed(2) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            If Form1.Height - PredictedY < Shape(i).Top + Ball.Width And Form1.Height - PredictedY > Shape(i).Top - Ball.Width And PredictedX > Shape(i).Left And PredictedX < Shape(i).Left + Shape(i).Width Then
                CheckD = ((CheckU - CheckD) / 2) + CheckD
            Else
                CheckU = ((CheckU - CheckD) / 2) + CheckD
            End If
        Loop
        
        If CheckD > 0 Then
            Select Case Shape(i).Shape
                Case 0 'Rectangle
                    Ball.State = "G"
            End Select
        End If
    Next i
End Sub
Private Sub CheckHitShape()
    For i = 0 To Shape.Count - 1
        CheckU = 100
        CheckD = 0
        
        'Check the top of the box
        Do While CheckU > CheckD + 1
            PredictedX = Ball.X + (Ball.Speed(1) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            PredictedY = Ball.Y + (Ball.Speed(2) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            If Form1.Height - PredictedY < Shape(i).Top + 100 And Form1.Height - PredictedY > Shape(i).Top + 100 - Ball.Width And PredictedX > Shape(i).Left And PredictedX < Shape(i).Left + Shape(i).Width Then
                CheckD = ((CheckU - CheckD) / 2) + CheckD
            Else
                CheckU = ((CheckU - CheckD) / 2) + CheckD
            End If
        Loop
        
        If CheckD > 0 Then
            Select Case Shape(i).Shape
                Case 0 'Rectangle
                    Ball.Speed(2) = Abs(Ball.Speed(2)) * Ball.CoeffRestitution
                    If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * EnvUsed.Gravity * Ball.CoeffFriction)
                    If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * EnvUsed.Gravity * Ball.CoeffFriction)
                    If Ball.Speed(2) < Abs(EnvUsed.Gravity) Then Ball.State = "G"
            End Select
        End If
        
        
        
        CheckU = 100
        CheckD = 0
        
        'Check the bottom of the box
        Do While CheckU > CheckD + 1
            PredictedX = Ball.X + (Ball.Speed(1) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            PredictedY = Ball.Y + (Ball.Speed(2) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            If Form1.Height - PredictedY < Shape(i).Top + Shape(i).Height + 100 And Form1.Height - PredictedY > Shape(i).Top + Shape(i).Height + 100 - Ball.Width And PredictedX > Shape(i).Left And PredictedX < Shape(i).Left + Shape(i).Width Then
                CheckD = ((CheckU - CheckD) / 2) + CheckD
            Else
                CheckU = ((CheckU - CheckD) / 2) + CheckD
            End If
        Loop
        
        If CheckD > 0 Then
            Select Case Shape(i).Shape
                Case 0 'Rectangle
                    Ball.Speed(2) = -Abs(Ball.Speed(2)) * Ball.CoeffRestitution
                    If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * EnvUsed.Gravity * Ball.CoeffFriction)
                    If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * EnvUsed.Gravity * Ball.CoeffFriction)
            End Select
        End If
        
        
        CheckU = 100
        CheckD = 0
        
        'Check the right of the box
        Do While CheckU > CheckD + 1
            PredictedX = Ball.X + (Ball.Speed(1) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            PredictedY = Ball.Y + (Ball.Speed(2) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            If PredictedX < Shape(i).Left + Shape(i).Width + 100 And PredictedX > Shape(i).Left + Shape(i).Width + 100 - Ball.Width And Form1.Height - PredictedY > Shape(i).Top And Form1.Height - PredictedY < Shape(i).Top + Shape(i).Height Then
                CheckD = ((CheckU - CheckD) / 2) + CheckD
            Else
                CheckU = ((CheckU - CheckD) / 2) + CheckD
            End If
        Loop
        
        If CheckD > 0 Then
            Select Case Shape(i).Shape
                Case 0 'Rectangle
                    Ball.Speed(1) = Abs(Ball.Speed(1)) * Ball.CoeffRestitution
                    If Ball.Speed(2) > 0 Then Ball.Speed(2) = Ball.Speed(2) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                    If Ball.Speed(2) < 0 Then Ball.Speed(2) = Ball.Speed(2) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
            End Select
        End If
        
        CheckU = 100
        CheckD = 0
        
        'Check the left of the box
        Do While CheckU > CheckD + 1
            PredictedX = Ball.X + (Ball.Speed(1) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            PredictedY = Ball.Y + (Ball.Speed(2) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            If PredictedX < Shape(i).Left + 100 And PredictedX > Shape(i).Left + 100 - Ball.Height And Form1.Height - PredictedY > Shape(i).Top And Form1.Height - PredictedY < Shape(i).Top + Shape(i).Height Then
                CheckD = ((CheckU - CheckD) / 2) + CheckD
            Else
                CheckU = ((CheckU - CheckD) / 2) + CheckD
            End If
        Loop
        
        If CheckD > 0 Then
            Select Case Shape(i).Shape
                Case 0 'Rectangle
                    Ball.Speed(1) = -Abs(Ball.Speed(1)) * Ball.CoeffRestitution
                    If Ball.Speed(2) > 0 Then Ball.Speed(2) = Ball.Speed(2) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                    If Ball.Speed(2) < 0 Then Ball.Speed(2) = Ball.Speed(2) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
            End Select
        End If
    Next i
End Sub
Private Sub MakeCurve(ThisOne)
    Select Case Curve(ThisOne).Tag
        Case "BR"
            For j = 0 To Curve(ThisOne).Width
                Line (Curve(ThisOne).Left + j, Curve(ThisOne).Top + Curve(ThisOne).Height)-(Curve(ThisOne).Left + Curve(ThisOne).Width, Curve(ThisOne).Top + Curve(ThisOne).Height - j)
            Next j
        Case "TR"
            For j = 0 To Curve(ThisOne).Width
                Line (Curve(ThisOne).Left + j, Curve(ThisOne).Top)-(Curve(ThisOne).Left + Curve(ThisOne).Width, Curve(ThisOne).Top + j)
            Next j
        Case "BL"
            For j = 0 To Curve(ThisOne).Width
                Line (Curve(ThisOne).Left + Curve(ThisOne).Width - j, Curve(ThisOne).Top + Curve(ThisOne).Height)-(Curve(ThisOne).Left, Curve(ThisOne).Top + Curve(ThisOne).Height - j)
            Next j
        Case "TL"
            For j = 0 To Curve(ThisOne).Width
                Line (Curve(ThisOne).Left + Curve(ThisOne).Width - j, Curve(ThisOne).Top)-(Curve(ThisOne).Left, Curve(ThisOne).Top + j)
            Next j
    End Select
End Sub
Private Sub CheckHitCurve()
    For i = 0 To Curve.Count - 1
        CheckU = 100
        CheckD = 0
        
        'Do a general check as to whether the ball in about to be within the curve's bounds
        Do While CheckU > CheckD + 1
            PredictedX = Ball.X + (Ball.Speed(1) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            PredictedY = Ball.Y + (Ball.Speed(2) * (((CheckU - CheckD) / 2) + CheckD) / 100)
            PredictedY = Form1.Height - PredictedY
            
            If PredictedX + (Ball.Width / 2) > Curve(i).Left And PredictedX - (Ball.Width / 2) < Curve(i).Left + Curve(i).Width And PredictedY + (Ball.Height / 2) > Curve(i).Top And PredictedY - (Ball.Height / 2) < Curve(i).Top + Curve(i).Height Then
                CheckD = ((CheckU - CheckD) / 2) + CheckD
            Else
                CheckU = ((CheckU - CheckD) / 2) + CheckD
            End If
        Loop
        If CheckD > 0 Then
            AlreadyBounced = False
            'The ball is with in the curve shape (well, it will be)
            Select Case Curve(i).Tag
                Case "TL"
                    If PredictedX < Curve(i).Left + Abs(Ball.Speed(1) / 2) And Ball.Speed(1) > 0 Then
                        'The ball is hitting the left side of the curve (i.e. a flat side)
                        Ball.Speed(1) = -Abs(Ball.Speed(1)) * Ball.CoeffRestitution
                        If Ball.Speed(2) > 0 Then Ball.Speed(2) = Ball.Speed(2) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        If Ball.Speed(2) < 0 Then Ball.Speed(2) = Ball.Speed(2) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        AlreadyBounced = True
                    End If
                    If PredictedY < Curve(i).Top + Abs(Ball.Speed(2) / 2) And Ball.Speed(2) < 0 Then
                        'The ball is hitting the top of the curve (i.e. flat)
                        Ball.Speed(2) = Abs(Ball.Speed(2)) * Ball.CoeffRestitution
                        If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        AlreadyBounced = True
                    End If
                    If AlreadyBounced = False Then Call CurveBounce("TL")
                Case "BL"
                    If PredictedX < Curve(i).Left + Abs(Ball.Speed(1) / 2) And Ball.Speed(1) > 0 Then
                        'The ball is hitting the left side of the curve (i.e. a flat side)
                        Ball.Speed(1) = -Abs(Ball.Speed(1)) * Ball.CoeffRestitution
                        If Ball.Speed(2) > 0 Then Ball.Speed(2) = Ball.Speed(2) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        If Ball.Speed(2) < 0 Then Ball.Speed(2) = Ball.Speed(2) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        AlreadyBounced = True
                    End If
                    If PredictedY + Ball.Height > Curve(i).Top + Curve(i).Height - Abs(Ball.Speed(2) / 2) And Ball.Speed(2) > 0 Then
                        'The ball is hitting the bottom of the curve (i.e. flat)
                        Ball.Speed(2) = -Abs(Ball.Speed(2)) * Ball.CoeffRestitution
                        If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        AlreadyBounced = True
                    End If
                    If AlreadyBounced = False Then Call CurveBounce("BL")
                Case "TR"
                    If PredictedX > Curve(i).Left + Curve(i).Width - Abs(Ball.Speed(1) / 2) And Ball.Speed(1) < 0 Then
                        'The ball is hitting the right side of the curve (i.e. a flat side)
                        Ball.Speed(1) = Abs(Ball.Speed(1)) * Ball.CoeffRestitution
                        If Ball.Speed(2) > 0 Then Ball.Speed(2) = Ball.Speed(2) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        If Ball.Speed(2) < 0 Then Ball.Speed(2) = Ball.Speed(2) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        AlreadyBounced = True
                    End If
                    If PredictedY < Curve(i).Top + Abs(Ball.Speed(2) / 2) And Ball.Speed(2) < 0 Then
                        'The ball is hitting the top of the curve (i.e. flat)
                        Ball.Speed(2) = Abs(Ball.Speed(2)) * Ball.CoeffRestitution
                        If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        AlreadyBounced = True
                        If AlreadyBounced = False Then Call CurveBounce("TR")
                    End If
                Case "BR"
                    If PredictedX > Curve(i).Left + Curve(i).Width - Abs(Ball.Speed(1) / 2) And Ball.Speed(1) < 0 Then
                        'The ball is hitting the right side of the curve (i.e. a flat side)
                        Ball.Speed(1) = Abs(Ball.Speed(1)) * Ball.CoeffRestitution
                        If Ball.Speed(2) > 0 Then Ball.Speed(2) = Ball.Speed(2) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        If Ball.Speed(2) < 0 Then Ball.Speed(2) = Ball.Speed(2) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        AlreadyBounced = True
                    End If
                    If PredictedY + Ball.Height > Curve(i).Top + Curve(i).Height - Abs(Ball.Speed(2) / 2) And Ball.Speed(2) > 0 Then
                        'The ball is hitting the bottom of the curve (i.e. flat)
                        Ball.Speed(2) = -Abs(Ball.Speed(2)) * Ball.CoeffRestitution
                        If Ball.Speed(1) > 0 Then Ball.Speed(1) = Ball.Speed(1) + (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        If Ball.Speed(1) < 0 Then Ball.Speed(1) = Ball.Speed(1) - (Ball.Mass * (Ball.Height / 800) * (Ball.Width / 800) * Ball.Speed(1) * Ball.CoeffFriction)
                        AlreadyBounced = True
                    End If
                    If AlreadyBounced = False Then Call CurveBounce("BR")
            End Select
        End If
    Next i
End Sub
Private Sub CurveBounce(CurvePos As String)
    Dim VecCirc2Col(1 To 2) As Double 'The vector from the circle to the collision point
    Dim GradTanCirc As Double 'The gradient of the circle at the point of contact
    Dim AngleTanCirc As Double 'The angle made by the x-axis and the tangent of the circle at the point of contact
    Dim AngleVeloTanCirc As Double 'The angle made by the velocity vector and the tangent of the circle at the point of contact
    Dim NewAngleVelo As Double 'The new angle we want the veolcity to make with the x-axis
    Dim BallSpeed As Double 'The resolved veolcity of the ball
    
    BallSpeed = Sqr((Ball.Speed(1) ^ 2) + (Ball.Speed(2) ^ 2))
    
    VecCirc2Col(1) = PredictedX - Curve(i).Left
    VecCirc2Col(2) = PredictedY - Curve(i).Top
    
    Select Case CurvePos
        Case "BR"
            If Sqr((VecCirc2Col(1) ^ 2) + (VecCirc2Col(2) ^ 2)) < Curve(i).Height Then
                Exit Sub 'Make sure the ball actually hit the curve, and didn't just enter the box surrounding it
            End If
            'Ok, so we know that the ball has collided, so now what?
            
            GradTanCirc = -1 / (VecCirc2Col(2) / VecCirc2Col(1))
            AngleTanCirc = Atn(GradTanCirc)
            
            AngleVeloTanCirc = Atn(Ball.Speed(2) / Ball.Speed(1))
            
            
            NewAngleVelo = AngleTanCirc - (AngleVeloTanCirc * 2) - Rad(90)
            
            Ball.Speed(1) = Cos(NewAngleVelo) * BallSpeed
            Ball.Speed(2) = Sin(NewAngleVelo) * BallSpeed
    End Select
End Sub
Private Function Rad(Degs)
    Rad = Degs * pi / 180
End Function
Private Function Deg(Rads)
    Deg = Rads * 180 / pi
End Function
