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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
|
--A file to show what functions are used for minigames
print("rubick's circle included!")
--[[ 7 0 1
\ | /
\ | /
\|/
6---------2
/|\
/ | \
/ | \
]]-- 5 4 3
Game = Game or {}
--Required functions
--Called once when the plyer starts casting
Game.Cast = function(spelltab,difficulty)
--Initalization stuff
--[[The cirlces for this spelltab, each cirlce has dots, represtented as a number, 0 is empty]]--
spelltab.Circles = {}
--The win conditions stored in the same way as Circles
spelltab.Goal = {}
--The currently selected circle number, 0 is the inner most
spelltab.SelectedCircle = 0
--The Points that need to be filled, represtented as circle, then a number 0-7 on which direction needs to be filled
spelltab.Requirements = {}
--How many circles there are on the lowest difficulty
spelltab.numcircle = 3
--The Next input, the color(as a number) and a number 0-7 of the direction
spelltab.NextInputColor = 0
spelltab.NextInputDirection = 0
--When things are moveing
spelltab.Animateingringnum = -1
spelltab.Animateingdirection = 0
spelltab.Animateingstart = 0
spelltab.ANIMATE_MOVEING_DURATION = 0.5
--If the column is falling, can be more than one
spelltab.AnimateFalling = false
spelltab.AnimateFallingColumnNum = {}
spelltab.AnimateFallingStartLvl = {}
spelltab.AnimateFallingStartTime = 0
spelltab.ANIMATE_FALLING_DURATION = 0.5
spelltab.AnimateRemoveing = false
--All the points that need to be animated to be removed
--Organized the same way as spelltab.Circles
spelltab.AnimateRemoveingPoints = {}
spelltab.AnimateRemoveingStartTime = 0
spelltab.ANIMATE_REMOVE_DURATION = 0.5
spelltab.MaxColor = 3
spelltab.GoalNum = 2
--Create a dummy panel so that the mouse is trapped, untrap it when it right clicks
spelltab.Score = nil
local scoreboard = vgui.Create("MBFrame")
if(!scoreboard) then return end
scoreboard:SetPos(0,0)
scoreboard:SetSize(0,0)
scoreboard:MakePopup()
spelltab.scoreboard = scoreboard
spelltab.numcircle = 3
if(difficulty == 3) then
spelltab.numcircle = spelltab.numcircle+2
end
for i=0, spelltab.numcircle-1 do
spelltab.AnimateRemoveingPoints[i] = {}
spelltab.Circles[i] = {}
spelltab.Goal[i] = {}
for j = 0, 7 do
spelltab.AnimateRemoveingPoints[i][j] = false
--spelltab.Circles[i][j] = math.Round(math.random(0,3))
spelltab.Circles[i][j] = 0
spelltab.Goal[i][j] = 0
end
end
for i=0, 7 do
spelltab.AnimateFallingColumnNum[i] = false
spelltab.AnimateFallingStartLvl[i] = -1
end
spelltab.NextInputDirection = math.Round(math.random(0,7))
spelltab.NextInputColor = math.Round(math.random(1,spelltab.MaxColor))
--Generate 5 random spots and colors that need to be filled
local i = 0
while(i < spelltab.GoalNum) do
local randLvl = math.Round(math.random(0,spelltab.numcircle-2))
local randang = math.Round(math.random(0,7))
local randcolor = math.Round(math.random(1,spelltab.MaxColor))
if(spelltab.Goal[randLvl][randang] != 0) then continue
else
spelltab.Goal[randLvl][randang] = randcolor
i = i+1
end
end
end
--Called continuously while the player is casting
Game.Draw = function(self)
if not input.IsKeyTrapping() then
input.StartKeyTrapping()
end
draw.DrawText( "Fill in the empty circles with the appropriate colors. Click the circle to select them, and use Q nd E to rotate the circles.", "TargetID", ScrW() * 0.5, ScrH() * 0.25, Color( 255, 255, 255, 255 ), TEXT_ALIGN_CENTER )
--Draw the rings
for i = 0, self.numcircle-1 do
if(self.SelectedCircle == i) then
surface.DrawCircle(ScrW()/2,ScrH()/2,(i+1)*100,Color(255,255,255))
surface.DrawCircle(ScrW()/2,ScrH()/2,((i+1)*100)+5,Color(255,255,255))
surface.DrawCircle(ScrW()/2,ScrH()/2,((i+1)*100)-5,Color(255,255,255))
else
surface.DrawCircle(ScrW()/2,ScrH()/2,(i+1)*100,Color(255,255,255))
end
--Draw the circles on the rings
local angadd = ((self.Animateingstart-CurTime())/self.ANIMATE_MOVEING_DURATION)*45*self.Animateingdirection
local subdist = (((self.AnimateFallingStartTime-CurTime())/self.ANIMATE_FALLING_DURATION)*100)
local altraid = 20 - (((self.AnimateRemoveingStartTime-CurTime())/self.ANIMATE_REMOVE_DURATION)*20)
for j = 0, 7 do
if(self.Circles[i][j] != 0) then
local angle = (-j*45)+90
if(i == self.SelectedCircle)then
angle = angle+angadd
end
local mul = (i+1)*100
if(self.AnimateFallingColumnNum[j] and i > self.AnimateFallingStartLvl[j]) then
mul = mul + subdist
end
local x = (math.cos(math.rad(angle))*mul) + (ScrW()/2)
local y = (math.sin(math.rad(angle))*mul) + (ScrH()/2)
local radius = 20
if(self.AnimateRemoveingPoints[i][j]) then
radius = 40 - altraid
end
surface.DrawCircle(x,y,radius,self.ColorFor(self.Circles[i][j]))
end
if(self.Goal[i][j] != 0) then
local angle = (-j*45)+90
local mul = (i+1)*100
local x = (math.cos(math.rad(angle))*mul) + (ScrW()/2)
local y = (math.sin(math.rad(angle))*mul) + (ScrH()/2)
local color = self.ColorFor(self.Goal[i][j])
surface.SetDrawColor(color)
if(self.Goal[i][j] == self.Circles[i][j]) then
surface.DrawRect(x-20,y-20,40,40)
else
surface.DrawOutlinedRect(x-20,y-20,40,40)
end
end
end
end
--Draw the next-to-add circle
local mul = ((self.numcircle+1)*100)-50
local nextang = (-self.NextInputDirection*45)+90
local x = (math.cos(math.rad(nextang))*mul) + (ScrW()/2)
local y = (math.sin(math.rad(nextang))*mul) + (ScrH()/2)
local nextcol = self.ColorFor(self.NextInputColor)
surface.DrawCircle(x,y,20,nextcol)
--Deal with moveing stuff
if(self.Animateingringnum != -1 and CurTime() > self.Animateingstart+self.ANIMATE_MOVEING_DURATION) then
if(self.Animateingdirection == 1) then
local tmp = self.Circles[self.SelectedCircle][7]
for i = 0, 6 do
self.Circles[self.SelectedCircle][7-i]=self.Circles[self.SelectedCircle][6-i]
end
self.Circles[self.SelectedCircle][0] = tmp
self.Animateingringnum = -1
self.Animateingdirection = 0
--Add the new dot in, or fail if we can't
if(self.Circles[self.numcircle-1][self.NextInputDirection] != 0) then
print("self fail :(")
self.Score = 0
self.scoreboard:Remove()
else
self.Circles[self.numcircle-1][self.NextInputDirection] = self.NextInputColor
self.NextInputDirection = math.Round(math.random(0,7))
self.NextInputColor = math.Round(math.random(1,self.MaxColor))
end
self.ProcessMoved(self)
elseif(self.Animateingdirection == -1) then
local tmp = self.Circles[self.SelectedCircle][0]
for i = 0, 6 do
self.Circles[self.SelectedCircle][i]=self.Circles[self.SelectedCircle][i+1]
end
self.Circles[self.SelectedCircle][7] = tmp
self.Animateingringnum = -1
self.Animateingdirection = 0
--Add the new dot in, or fail if we can't
if(self.Circles[self.numcircle-1][self.NextInputDirection] != 0) then
print("self fail :(")
self.Score = 0
self.scoreboard:Remove()
else
self.Circles[self.numcircle-1][self.NextInputDirection] = self.NextInputColor
self.NextInputDirection = math.Round(math.random(0,7))
self.NextInputColor = math.Round(math.random(1,self.MaxColor))
end
self.ProcessMoved(self)
end
elseif(self.AnimateFalling and CurTime() > self.AnimateFallingStartTime + self.ANIMATE_FALLING_DURATION) then
for k,v in pairs(self.AnimateFallingColumnNum) do
if(v) then
for i = self.AnimateFallingStartLvl[k], self.numcircle-2 do
self.Circles[i][k] = self.Circles[i+1][k]
end
self.Circles[self.numcircle-1][k] = 0
end
end
for i = 0, 7 do
self.AnimateFalling = false
self.AnimateFallingColumnNum[i] = false
self.AnimateFallingStartLvl[i] = -1
end
self.ProcessMoved(self)
--[[
elseif(self.AnimateRemoveing and CurTime() > self.AnimateRemoveingStartTime + self.ANIMATE_REMOVE_DURATION) then
for i = 0, self.numcircle-1 do
for k = 0, 7 do
if(self.AnimateRemoveingPoints[i][k]) then
self.Circles[k][n] = 0
self.AnimateRemoveingPoints[k][n] = false
end
end
end
self.AnimateRemoveing = false
self.ProcessMoved()
]]--
elseif(input.IsKeyDown(KEY_Q)) then
--If anything is animateing, don't allow the player input
if(self.Animateingringnum != -1 or self.AnimateFalling) then return end
--Rotate stuff counter-clockwise
self.Animateingringnum = self.SelectedCircle
self.Animateingdirection = 1
self.Animateingstart = CurTime()
elseif(input.IsKeyDown(KEY_E)) then
--Don't move if animations are happeneing
if(self.Animateingringnum != -1 or self.AnimateFalling) then return end
--Rotate stuff clockwise
self.Animateingringnum = self.SelectedCircle
self.Animateingdirection = -1
self.Animateingstart = CurTime()
--Detect mouse input
elseif(input.IsMouseDown(MOUSE_LEFT)) then
local offset = math.Distance(gui.MouseX(),gui.MouseY(),ScrW()/2,ScrH()/2)
print("Offset:" .. offset)
for i = 0, self.numcircle-1 do
if(offset > (100*(i+1))-50 and offset < (100*(1+i))+50) then
self.SelectedCircle = i
end
end
end
if(input.IsMouseDown(MOUSE_RIGHT)) then
self.Score = 0
self.scoreboard:Remove()
end
end
Game.CheckCompleted = function(self)
local numcompleted = 0
for i=0,self.numcircle-1 do
for j=0, 7 do
if(self.Goal[i][j] != 0 and self.Circles[i][j] == self.Goal[i][j]) then
numcompleted = numcompleted + 1
end
end
end
if(numcompleted == self.GoalNum) then
self.Score = 100
self.scoreboard:Remove()
end
end
--What to do when anything moved
Game.ProcessMoved = function(self)
PrintTable(self)
if(self.Circles == nil) then
print("OH NO, CIRCLES WAS NIL!")
return
end
--First, check to see if anything is 3 in a column
for i = 0, 7 do
for j = 0, self.numcircle-3 do
if(self.Circles[j] == nil) then
print("J table:")
PrintTable(j)
--print("OH NO, CIRCLE " .. j .. " WAS NIL!")
return
end
local tomatch = self.Circles[j][i]
if(tomatch == 0) then continue end
local ismatching = true
for k = 0, 2 do
if(self.Circles[j+k][i] != tomatch) then
ismatching = false
break
end
end
if(ismatching) then
--PrintTable(self.Circles)
--print("Found a matching column ring " .. j .. " column " .. i .. " " .. tomatch)
for k = 0, 2 do
self.Circles[j+k][i] = 0
--self.AnimateRemoveingPoints[j+k][i] = true
--self.AnimateRemoveingStartTime = CurTime()
end
end
end
end
--Next, check to see if anything is 3 in a row
for i = 0, self.numcircle-1 do
for j = 0, 7 do
local tomatch = self.Circles[i][j]
if(tomatch == 0) then continue end
local ismatching = true
for k = 0,2 do
if(self.Circles[i][(j+k)%8] != tomatch) then
ismatching = false
break
end
end
if(ismatching) then
--PrintTable(self.Circles)
--print("Found a matching row ring " .. i .. " column " .. j .. " " .. tomatch)
for k = 0,2 do
self.Circles[i][(j+k)%8] = 0
--self.AnimateRemoveingPoints[i][(j+k)%8] = true
--self.AnimateRemoveingStartTime = CurTime()
end
end
end
end
--Next, check to see if we need to drop anything
for i = 0, 7 do
for j = 0, self.numcircle-1 do
if(self.Circles[j][i] == 0) then
for k=j, self.numcircle-1 do
if(self.Circles[k][i] != 0) then
--self.Circles[j][i] = self.Circles[k][i]
--self.Circles[k][i] = 0
self.AnimateFallingStartLvl[i] = j
self.AnimateFallingColumnNum[i] = true
self.AnimateFallingStartTime = CurTime()
self.AnimateFalling = true
--return
break
end
end
end
end
end
self.CheckCompleted(self)
end
Game.ColorFor = function(num)
if(num == 0) then return nil end
if(num == 1) then return Color(255,0,0) end
if(num == 2) then return Color(0,255,0) end
if(num == 3) then return Color(0,0,255) end
if(num == 4) then return Color(255,0,255) end
if(num == 5) then return Color(0,255,255) end
if(num == 6) then return Color(255,255,0) end
end
|