Microsoft Small Basic

Program Listing: FKX723
' Rotating Classic Soccer Ball
' Copyright © 2018 Nonki Takahashi. The MIT License.

GraphicsWindow.Title = "Rotating Classic Soccer Ball"
GraphicsWindow.BackgroundColor = "Green"
Init()
r = ox
x = ox - r + dx
y = oy - r + dy
size = r * 2
a = 0
While "True"
DrawBall()
Program.Delay(10)
a = a + 1
If 360 <= a Then
a = a - 360
EndIf
RotateBall()
EndWhile

Sub AddEdges
' param polygon
nVertex = Array.GetItemCount(polygon)
For i1 = 1 To nVertex
i2 = i1 + 1
If nVertex < i2 Then
i2 = i2 - nVertex
EndIf
If polygon[i1] < polygon[i2] Then
edge = Text.Append(Text.Append(polygon[i1], "-"), polygon[i2])
Else
edge = Text.Append(Text.Append(polygon[i2], "-"), polygon[i1])
EndIf
If Not[Array.ContainsValue(edges, edge)] Then
nEdges = nEdges + 1
edges[nEdges] = edge
EndIf
EndFor
EndSub

Sub CalcHexagonCenter
For j = 1 To nHexagons
hexagon = hexagons[j]
hx[j] = 0
hy[j] = 0
hz[j] = 0
For i = 1 To 6
point = points[hexagon[i]]
hx[j] = hx[j] + point["x"]
hy[j] = hy[j] + point["y"]
hz[j] = hz[j] + point["z"]
EndFor
hx[j] = Math.Round(hx[j] * 100 / 6) / 100
hy[j] = Math.Round(hy[j] * 100 / 6) / 100
hz[j] = Math.Round(hz[j] * 100 / 6) / 100
EndFor
EndSub

Sub CalcPentagonCenter
For j = 1 To nPentagons
pentagon = pentagons[j]
px[j] = 0
py[j] = 0
pz[j] = 0
For i = 1 To 5
point = points[pentagon[i]]
px[j] = px[j] + point["x"]
py[j] = py[j] + point["y"]
pz[j] = pz[j] + point["z"]
EndFor
px[j] = Math.Round(px[j] * 100 / 5) / 100
py[j] = Math.Round(py[j] * 100 / 5) / 100
pz[j] = Math.Round(pz[j] * 100 / 5) / 100
EndFor
EndSub

Sub DrawBall
edges = ""
nEdges = 0
GraphicsWindow.BrushColor = "Black"
For j = 1 To nPentagons
If pz[j] <= oz Then
pentagon = pentagons[j]
FillPentagon()
polygon = pentagon
AddEdges()
EndIf
EndFor
GraphicsWindow.BrushColor = "White"
For j = 1 To nHexagons
If hz[j] <= oz Then
hexagon = hexagons[j]
FillHexagon()
polygon = hexagon
AddEdges()
EndIf
EndFor
For j = 1 To nEdges
edge = edges[j]
h = Text.GetIndexOf(edge, "-") ' hyphen
i1 = Text.GetSubText(edge, 1, h - 1)
i2 = Text.GetSubTextToEnd(edge, h + 1)
point = points[i1]
x1 = point["x"] + dx
y1 = point["y"] + dy
point = points[i2]
x2 = point["x"] + dx
y2 = point["y"] + dy
GraphicsWindow.DrawLine(x1, y1, x2, y2)
EndFor
EndSub

Sub FillHexagon
For i1 = 1 To 6
i2 = i1 + 1
If 6 < i2 Then
i2 = i2 - 6
EndIf
i3 = i1 + 3
If 6 < i3 Then
i3 = i3 - 6
EndIf
point = points[hexagon[i1]]
x1 = point["x"] + dx
y1 = point["y"] + dy
point = points[hexagon[i2]]
x2 = point["x"] + dx
y2 = point["y"] + dy
point = points[hexagon[i3]]
x3 = point["x"] + dx
y3 = point["y"] + dy
GraphicsWindow.FillTriangle(x1, y1, x2, y2, x3, y3)
EndFor
EndSub

