-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.lua
474 lines (423 loc) · 11.1 KB
/
main.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
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
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
function _init()
-- enable mouse
poke(0x5f2d, 3)
-- disable key repeat
poke(0x5f5c, -1)
cursor_color = 7
--
debug = false
gtime = 0
gstate = 0
ndeath = 0
freeze_time = 0
shake = 0
cam = {x = 0, y = 0}
printable = 0
transi_core = nil
on_transition_closed = nil
transi = 0
transi_min = 0
transi_max = 32
--
exir_door_pos = {x = 105, y = 105}
levels = {level1_1, level1_2, level1_3, level1_4, level2_1, level2_2, level2_3, level2_4, level3_1, level3_2, level3_3, level3_4, level3_5, level3_6, level3_7}
current_level = 1
--
cartdata("mastoast_transilvaniawkward_v1")
-- reset save
-- for index = 1, #levels do
-- dset(index, 0)
-- end
-- -- complete save
-- for index = 1, #levels do
-- dset(index, 1)
-- end
for index = 1, #levels do
levels[index].cleared = (dget(index) == 1 and true) or false
end
init_menu()
-- queue_init(init_level)
-- queue_init(init_lvl_selection)
-- init_level()
-- create(bat, 64, 64)
end
-- gstate
-- 1 = Menu
-- 2 = Level Selection
-- 3 = Level
function init_menu()
gtime = 0
gstate = 1
objects = {}
particles = {}
--
menuitem(1)
menuitem(2)
create(chair, 56, 88)
local vamp = create(vampire, 40-4, 88)
vamp.flip_x = true
create(wolf, 72 + 4, 88)
create(chandelier, 11, 9)
create(chandelier, 11, 113)
create(chandelier, 115, 9)
music(0)
end
function init_lvl_selection()
gtime = 0
gstate = 2
objects = {}
particles = {}
menuitem(1, "back to menu", function() init_menu() end)
menuitem(2)
--
local margin_x = 12
local margin_y = 28
local line_size = 5
local distance = 23
for i = 0, #levels - 1 do
local lvl = create(door, margin_x + (i % line_size) * distance, margin_y + flr(i \ line_size) * distance)
lvl.index_lvl = i + 1
lvl.lvl = levels[i + 1]
end
transi_cor = cocreate(open_transition)
end
function queue_init(followup)
on_transition_closed = followup
transi_cor = cocreate(close_transition)
end
function init_level()
local level = levels[current_level]
gtime = 0
gstate = 3
objects = {}
particles = {}
target = nil
target_x = nil
target_y = nil
target_chair = nil
lwin = false
--
menuitem(1, "restart level", function() queue_init(init_level) end)
menuitem(2, "level selection", function() queue_init(init_lvl_selection) end)
menuitem(3, "reset progress", function() reset_progression() end)
--
level:init()
create(exit_door, exir_door_pos.x, exir_door_pos.y)
create(chandelier, 11, 9)
create(chandelier, 11, 113)
create(chandelier, 115, 9)
transi_cor = cocreate(open_transition)
end
function reset_progression()
for index = 1, #levels do
dset(index, 0)
levels[index].cleared = false
queue_init(init_menu)
end
end
function _update60()
-- timers
gtime += 1
--
if transi_cor and costatus(transi_cor) != 'dead' then
coresume(transi_cor)
return
else
transi_cor = nil
end
if gstate == 1 then
update_menu()
elseif gstate == 2 then
update_lvl_selection()
elseif gstate == 3 then
update_level()
end
end
function open_transition()
transi = transi_max
while transi > transi_min do
transi -= 1
yield()
end
end
function close_transition()
transi = transi_min
while transi < transi_max do
transi += 1
yield()
end
if on_transition_closed then
on_transition_closed()
end
end
function update_menu()
if btnp(❎) then queue_init(init_lvl_selection) end
for o in all(objects) do
if o.freeze > 0 then
o.freeze -= 1
else
o:update()
end
end
for a in all(particles) do
a:update()
end
end
function update_lvl_selection()
for o in all(objects) do
if o.freeze > 0 then
o.freeze -= 1
else
o:update()
end
if o.base != player and o.destroyed then
del(objects, o)
end
end
end
function update_level()
-- freeze
if freeze_time > 0 then
freeze_time -= 1
return
end
-- screenshake
shake = max(shake - 1)
-- player actions
if btnp(❎) then
if target then
release_target()
else
pickup_target()
end
update_solution()
end
if btnp(🅾️) then
reset_target()
update_solution()
end
if target then
target.x = stat(32) - target.hit_w /2
target.y = stat(33) - target.hit_h /2
end
if debug then
if stat(36) > 0 then
current_level = min(current_level + 1, #levels)
queue_init(init_level)
elseif stat(36) < 0 then
current_level = max(current_level - 1, 1)
queue_init(init_level)
end
end
-- update scene
for o in all(objects) do
if o.freeze > 0 then
o.freeze -= 1
else
o:update()
end
if o.base != player and o.destroyed then
del(objects, o)
end
end
for a in all(particles) do
a:update()
end
end
function update_solution()
local win = true
for o in all(objects) do
if o.base.base == monster then
if not o:update_solution() then win = false end
end
end
if win == true then
if not lwin then
spawn_particles(15,5,exir_door_pos.x + 8,exir_door_pos.y + 8, 10)
--
local txt = "level cleared"
local text = create(floating_text, 64 - (#txt * 2), 30)
text.text = txt
text.color = 7
text.t_max = 45
end
lwin = true
if not levels[current_level].cleared then
levels[current_level].cleared = true
dset(current_level, 1)
end
else
lwin = false
end
end
function pickup_target()
for o in all(objects) do
if o.movable and on_cursor(o) then
if o.chair then
target_chair = o.chair
o.chair.user = nil
o.chair = nil
end
target = o
target_x, target_y = target.x, target.y
target.picked = true
spawn_particles(5,4,stat(32),stat(33),2)
break
end
end
end
function release_target()
if not target then return end
target.picked = false
if cursor_out_of_map() then
reset_target()
return
end
for o in all(objects) do
if o != target and on_cursor(o) then
if o.base == chair then
if o.user == nil then
o.user = target
target.chair = o
target.x, target.y = o.x, o.y
target, target_x, target_y, target_chair = nil
break
end
elseif o.movable then
switch_target(o)
break
end
end
end
target, target_x, target_y, target_chair = nil
spawn_particles(5,4,stat(32),stat(33),2)
end
function reset_target()
if not target then return end
target.x, target.y = target_x, target_y
if target_chair then
target.chair = target_chair
target.chair.user = target
end
target.picked = false
target, target_x, target_y, target_chair = nil
end
function switch_target(object)
spawn_particles(5,4,target_x,target_y,2)
local new_chair
if object.chair then
new_chair = object.chair
end
object.chair = nil
target.x = object.x
target.y = object.y
if target_chair then
object.chair = target_chair
target_chair.user = object
end
object.x = target_x
object.y = target_y
if new_chair then
target.chair = new_chair
new_chair.user = target
end
end
function cursor_out_of_map()
return stat(32) > 120 or stat(33) > 120 or stat(32) < 8 or stat(33) < 8
end
function _draw()
cls(0)
-- camera
if shake > 0 then
camera(cam.x - 2 + rnd(5), cam.y - 2 + rnd(5))
else
camera(cam.x, cam.y)
end
-- draw map
if gstate == 1 then
map(0, 0, 0, 0, 16, 16)
-- local moon_x, moon_y = 100, 23
-- circfill(moon_x, moon_y, 8, 7)
-- circfill(moon_x - 1, moon_y, 8, 6)
-- circfill(moon_x - 6, moon_y - 2, 8, 0)
elseif gstate == 2 then
map(0, 0, 0, 0, 16, 16)
if levels[#levels].cleared then
print_centered("thank you for playing !", 0-1, 105-1, 1)
print_centered("thank you for playing !", 0-1, 105+1, 1)
print_centered("thank you for playing !", 0, 105, 15)
end
elseif gstate == 3 then
map(0, 0, 0, 0, 16, 16)
end
-- draw objects
for o in all(objects) do
o:draw()
end
-- draw particles
for a in all(particles) do
a:draw()
end
-- UI
for o in all(objects) do
o:draw_ui()
end
if gstate == 1 then
local coord = 64 - (#"transilvaniawkward" * 2)
print("transilvani", coord - 1, 23 - 1, 1)
coord = print("transilvani", coord, 23, 7)
print("awkward", coord-1, 23-1, 1)
print("awkward", coord, 23, 9)
print_centered("press left click", -1, 64-1, 1)
print_centered("press left click", 0, 64, 7)
elseif gstate == 2 then
print_centered("level selection", -1, 13-1, 1)
print_centered("level selection", 0, 13, 7)
end
draw_cursor()
draw_transition()
if debug then
print(printable, cam.x + 80, cam.y + 120, 4)
end
end
function draw_cursor()
local pixels = {{x = 0, y = -2}, {x = -2, y = 0}, {x = 2, y = 0}, {x = 0, y = 2}, {x = 0, y = 0}}
for p in all(pixels) do
pset(stat(32) + p.x, stat(33) + p.y, cursor_color)
end
end
function draw_transition()
if transi == transi_min then return end
local ratio = transi / transi_max
circfill(64, 64, (128 / transi_max) * flr(transi), 10)
local height = bat.hit_h * ratio * 5
local width = bat.hit_w * ratio * 5
sspr((bat.spr % 16) * 8, flr(bat.spr \ 16) * 8, bat.hit_w, bat.hit_h, 64 - width, 64, width, height)
sspr((bat.spr % 16) * 8, flr(bat.spr \ 16) * 8, bat.hit_w, bat.hit_h, 64 - 1, 64, width, height, true, false)
end
-- UTILS
function get_distance(obj1, obj2)
return sqrt((obj2.x + obj2.hit_w/2 - obj1.x - obj1.hit_w/2)^2 + (obj2.y + obj2.hit_h/2 - obj1.y - obj1.hit_h/2)^2)
end
function on_cursor(object)
return object:contains(stat(32), stat(33))
end
-- linear interpolation
function lerp(start,finish,t)
return mid(start,start*(1-t)+finish*t,finish)
end
-- print at center
function print_centered(str, offset_x, y, col)
return print(str, cam.x + 64 - (#str * 2) + offset_x, y, col)
end
-- random range
function rrnd(min, max)
return flr(min + rnd(max - min))
end
-- find index for element in table
function find_item_table_index(item, table)
for k, v in pairs(table) do
if v == item then return k end
end
return 0
end