Microsoft Small Basic

Program Listing: NWP151-0
' Collision Sample
' Version 0.2
' Copyright © 2015 Nonki Takahashi. The MIT License.
' Subroutine CollisionCheck is written by litdev.
' Program ID NWP151-0
'
GraphicsWindow.Title = "Collision Sample"
gw = 598
gh = 428
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
fps = 20 ' [frame/s]
dt = 1 / fps ' [s]
g = 90 ' acceleratioon of gravity [pixel/s^2]
AddObjects()
While "True"
t1 = Clock.ElapsedMilliseconds
Gravity()
WallCheck()
CollisionCheck()
MoveObjects()
t2 = Clock.ElapsedMilliseconds
Program.Delay(Math.Max(1000 * dt - (t2 - t1), 0))
EndWhile
Sub AddObjects
Ball_Number = 10
Ball_Diameter = 32
r = Ball_Diameter / 2
GraphicsWindow.PenWidth = 0
GraphicsWindow.BrushColor = "Gray"
For i = 1 To Ball_Number
Ball_Obj[i] = Shapes.AddRectangle(Ball_Diameter, Ball_Diameter)
Ball_X[i] = Math.GetRandomNumber(gw - Ball_Diameter) + r
Ball_Y[i] = Math.GetRandomNumber(gh - Ball_Diameter) + r
Shapes.Move(Ball_Obj[i], Ball_X[i] - r, Ball_Y[i] - r)
EndFor
EndSub
Sub MoveObjects
For i = 1 To Ball_Number
Shapes.Move(Ball_Obj[i], Ball_X[i] - r, Ball_Y[i] - r)
EndFor
EndSub
Sub Gravity
For i = 1 To Ball_Number
' ax = 0
ay = g
vy = Ball_vY[i]
Ball_vY[i] = vy + dt * ay
Ball_X[i] = Ball_X[i] + Ball_vX[i] * dt
Ball_Y[i] = Ball_Y[i] + (vy + Ball_vY[i]) * dt / 2
EndFor
EndSub
Sub WallCheck
For i = 1 To Ball_Number
If Ball_X[i] - r < 0 Then
Ball_X[i] = Ball_X[i] + (r - Ball_X[i]) * 2
Ball_vX[i] = -Ball_vX[i]
ElseIf gw < Ball_X[i] + r Then
Ball_X[i] = Ball_X[i] - (Ball_X[i] + r - gw) * 2
Ball_vX[i] = -Ball_vX[i]
EndIf
If Ball_Y[i] - r < 0 Then
Ball_Y[i] = Ball_Y[i] + (r - Ball_Y[i]) * 2
Ball_vY[i] = -Ball_vY[i]
ElseIf gh < Ball_Y[i] + r Then
Ball_Y[i] = Ball_Y[i] - (Ball_Y[i] + r - gh) * 2
Ball_vY[i] = -Ball_vY[i]
EndIf
EndFor
EndSub
Sub CollisionCheck
' This subroutine is published by litdev in a TechNet Wiki article Small Basic: Dynamic Graphics.
' http://social.technet.microsoft.com/wiki/contents/articles/20865.small-basic-dynamic-graphics.aspx
For i = 1 To Ball_Number - 1
For j = i + 1 To Ball_Number
dx = Ball_X[i] - Ball_X[j]
dy = Ball_Y[i] - Ball_Y[j]
Distance = Math.SquareRoot(dx * dx + dy * dy)
If Distance < Ball_Diameter Then
Cx = (Ball_vX[i] + ball_vX[j]) / 2
Cy = (Ball_vY[i] + ball_vY[j]) / 2
Relative_vX[i] = Ball_vX[i] - Cx
Relative_vY[i] = Ball_vY[i] - Cy
Relative_vX[j] = Ball_vX[j] - Cx
Relative_vY[j] = Ball_vY[j] - Cy
Nx = dx / Distance
Ny = dy / Distance
L[i] = Nx * Relative_vX[i] + Ny * Relative_vY[i]
L[j] = Nx * Relative_vX[j] + Ny * Relative_vY[j]

Relative_vX[i] = Relative_vX[i] - (2 * L[i] * Nx)
Relative_vY[i] = Relative_vY[i] - (2 * L[i] * Ny)
Relative_vX[j] = Relative_vX[j] - (2 * L[j] * Nx)
Relative_vY[j] = Relative_vY[j] - (2 * L[j] * Ny)

Ball_vX[i] = (Relative_vX[i] + Cx)
Ball_vY[i] = (Relative_vY[i] + Cy)
Ball_vX[j] = (Relative_vX[j] + Cx)
Ball_vY[j] = (Relative_vY[j] + Cy)

Ball_X[i] = Ball_X[i] + Nx * (Ball_Diameter-Distance)
Ball_Y[i] = Ball_Y[i] + Ny * (Ball_Diameter-Distance)
Ball_X[j] = Ball_X[j] - Nx * (Ball_Diameter-Distance)
Ball_Y[j] = Ball_Y[j] - Ny * (Ball_Diameter-Distance)
EndIf
EndFor
EndFor
EndSub