Sub FillPentagon
For i1 = 1 To 5
i2 = i1 + 1
If 5 < i2 Then
i2 = i2 - 5
EndIf
i3 = i1 + 3
If 5 < i3 Then
i3 = i3 - 5
EndIf
point = points[pentagon[i1]]
x1 = point["x"] + dx
y1 = point["y"] + dy
point = points[pentagon[i2]]
x2 = point["x"] + dx
y2 = point["y"] + dy
point = points[pentagon[i3]]
x3 = point["x"] + dx
y3 = point["y"] + dy
GraphicsWindow.FillTriangle(x1, y1, x2, y2, x3, y3)
EndFor
EndSub

Sub Init
Not = "False=True;True=False;"
gw = 598
gh = 428
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
points[1] = "x=113.90;y=72.21;z=0.00;"
points[2] = "x=151.87;y=99.80;z=0.00;"
points[3] = "x=137.37;y=144.43;z=0.00;"
points[4] = "x=90.44;y=144.43;z=0.00;"
points[5] = "x=75.94;y=99.80;z=0.00;"
points[6] = "x=113.90;y=32.29;z=24.67;"
points[7] = "x=189.84;y=87.46;z=24.67;"
points[8] = "x=160.83;y=176.73;z=24.67;"
points[9] = "x=66.97;y=176.73;z=24.67;"
points[10] = "x=37.97;y=87.46;z=24.67;"
points[11] = "x=151.87;y=19.96;z=49.35;"
points[12] = "x=189.84;y=47.54;z=49.35;"
points[13] = "x=213.30;y=119.76;z=49.35;"
points[14] = "x=198.80;y=164.39;z=49.35;"
points[15] = "x=137.37;y=209.03;z=49.35;"
points[16] = "x=90.44;y=209.03;z=49.35;"
points[17] = "x=29.00;y=164.39;z=49.35;"
points[18] = "x=14.50;y=119.76;z=49.35;"
points[19] = "x=37.97;y=47.54;z=49.35;"
points[20] = "x=75.94;y=19.96;z=49.35;"
points[21] = "x=137.37;y=0.00;z=89.27;"
points[22] = "x=160.83;y=7.62;z=129.19;"
points[23] = "x=198.80;y=35.20;z=129.19;"
points[24] = "x=213.30;y=55.16;z=89.27;"
points[25] = "x=227.80;y=99.80;z=89.27;"
points[26] = "x=227.80;y=124.47;z=129.19;"
points[27] = "x=213.30;y=169.10;z=129.19;"
points[28] = "x=198.80;y=189.07;z=89.27;"
points[29] = "x=160.83;y=216.65;z=89.27;"
points[30] = "x=137.37;y=224.27;z=129.19;"
points[31] = "x=90.44;y=224.27;z=129.19;"
points[32] = "x=66.97;y=216.65;z=89.27;"
points[33] = "x=29.00;y=189.07;z=89.27;"
points[34] = "x=14.50;y=169.10;z=129.19;"
points[35] = "x=0.00;y=124.47;z=129.19;"
points[36] = "x=0.00;y=99.80;z=89.27;"
points[37] = "x=14.50;y=55.16;z=89.27;"
points[38] = "x=29.00;y=35.20;z=129.19;"
points[39] = "x=66.97;y=7.62;z=129.19;"
points[40] = "x=90.44;y=0.00;z=89.27;"
points[41] = "x=137.37;y=15.24;z=169.11;"
points[42] = "x=198.80;y=59.88;z=169.11;"
points[43] = "x=213.30;y=104.51;z=169.11;"
points[44] = "x=189.84;y=176.73;z=169.11;"
points[45] = "x=151.87;y=204.31;z=169.11;"
points[46] = "x=75.94;y=204.31;z=169.11;"
points[47] = "x=37.97;y=176.73;z=169.11;"
points[48] = "x=14.50;y=104.51;z=169.11;"
points[49] = "x=29.00;y=59.88;z=169.11;"
points[50] = "x=90.44;y=15.24;z=169.11;"
points[51] = "x=160.83;y=47.54;z=193.79;"
points[52] = "x=189.84;y=136.33;z=193.79;"
points[53] = "x=113.90;y=191.98;z=193.79;"
points[54] = "x=37.97;y=136.33;z=193.79;"
points[55] = "x=66.97;y=47.54;z=193.79;"
points[56] = "x=137.37;y=79.84;z=218.46;"
points[57] = "x=151.87;y=124.48;z=218.46;"
points[58] = "x=113.90;y=151.62;z=218.46;"
points[59] = "x=75.94;y=124.48;z=218.46;"
points[60] = "x=90.44;y=79.84;z=218.46;"
nPoints = Array.GetItemCount(points)
_points = points
ox = points[1]["x"]
oy = Math.Round((points[25]["y"] + points[26]["y"]) * 100 / 2) / 100
oz = (points[1]["z"] + points[56]["z"]) / 2
dx = gw / 2 - ox
dy = gh / 2 - oy
GraphicsWindow.PenColor = "#333333"
pentagons[1] = "1=1;2=2;3=3;4=4;5=5;"
pentagons[2] = "1=6;2=20;3=40;4=21;5=11;"
pentagons[3] = "1=7;2=12;3=24;4=25;5=13;"
pentagons[4] = "1=8;2=14;3=28;4=29;5=15;"
pentagons[5] = "1=9;2=16;3=32;4=33;5=17;"
pentagons[6] = "1=10;2=18;3=36;4=37;5=19;"
pentagons[7] = "1=51;2=42;3=23;4=22;5=41;"
pentagons[8] = "1=52;2=44;3=27;4=26;5=43;"
pentagons[9] = "1=53;2=46;3=31;4=30;5=45;"
pentagons[10] = "1=54;2=48;3=35;4=34;5=47;"
pentagons[11] = "1=55;2=50;3=39;4=38;5=49;"
pentagons[12] = "1=56;2=60;3=59;4=58;5=57;"
nPentagons = Array.GetItemCount(pentagons)
CalcPentagonCenter()
hexagons[1] = "1=1;2=6;3=11;4=12;5=7;6=2;"
hexagons[2] = "1=2;2=7;3=13;4=14;5=8;6=3;"
hexagons[3] = "1=3;2=8;3=15;4=16;5=9;6=4;"
hexagons[4] = "1=4;2=9;3=17;4=18;5=10;6=5;"
hexagons[5] = "1=5;2=10;3=19;4=20;5=6;6=1;"
hexagons[6] = "1=11;2=21;3=22;4=23;5=24;6=12;"
hexagons[7] = "1=13;2=25;3=26;4=27;5=28;6=14;"
hexagons[8] = "1=15;2=29;3=30;4=31;5=32;6=16;"
hexagons[9] = "1=17;2=33;3=34;4=35;5=36;6=18;"
hexagons[10] = "1=19;2=37;3=38;4=39;5=40;6=20;"
hexagons[11] = "1=21;2=40;3=39;4=50;5=41;6=22;"
hexagons[12] = "1=24;2=23;3=42;4=43;5=26;6=25;"
hexagons[13] = "1=28;2=27;3=44;4=45;5=30;6=29;"
hexagons[14] = "1=32;2=31;3=46;4=47;5=34;6=33;"
hexagons[15] = "1=36;2=35;3=48;4=49;5=38;6=37;"
hexagons[16] = "1=41;2=50;3=55;4=60;5=56;6=51;"
hexagons[17] = "1=43;2=42;3=51;4=56;5=57;6=52;"
hexagons[18] = "1=45;2=44;3=52;4=57;5=58;6=53;"
hexagons[19] = "1=47;2=46;3=53;4=58;5=59;6=54;"
hexagons[20] = "1=49;2=48;3=54;4=59;5=60;6=55;"
nHexagons = Array.GetItemCount(hexagons)
CalcHexagonCenter()
EndSub

Sub RotateBall
' param a - angle
_a = Math.GetRadians(a)
For i = 1 To nPoints
point = _points[i]
_x = point["x"] - ox
_z = point["z"] - oz
x = Math.Cos(_a) * _x - Math.Sin(_a) * _z
z = Math.Sin(_a) * _x + Math.Cos(_a) * _z
point["x"] = Math.Round(x * 100) / 100 + ox
point["z"] = Math.Round(z * 100) / 100 + oz
points[i] = point
EndFor
CalcPentagonCenter()
CalcHexagonCenter()
EndSub