-
Notifications
You must be signed in to change notification settings - Fork 0
/
BubbleSort.module.lua
262 lines (213 loc) · 7.35 KB
/
BubbleSort.module.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
local BubbleSortDemo = {}
-- ARRAY CONSTANTS
local DICE_COUNT = 30
local DICE_HEIGHT_VARIATIONS = 20
-- DICE PROPERTIES
local DICE_BASE_SIZE = Vector3.new(4, 4, 0.4)
local DICE_COLOR_START = Color3.fromRGB(128, 128, 128)
local DICE_COLOR_SWAP = Color3.fromRGB(255, 251, 0)
local DICE_COLOR_FINISH = Color3.fromRGB(0, 255, 0)
local DICE_BRICK_COLOR_FINISH = BrickColor.new("Lime green")
local DICE_MATERIAL = "Metal"
local DICE_HEIGHT_STEP = 1.1
local DICE_DISTANCE_BETWEEN = 2
local DICE_ABOVE_SURFACE = 1.5
local DICE_COMPARE_DISTANCE = 6
-- TIMINGS
local WAIT_BEFORE_SELECT = 0.125
local MOVE_TO_COMPARE = 0.35
local WAIT_BEFORE_COMPARE_RESULT = 0.05
local WAIT_AFTER_COMPARE_RESULT = 0.35
local SWAP_DURATION = 0.35
local WAIT_AFTER_SWAP = 0.1
local MOVE_FROM_COMPARE = 0.35
local WAIT_BEFORE_DESELECT = 0.05
local TIME_OF_DAY_MOVING = 0.01
local TweenService = game:GetService("TweenService")
local Lighting = game:GetService("Lighting")
math.randomseed(os.time())
local function moveTimeOfDay()
Lighting.ClockTime = Lighting.ClockTime + TIME_OF_DAY_MOVING
end
local function calcPositionOnSurface(position, sizeY)
return Vector3.new(position.X, DICE_ABOVE_SURFACE + sizeY / 2, position.Z)
end
local function positionOnSurface(part)
part.Position = calcPositionOnSurface(part.Position, part.Size.Y)
end
local function moveOverTime(part, endPosition, duration)
local tweenInfo = TweenInfo.new(duration, Enum.EasingStyle.Linear)
local tween = TweenService:Create(part, tweenInfo, {Position = endPosition})
tween:Play()
end
local function rotateOverTime(part, angle, duration)
local rotationTweenInfo = TweenInfo.new(duration, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local rotate = Vector3.new(0, angle, 0)
local rotationTween = TweenService:Create(part, rotationTweenInfo, {Rotation = rotate})
rotationTween:Play()
end
local function createComparatorUi(position)
local size = Vector3.new(0.1, 4, 4)
local part = Instance.new("Part")
part.Size = size
part.Position = position
positionOnSurface(part)
part.Material = DICE_MATERIAL
part.Color = Color3.fromRGB(255,255,255)
part.Anchored = true
part.Transparency = 1
part.Parent = game.Workspace
local surfaceGui = Instance.new("SurfaceGui")
surfaceGui.Face = "Left"
surfaceGui.Parent = part
surfaceGui.SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud
surfaceGui.PixelsPerStud = 10
local textLabel = Instance.new("TextLabel")
textLabel.Parent = surfaceGui
textLabel.Text = ""
textLabel.Size = UDim2.new(1, 0, 1, 0)
textLabel.TextScaled = true
textLabel.BackgroundTransparency = 1
textLabel.Font = Enum.Font.Arial
surfaceGui.Adornee = part
local comparatorUi = {
part = part,
surfaceGui = surfaceGui,
textLabel = textLabel,
}
return comparatorUi
end
local function hideComparatorUi(comparatorUi)
comparatorUi.textLabel.Text = ""
end
local function showComparatorUi(comparatorUi, left, right)
if (left.Size.Y < right.size.Y) then
comparatorUi.textLabel.Text = "<"
elseif (left.Size.Y > right.Size.Y) then
comparatorUi.textLabel.Text = ">"
else
comparatorUi.textLabel.Text = "="
end
end
local function createDice(position, height)
local diceSize = Vector3.new(DICE_BASE_SIZE.X, DICE_BASE_SIZE.Y + height * DICE_HEIGHT_STEP, DICE_BASE_SIZE.Z)
local part = Instance.new("Part")
part.Size = diceSize
part.Position = position
positionOnSurface(part)
part.Material = DICE_MATERIAL
part.Color = DICE_COLOR_START
part.Anchored = true
part.Parent = game.Workspace
return part
end
local function createDiceArray(center, count, maxNumber)
local result = {}
local point = Vector3.new(center.X, center.Y, center.Z - (count / 2) * DICE_DISTANCE_BETWEEN)
for i = 1, count do
local randomNumber = math.random(1, maxNumber)
local dice = createDice(point, randomNumber)
table.insert(result, dice)
point = Vector3.new(point.X, point.Y, point.Z + DICE_DISTANCE_BETWEEN)
end
return result
end
local function selectForSwap(part)
part.Color = DICE_COLOR_SWAP
end
local function deselect(part)
part.Color = DICE_COLOR_START
end
local function setFinish(part)
part.BrickColor = DICE_BRICK_COLOR_FINISH
part.Color = DICE_COLOR_FINISH
end
local function swapClockwise(leftPart, rightPart, duration)
leftPart.Orientation = Vector3.new(0, 0, 0)
rightPart.Orientation = Vector3.new(0, 0, 0)
local leftPos = leftPart.Position
local rightPos = rightPart.Position
local midZ = (leftPos.Z + rightPos.Z)/2
local topPosition = Vector3.new(leftPos.X + DICE_COMPARE_DISTANCE/2, leftPos.Y, midZ)
local bottomPosition = Vector3.new(rightPos.X - DICE_COMPARE_DISTANCE/2, rightPos.Y, midZ)
moveOverTime(leftPart, topPosition, duration/2)
rotateOverTime(leftPart, -90, duration/2)
moveOverTime(rightPart, bottomPosition, duration/2)
rotateOverTime(rightPart, -90, duration/2)
wait(duration/2)
rightPos = calcPositionOnSurface(rightPos, leftPart.Size.Y)
leftPos = calcPositionOnSurface(leftPos, rightPart.Size.Y)
moveOverTime(leftPart, rightPos, duration/2)
rotateOverTime(leftPart, -180, duration/2)
moveOverTime(rightPart, leftPos, duration/2)
rotateOverTime(rightPart, -180, duration/2)
wait(duration/2)
end
local function trySwap(left, right, pivot, comparatorUi)
local originLeftPos = left.Position
local originRightPos = right.Position
local leftComparePosition = pivot + Vector3.new(0,0,-DICE_COMPARE_DISTANCE / 2)
local rightComparePosition = pivot + Vector3.new(0,0,DICE_COMPARE_DISTANCE / 2)
leftComparePosition = calcPositionOnSurface(leftComparePosition, left.Size.Y)
rightComparePosition = calcPositionOnSurface(rightComparePosition, right.Size.Y)
moveOverTime(left, leftComparePosition, MOVE_TO_COMPARE)
moveOverTime(right, rightComparePosition, MOVE_TO_COMPARE)
wait(MOVE_TO_COMPARE + WAIT_BEFORE_COMPARE_RESULT)
moveTimeOfDay()
showComparatorUi(comparatorUi, left, right)
wait(WAIT_AFTER_COMPARE_RESULT)
if (left.Size.Y > right.Size.Y) then
swapClockwise(left, right, SWAP_DURATION)
wait(WAIT_AFTER_SWAP)
moveTimeOfDay()
originLeftPos = calcPositionOnSurface(originLeftPos, right.Size.Y)
originRightPos = calcPositionOnSurface(originRightPos, left.Size.Y)
hideComparatorUi(comparatorUi)
moveOverTime(left, originRightPos, MOVE_FROM_COMPARE)
moveOverTime(right, originLeftPos, MOVE_FROM_COMPARE)
wait(MOVE_FROM_COMPARE)
moveTimeOfDay()
return true
else
hideComparatorUi(comparatorUi)
moveOverTime(left, originLeftPos, MOVE_FROM_COMPARE)
moveOverTime(right, originRightPos, MOVE_FROM_COMPARE)
wait(MOVE_FROM_COMPARE)
moveTimeOfDay()
return false
end
end
local function bubbleSort(array, pivot, spectatorDistanceX)
local max = #array-1
local swapped = false
local comparePivot = pivot + Vector3.new(-spectatorDistanceX/2, 0, 0);
local comparatorUi = createComparatorUi(comparePivot)
while max >= 1 do
for i = 1, max do
wait(WAIT_BEFORE_SELECT)
moveTimeOfDay()
local left = array[i]
selectForSwap(left)
local right = array[i+1]
selectForSwap(right)
if (trySwap(left, right, comparePivot, comparatorUi)) then
local buf = left
array[i] = right
array[i+1] = buf
end
wait(WAIT_BEFORE_DESELECT)
moveTimeOfDay()
deselect(left)
deselect(right)
end
setFinish(array[max + 1])
max = max - 1
end
setFinish(array[1])
end
function BubbleSortDemo.start(point, spectatorDistanceX)
print("Started Demo")
local dices = createDiceArray(point, DICE_COUNT, DICE_HEIGHT_VARIATIONS)
bubbleSort(dices, point, spectatorDistanceX)
end
return BubbleSortDemo