· 3 years ago · May 03, 2022, 04:20 AM
1local tArg = {...}
2local selfDelete = false -- if true, deletes extractor after running
3local file
4local outputPath = "gametest"
5local safeColorList = {[colors.white] = true,[colors.lightGray] = true,[colors.gray] = true,[colors.black] = true}
6local stc = function(color) if (term.isColor() or safeColorList[color]) then term.setTextColor(color) end end
7local choice = function()
8 local input = "yn"
9 write("[")
10 for a = 1, #input do
11 write(input:sub(a,a):upper())
12 if a < #input then
13 write(",")
14 end
15 end
16 print("]?")
17 local evt,char
18 repeat
19 evt,char = os.pullEvent("char")
20 until string.find(input:lower(),char:lower())
21 if verbose then
22 print(char:upper())
23 end
24 local pos = string.find(input:lower(), char:lower())
25 return pos, char:lower()
26end
27local archive = textutils.unserialize("{\
28 mainFile = \"game.lua\",\
29 compressed = false,\
30 data = {\
31 [ \".game/sprites/megaman/hurt.nft\" ] = \" 3ff3\\\
32 bfbf3\\\
33 3ff3b0b3ff3\\\
34bf33ffb0f03b
ffb\\\
35b 3ff3 fb
\\\
36 3fb33f\\\
37 3f
bb3fb3fb3fb\\\
38 b3fb bfbf\\\
39 bfb\\\
40 fb\",\
41 [ \".game/sprites/megaman/teleport3.nft\" ] = \"\\\
42\\\
43\\\
44\\\
45 bf3b\\\
46b3b\\\
47\\\
48bf3bb33bbf\\\
49bbf3b
b33bf\\\
50 3bb3
3bb3\\\
51 fb3b\",\
52 [ \".game/sprites/megaman/buster3-2.nft\" ] = \" 4f\\\
53 0f40f4f 4f0f4\\\
544f00f4
4f0404f\\\
550f0 f400f4\\\
56404f 4ff4004\\\
57 f040ff4 f4\",\
58 [ \".game/sprites/megaman/walk2.nft\" ] = \" bff3\\\
59 3fbb03ffb
\\\
60 3ff30b0ff0\\\
61 f3bf3ff0\\\
62 fbbf3f3b\\\
63 fb3ff3
\\\
64 bfbf\\\
65 fb\",\
66 [ \".game/sprites/megaman/climbshoot.nft\" ] = \" bffb\\\
67bf3ff3\\\
683fb3b0f
\\\
693bb30f0f3bf3\\\
70 f33fb0f3b\\\
713fb3\\\
723bfbbf3b\\\
73 bffb3bfb\\\
74 bfbf\\\
75 fb
\",\
76 [ \".game/sprites/megaman/teleport2.nft\" ] = \"\\\
77\\\
78\\\
79\\\
80\\\
81\\\
82\\\
83 bf3\\\
84bbf3b
b33bf\\\
85 3bb3
3bb3\\\
86 fb3b\",\
87 [ \".game/sprites/megaman/shoot.nft\" ] = \" bff3\\\
88 b30b3fb\\\
89 3fb00f
bffb\\\
90 bffbbf3fb03ff3bf\\\
91 fbbf33f\\\
92 3fbb3f3\\\
93 bf3fbfb\\\
94b fb\",\
95 [ \".game/sprites/megaman/buster2-1.nft\" ] = \" 4f\\\
964f0404f\\\
974004f4
\\\
98 f4\",\
99 [ \".game/sprites/megaman/jump.nft\" ] = \"bf bff3 bf\\\
100bbf3bb03ffb
bf
fb\\\
101 fbbff30b0ff0b3fb\\\
102 3f0f3f3\\\
103 33\\\
104 3bb3b3\\\
105 33f bfbf\\\
106 bf fb\\\
107 bfb\",\
108 [ \".game/sprites/megaman/teleport1.nft\" ] = \" 3fbbf3\\\
109 3bf3\\\
110 3bbf3\\\
111 3f
bf3\\\
112 3bb3f\\\
113 3fbbf3\\\
114 3fbf3\\\
115 3bb3f\\\
116 3fbbf3\\\
117 3bf3\\\
118 b3fb3
\",\
119 [ \".game/sprites/megaman/buster3-3.nft\" ] = \"\\\
120 0ff0 bf99bffb\\\
1214f
f040 bf9b9bf\\\
12204f0 9f9fb\\\
12340ff0 fb9f9b
\\\
124 f4 fb9\",\
125 [ \".game/sprites/megaman/walkshoot3.nft\" ] = \" 3ff3\\\
126 bfbf3\\\
127 b30bb0fbbf\\\
128 bf03f03ff3b3f\\\
129 bff33bb3ffb3b\\\
130bfbf3bb3f3fb\\\
131b3 f3bfb\\\
132 fb\",\
133 [ \".game/sprites/megaman/buster1.nft\" ] = \"f4f\\\
134440f4
\",\
135 [ \".game/sprites/megaman/jumpshoot.nft\" ] = \"bffb bff3\\\
136bbffbb30b3fb\\\
137 fb3bf00f
3f3bf3\\\
138 f33ffb0f3f3
b\\\
139 3f3f\\\
140 bf3b3b3fb\\\
141 3fb3f fbbffb\\\
142 fbbf fb\\\
143 bbf\\\
144 fb\",\
145 [ \".game/sprites/megaman/climb2.nft\" ] = \" bffb\\\
146bffbbf3b\\\
1473fbb33bbf\\\
1483bb3b3ffb\\\
149 f33fb3bf\\\
1503fb33ff3
\\\
1513bfbbf3b\\\
152 bffb3bfb\\\
153 bfbf\\\
154 fb
\",\
155 [ \".game/sprites/megaman/throw.nft\" ] = \" bff3\\\
156 b30b3fb\\\
157 3fb00f
\\\
158 bffbbf3fb03f\\\
159 fbbf33f3fb3\\\
160 3fbb3f3 fbbf\\\
161 bf3fbfb fb\\\
162b fb\",\
163 [ \".game/sprites/megaman/walk0.nft\" ] = \" bff3\\\
164 b30b3fb\\\
165 bf00f
\\\
166 bf3fb03fb\\\
167 bbf3f3fbffb\\\
168 fbbf
b3f3b\\\
169 bf
3f3fb3f\\\
170b fb\",\
171 [ \".game/sprites/megaman/stand1.nft\" ] = \" bff3\\\
172 3fbb03ffb
\\\
173 f30b0ff0\\\
174 bf33ff00f3fb\\\
175bff33fbfb\\\
176b3fb3b3bffb\\\
177 bfb3fbffb\\\
178b fb\",\
179 [ \".game/sprites/megaman/climbtop.nft\" ] = \" bffb\\\
180bf33ffb\\\
181bffbb3b3fb\\\
182 bf3b3ffb\\\
183 3f3f
bfbf\\\
184 bfbf\\\
185 fbbf\",\
186 [ \".game/maps/testmap.nft\" ] = \" 47 \\\
187 07 07 47 \\\
18807 47 3 4 3 4 3 4 3 4 \\\
18907 47 3 4 3 4 3 4 3 4 \\\
19007 47 3 4 3 4 3 4 3 4 07 07 \\\
19107 47 3 4 3 4 3 4 3 4 07 \\\
19207 47 3 4 3 4 3 4 3 4 07 \\\
19307 47 3 4 3 4 3 4 3 4 07 07 \\\
19407 47 3 4 3 4 3 4 3 4 0 07 \\\
19507 47 3 4 3 4 0 07 \\\
19607 47 47 0 07 \\\
19707 47 You can hit your 07 07 \\\
19807 47 head on the roof! 07 07 \\\
19907 47 07 07 \\\
20007 07 Sliding! 07 \\\
20107 07 (Down and Jump) 07 \\\
20207 07 07 \\\
20307 07 07 \\\
20407 07 07 \\\
20507 07 07 \\\
20607 07 07 07 \\\
20707 07 Slopes! 07 07 \\\
20807 07 07 07 \\\
20907 07 07 07 e 0 \\\
21007 07 Look at my engine! 07 07 e 0 \\\
21107 07 I spent too much 07 07 e 0 \\\
21207 time on this 07 Pits! 07 e 0 \\\
21307 07 e 0 \\\
21407 07 Scrolling! 07 e7 \\\
215 07 07 e7 0 e7 \\\
216 07 c7 c7 c7 c7 c7 c7 c7 e7 e7 Q to \\\
217 07 c7 c7 c7 c7 c7 c7 c7 c7 e7 e7 \\\
218 07 c7 c7 c7 c7 c7 c7 c7 c7 e7 e7 quit \\\
219 07 c7 c7 c7 c7 c7 c7 c7 c7 e7 e7 \\\
220 c7 c7 c7 c7 c7 e7 e7 \\\
221 c7 e7 e7 \\\
222 e7 e7 \\\
223 e7 e7 \\\
224 e7 e7 \",\
225 [ \".game/sprites/megaman/walk1.nft\" ] = \" 3ff3\\\
226 bfbf3\\\
227 bf3f3b0bb0fbbf\\\
228bfbf
3ffb0f0 bffb\\\
229bfb33ff03fbfb\\\
230bffbbf3bff3b\\\
231b3bf3fb
\\\
232 fb\",\
233 [ \".game/sprites/megaman/buster3-4.nft\" ] = \"\\\
234\\\
235 4f0f4\\\
2364400f\\\
237 f404\",\
238 [ \".game/sprites/megaman/walk4.nft\" ] = \" bff3\\\
239 3fbb03ffb
\\\
240 3ff30b0ff0\\\
241 f3bf3ff0\\\
242 fbbf3f3b\\\
243 fb3ff3
\\\
244 bfbf\\\
245 fb\",\
246 [ \"game.lua\" ] = \"local game = {}\\\
247game.path = fs.combine(fs.getDir(shell.getRunningProgram()),\\\".game\\\")\\\
248game.apiPath = fs.combine(game.path, \\\"api\\\")\\\
249game.spritePath = fs.combine(game.path, \\\"sprites\\\")\\\
250game.mapPath = fs.combine(game.path, \\\"maps\\\")\\\
251game.imagePath = fs.combine(game.path, \\\"image\\\")\\\
252game.configPath = fs.combine(game.path, \\\"config.cfg\\\")\\\
253\\\
254local scr_x, scr_y = term.getSize()\\\
255local mapname = \\\"testmap\\\"\\\
256\\\
257local scrollX = 0\\\
258local scrollY = 0\\\
259local killY = 100\\\
260\\\
261local keysDown = {}\\\
262\\\
263local tsv = function(visible)\\\
264 if term.current().setVisible then\\\
265 term.current().setVisible(visible)\\\
266 end\\\
267end\\\
268\\\
269local getAPI = function(apiName, apiPath, apiURL, doDoFile)\\\
270 apiPath = fs.combine(game.apiPath, apiPath)\\\
271 if not fs.exists(apiPath) then\\\
272 write(\\\"Getting \\\" .. apiName .. \\\"...\\\")\\\
273 local prog = http.get(apiURL)\\\
274 if prog then\\\
275 print(\\\"success!\\\")\\\
276 local file = fs.open(apiPath, \\\"w\\\")\\\
277 file.write(prog.readAll())\\\
278 file.close()\\\
279 else\\\
280 error(\\\"fail!\\\")\\\
281 end\\\
282 end\\\
283 if doDoFile then\\\
284 _ENV[fs.getName(apiPath)] = dofile(apiPath)\\\
285 else\\\
286 os.loadAPI(apiPath)\\\
287 end\\\
288end\\\
289\\\
290getAPI(\\\"NFT Extra\\\", \\\"nfte\\\", \\\"https://github.com/LDDestroier/NFT-Extra/raw/master/nfte\\\", false)\\\
291\\\
292-- load sprites from sprite folder\\\
293-- sprites are separated into \\\"sets\\\", but the only one here is \\\"megaman\\\" so whatever\\\
294\\\
295local sprites, maps = {}, {}\\\
296for k, set in pairs(fs.list(game.spritePath)) do\\\
297 sprites[set] = {}\\\
298 for num, name in pairs(fs.list(fs.combine(game.spritePath, set))) do\\\
299 sprites[set][name:gsub(\\\".nft\\\", \\\"\\\")] = nfte.loadImage(fs.combine(game.spritePath, set .. \\\"/\\\" .. name))\\\
300 print(\\\"Loaded sprite \\\" .. name:gsub(\\\".nft\\\",\\\"\\\"))\\\
301 end\\\
302end\\\
303for num, name in pairs(fs.list(game.mapPath)) do\\\
304 maps[name:gsub(\\\".nft\\\", \\\"\\\")] = nfte.loadImage(fs.combine(game.mapPath, name))\\\
305 print(\\\"Loaded map \\\" .. name:gsub(\\\".nft\\\",\\\"\\\"))\\\
306end\\\
307\\\
308local projectiles = {}\\\
309local players = {}\\\
310\\\
311local newPlayer = function(name, spriteset, x, y)\\\
312 return {\\\
313 name = name, -- player name\\\
314 spriteset = spriteset, -- set of sprites to use\\\
315 sprite = \\\"stand\\\", -- current sprite\\\
316 direction = 1, -- 1 is right, -1 is left\\\
317 xsize = 10, -- hitbox x size\\\
318 ysize = 8, -- hitbox y size\\\
319 x = x, -- x position\\\
320 y = y, -- y position\\\
321 xadj = 0, -- adjust x for good looks\\\
322 yadj = 0, -- adjust y for good looks\\\
323 xvel = 0, -- x velocity\\\
324 yvel = 0, -- y velocity\\\
325 maxVelocity = 8, -- highest posible speed in any direction\\\
326 jumpHeight = 2, -- height of jump\\\
327 jumpAssist = 0.5, -- assists jump while in air\\\
328 moveSpeed = 2, -- speed of walking\\\
329 gravity = 0.75, -- force of gravity\\\
330 slideSpeed = 4, -- speed of sliding\\\
331 grounded = false, -- is on solid ground\\\
332 shots = 0, -- how many shots onscreen\\\
333 maxShots = 3, -- maximum shots onscreen\\\
334 lemonSpeed = 3, -- speed of megabuster shots\\\
335 chargeLevel = 0, -- current charged buster level\\\
336 cycle = { -- used for animation cycles\\\
337 run = 0, -- used for run sprite\\\
338 shoot = 0, -- determines duration of shoot sprite\\\
339 shootHold = 0, -- forces user to release then push shoot\\\
340 stand = 0, -- used for high-octane eye blinking action\\\
341 slide = 0, -- used to limit slide length\\\
342 jump = 0, -- used to prevent auto-bunnyhopping\\\
343 shootCharge = 0, -- records how charged your megabuster is\\\
344 ouch = 0, -- records hitstun\\\
345 iddqd = 0 -- records invincibility frames\\\
346 },\\\
347 chargeDiscolor = { -- swaps colors during buster charging\\\
348 [0] = {{}},\\\
349 [1] = { -- charge level one\\\
350 {\\\
351 [\\\"b\\\"] = \\\"a\\\"\\\
352 },\\\
353 {\\\
354 [\\\"b\\\"] = \\\"b\\\"\\\
355 }\\\
356 },\\\
357 [2] = { -- woAH charge level two\\\
358 {\\\
359 --[\\\"f\\\"] = \\\"b\\\",\\\
360 [\\\"b\\\"] = \\\"3\\\",\\\
361 [\\\"3\\\"] = \\\"f\\\"\\\
362 },\\\
363 {\\\
364 --[\\\"f\\\"] = \\\"3\\\",\\\
365 [\\\"3\\\"] = \\\"b\\\",\\\
366 [\\\"b\\\"] = \\\"f\\\"\\\
367 },\\\
368 {\\\
369 --[\\\"f\\\"] = \\\"3\\\",\\\
370 [\\\"3\\\"] = \\\"b\\\",\\\
371 [\\\"b\\\"] = \\\"8\\\"\\\
372 }\\\
373 }\\\
374 },\\\
375 control = { -- inputs\\\
376 up = false, -- move up ladders\\\
377 down = false, -- move down ladders, or slide\\\
378 left = false, -- point and walk left\\\
379 right = false, -- point and walk right\\\
380 jump = false, -- jump, or slide\\\
381 shoot = false -- fire your weapon\\\
382 }\\\
383 }\\\
384end\\\
385\\\
386local deriveControls = function(keyList)\\\
387 return {\\\
388 up = keyList[keys.up],\\\
389 down = keyList[keys.down],\\\
390 left = keyList[keys.left],\\\
391 right = keyList[keys.right],\\\
392 jump = keyList[keys.x],\\\
393 shoot = keyList[keys.z]\\\
394 }\\\
395end\\\
396\\\
397-- main colision function\\\
398local isSolid = function(x, y)\\\
399 x = math.floor(x)\\\
400 y = math.floor(y)\\\
401 if (not maps[mapname][1][y]) or (x < 1) then\\\
402 return false\\\
403 else\\\
404 if (maps[mapname][1][y]:sub(x,x) == \\\" \\\" or\\\
405 maps[mapname][1][y]:sub(x,x) == \\\"\\\") and\\\
406 (maps[mapname][3][y]:sub(x,x) == \\\" \\\" or\\\
407 maps[mapname][3][y]:sub(x,x) == \\\"\\\") then\\\
408 return false\\\
409 else\\\
410 return true\\\
411 end\\\
412 end\\\
413end\\\
414\\\
415local isPlayerTouchingSolid = function(player, xmod, ymod, ycutoff)\\\
416 for y = player.y + (ycutoff or 0), player.ysize + player.y - 1 do\\\
417 for x = player.x, player.xsize + player.x - 1 do\\\
418 if isSolid(x + (xmod or 0), y + (ymod or 0)) then\\\
419 return \\\"map\\\"\\\
420 end\\\
421 end\\\
422 end\\\
423 return false\\\
424end\\\
425\\\
426you = 1\\\
427players[you] = newPlayer(\\\"LDD\\\", \\\"megaman\\\", 40, 8)\\\
428\\\
429local movePlayer = function(player, x, y)\\\
430 i = player.yvel / math.abs(player.yvel)\\\
431 for y = 1, math.abs(player.yvel) do\\\
432 if isPlayerTouchingSolid(player, 0, -i, (player.cycle.slide > 0 and 2 or 0)) then\\\
433 if player.yvel < 0 then\\\
434 player.grounded = true\\\
435 end\\\
436 player.yvel = 0\\\
437 break\\\
438 else\\\
439 player.y = player.y - i\\\
440 player.grounded = false\\\
441 end\\\
442 end\\\
443 i = player.xvel / math.abs(player.xvel)\\\
444 for x = 1, math.abs(player.xvel) do\\\
445 if isPlayerTouchingSolid(player, i, 0, (player.cycle.slide > 0 and 2 or 0)) then\\\
446 if player.grounded and not isPlayerTouchingSolid(player, i, -1) then -- upward slope detection\\\
447 player.y = player.y - 1\\\
448 player.x = player.x + i\\\
449 grounded = true\\\
450 else\\\
451 player.xvel = 0\\\
452 break\\\
453 end\\\
454 else\\\
455 player.x = player.x + i\\\
456 end\\\
457 end\\\
458end\\\
459\\\
460-- types of projectiles\\\
461\\\
462local bullet = {\\\
463 lemon = {\\\
464 damage = 1,\\\
465 element = \\\"neutral\\\",\\\
466 sprites = {\\\
467 sprites[\\\"megaman\\\"][\\\"buster1\\\"]\\\
468 },\\\
469 },\\\
470 lemon2 = {\\\
471 damage = 1,\\\
472 element = \\\"neutral\\\",\\\
473 sprites = {\\\
474 sprites[\\\"megaman\\\"][\\\"buster2-1\\\"],\\\
475 sprites[\\\"megaman\\\"][\\\"buster2-2\\\"]\\\
476 }\\\
477 },\\\
478 lemon3 = {\\\
479 damage = 4,\\\
480 element = \\\"neutral\\\",\\\
481 sprites = {\\\
482 sprites[\\\"megaman\\\"][\\\"buster3-1\\\"],\\\
483 sprites[\\\"megaman\\\"][\\\"buster3-2\\\"],\\\
484 sprites[\\\"megaman\\\"][\\\"buster3-3\\\"],\\\
485 sprites[\\\"megaman\\\"][\\\"buster3-4\\\"],\\\
486 }\\\
487 }\\\
488}\\\
489\\\
490local spawnProjectile = function(boolit, owner, x, y, xvel, yvel)\\\
491 projectiles[#projectiles+1] = {\\\
492 owner = owner,\\\
493 bullet = boolit,\\\
494 x = x,\\\
495 y = y,\\\
496 xvel = xvel,\\\
497 yvel = yvel,\\\
498 direction = xvel / math.abs(xvel),\\\
499 life = 32,\\\
500 cycle = 0,\\\
501 phaze = false,\\\
502 }\\\
503end\\\
504\\\
505local moveTick = function()\\\
506 local i\\\
507 for num, player in pairs(players) do\\\
508\\\
509 -- falling\\\
510 player.yvel = player.yvel - player.gravity\\\
511\\\
512 -- jumping\\\
513\\\
514 if player.control.jump then\\\
515 if player.grounded then\\\
516 if player.cycle.jump == 0 then\\\
517 if player.control.down and player.cycle.slide == 0 then\\\
518 player.cycle.slide = 6\\\
519 elseif not isPlayerTouchingSolid(player, 0, -1, 0) then\\\
520 player.yvel = player.jumpHeight\\\
521 player.cycle.slide = 0\\\
522 player.grounded = false\\\
523 end\\\
524 end\\\
525 player.cycle.jump = 1\\\
526 end\\\
527 if player.yvel > 0 and not player.grounded then\\\
528 player.yvel = player.yvel + player.jumpAssist\\\
529 end\\\
530 else\\\
531 player.cycle.jump = 0\\\
532 end\\\
533\\\
534 -- walking\\\
535\\\
536 if player.control.right then\\\
537 player.direction = 1\\\
538 player.xvel = player.moveSpeed\\\
539 elseif player.control.left then\\\
540 player.direction = -1\\\
541 player.xvel = -player.moveSpeed\\\
542 else\\\
543 player.xvel = 0\\\
544 end\\\
545 if player.cycle.slide > 0 then\\\
546 player.xvel = player.direction * player.slideSpeed\\\
547 end\\\
548\\\
549 -- shooting\\\
550\\\
551 if player.control.shoot then\\\
552 if player.cycle.shootHold == 0 then\\\
553 if player.shots < player.maxShots and player.cycle.slide == 0 then\\\
554 spawnProjectile(\\\
555 bullet.lemon,\\\
556 player,\\\
557 player.x + player.xsize * player.direction,\\\
558 player.y + 2,\\\
559 player.lemonSpeed * player.direction,\\\
560 0\\\
561 )\\\
562 player.cycle.shoot = 5\\\
563 player.shots = player.shots + 1\\\
564 end\\\
565 player.cycle.shootHold = 1\\\
566 end\\\
567 if player.cycle.shootHold == 1 then\\\
568 player.cycle.shootCharge = player.cycle.shootCharge + 1\\\
569 if player.cycle.shootCharge < 16 then\\\
570 player.chargeLevel = 0\\\
571 elseif player.cycle.shootCharge < 32 then\\\
572 player.chargeLevel = 1\\\
573 else\\\
574 player.chargeLevel = 2\\\
575 end\\\
576 end\\\
577 else\\\
578 player.cycle.shootHold = 0\\\
579 if player.shots < player.maxShots and player.cycle.slide == 0 then\\\
580 if player.cycle.shootCharge > 16 then\\\
581 if player.cycle.shootCharge >= 32 then\\\
582 spawnProjectile(\\\
583 bullet.lemon3,\\\
584 player,\\\
585 player.x + math.max(0, player.direction * player.xsize),\\\
586 player.y,\\\
587 player.lemonSpeed * player.direction,\\\
588 0\\\
589 )\\\
590 else\\\
591 spawnProjectile(\\\
592 bullet.lemon2,\\\
593 player,\\\
594 player.x + math.max(0, player.direction * player.xsize),\\\
595 player.y + 1,\\\
596 player.lemonSpeed * player.direction,\\\
597 0\\\
598 )\\\
599 end\\\
600 player.shots = player.shots + 1\\\
601 player.cycle.shoot = 5\\\
602 end\\\
603 end\\\
604 player.cycle.shootCharge = 0\\\
605 player.chargeLevel = 0\\\
606 end\\\
607\\\
608 -- movement\\\
609 if player.xvel > 0 then\\\
610 player.xvel = math.min(player.xvel, player.maxVelocity)\\\
611 else\\\
612 player.xvel = math.max(player.xvel, -player.maxVelocity)\\\
613 end\\\
614 if player.yvel > 0 then\\\
615 player.yvel = math.min(player.yvel, player.maxVelocity)\\\
616 else\\\
617 player.yvel = math.max(player.yvel, -player.maxVelocity)\\\
618 end\\\
619\\\
620 if player.y > killY then\\\
621 player.x = 40\\\
622 player.y = -80\\\
623 player.xvel = 0\\\
624 end\\\
625\\\
626 movePlayer(player, xvel, yvel)\\\
627\\\
628 scrollX = player.x - math.floor(scr_x / 2) + math.floor(player.xsize / 2)\\\
629 scrollY = player.y - math.floor(scr_y / 2) + math.floor(player.ysize / 2)\\\
630\\\
631 -- projectile management\\\
632\\\
633 for i = #projectiles, 1, -1 do\\\
634 projectiles[i].x = projectiles[i].x + projectiles[i].xvel\\\
635 projectiles[i].y = projectiles[i].y + projectiles[i].yvel\\\
636 projectiles[i].cycle = projectiles[i].cycle + 1\\\
637 projectiles[i].life = projectiles[i].life - 1\\\
638 if projectiles[i].life <= 0 then\\\
639 table.remove(projectiles, i)\\\
640 player.shots = player.shots - 1\\\
641 end\\\
642 end\\\
643\\\
644 end\\\
645end\\\
646\\\
647local render = function()\\\
648 tsv(false)\\\
649 term.clear()\\\
650 nfte.drawImage(maps[mapname], -scrollX + 1, -scrollY + 1)\\\
651 for num,player in pairs(players) do\\\
652 term.setCursorPos(1,num)\\\
653 print(\\\"(\\\" .. player.x .. \\\", \\\" .. player.y .. \\\", \\\" .. tostring(player.shots) .. \\\")\\\")\\\
654 if player.direction == -1 then\\\
655 nfte.drawImageTransparent(\\\
656 nfte.colorSwap(\\\
657 nfte.flipX(\\\
658 sprites[player.spriteset][player.sprite]\\\
659 ),\\\
660 player.chargeDiscolor[player.chargeLevel][\\\
661 (math.floor(player.cycle.shootCharge / 2) % #player.chargeDiscolor[player.chargeLevel]) + 1\\\
662 ]\\\
663 ),\\\
664 player.x - scrollX + player.xadj,\\\
665 player.y - scrollY + player.yadj\\\
666 )\\\
667 else\\\
668 nfte.drawImageTransparent(\\\
669 nfte.colorSwap(\\\
670 sprites[player.spriteset][player.sprite],\\\
671 player.chargeDiscolor[player.chargeLevel][\\\
672 (math.floor(player.cycle.shootCharge / 2) % #player.chargeDiscolor[player.chargeLevel]) + 1\\\
673 ]\\\
674 ),\\\
675 player.x - scrollX,\\\
676 player.y - scrollY\\\
677 )\\\
678 end\\\
679 end\\\
680 for num,p in pairs(projectiles) do\\\
681 if p.direction == -1 then\\\
682 nfte.drawImageTransparent(\\\
683 nfte.flipX(p.bullet.sprites[(p.cycle % #p.bullet.sprites) + 1]),\\\
684 p.x - scrollX,\\\
685 p.y - scrollY\\\
686 )\\\
687 else\\\
688 nfte.drawImageTransparent(\\\
689 p.bullet.sprites[(p.cycle % #p.bullet.sprites) + 1],\\\
690 p.x - scrollX,\\\
691 p.y - scrollY\\\
692 )\\\
693 end\\\
694 end\\\
695 tsv(true)\\\
696end\\\
697\\\
698-- determines what sprite a player uses\\\
699local determineSprite = function(player)\\\
700 local output\\\
701 player.xadj = 0\\\
702 player.yadj = 0\\\
703 if player.grounded then\\\
704 if player.cycle.slide > 0 then\\\
705 player.cycle.slide = math.max(player.cycle.slide - 1, isPlayerTouchingSolid(player, 0, 0, 0) and 1 or 0)\\\
706 output = \\\"slide\\\"\\\
707 else\\\
708 if player.xvel == 0 then\\\
709 player.cycle.run = -1\\\
710 player.cycle.stand = (player.cycle.stand + 1) % 40\\\
711 if player.cycle.shoot > 0 then\\\
712 output = \\\"shoot\\\"\\\
713 if player.direction == -1 then\\\
714 player.xadj = -5\\\
715 end\\\
716 else\\\
717 output = player.cycle.stand == 39 and \\\"stand2\\\" or \\\"stand1\\\"\\\
718 end\\\
719 else\\\
720 if player.cycle.run == -1 and player.cycle.shoot == 0 then\\\
721 player.cycle.run = 0\\\
722 output = \\\"walk0\\\"\\\
723 else\\\
724 player.cycle.run = (player.cycle.run + 0.35) % 4\\\
725 if player.cycle.shoot > 0 then\\\
726 output = \\\"walkshoot\\\" .. (math.floor(player.cycle.run) + 1)\\\
727 else\\\
728 output = \\\"walk\\\" .. (math.floor(player.cycle.run) + 1)\\\
729 end\\\
730 end\\\
731 end\\\
732 end\\\
733 else\\\
734 player.cycle.slide = isPlayerTouchingSolid(player, 0, 0, 0) and 1 or 0\\\
735 if player.cycle.shoot > 0 then\\\
736 output = \\\"jumpshoot\\\"\\\
737 if player.direction == -1 then\\\
738 player.xadj = -1\\\
739 end\\\
740 else\\\
741 output = \\\"jump\\\"\\\
742 end\\\
743 end\\\
744 player.cycle.shoot = math.max(player.cycle.shoot - 1, 0)\\\
745 return output\\\
746end\\\
747\\\
748local getInput = function()\\\
749 local evt\\\
750 while true do\\\
751 evt = {os.pullEvent()}\\\
752 if evt[1] == \\\"key\\\" then\\\
753 keysDown[evt[2]] = true\\\
754 elseif evt[1] == \\\"key_up\\\" then\\\
755 keysDown[evt[2]] = false\\\
756 end\\\
757 end\\\
758end\\\
759\\\
760local main = function()\\\
761 while true do\\\
762 players[you].control = deriveControls(keysDown)\\\
763 moveTick()\\\
764 players[you].sprite = determineSprite(players[you])\\\
765 render()\\\
766 if keysDown[keys.q] then\\\
767 return\\\
768 end\\\
769 sleep(0.05)\\\
770 end\\\
771end\\\
772\\\
773parallel.waitForAny(getInput, main)\\\
774\\\
775term.setCursorPos(1, scr_y)\\\
776term.clearLine()\\\
777\",\
778 [ \".game/sprites/megaman/jumpthrow.nft\" ] = \"bf bff3\\\
779bbf3bb03ffb
\\\
780 fbbff30b0ff03fbfb\\\
781 3f0f3f3bbf\\\
782 33\\\
783 3bb3b3\\\
784 33f bfbf\\\
785 bf fb\\\
786 bfb\\\
787 fb\",\
788 [ \".game/sprites/megaman/climb1.nft\" ] = \" bffb\\\
789 bf3fbbf\\\
790 bfb3b3bf\\\
791bff3bb3fb3\\\
7923b3fbf3\\\
79333fb33f\\\
794f3bfbf3\\\
795fb3 fbb\\\
796fbb\\\
797fb\",\
798 [ \".game/sprites/megaman/walkshoot4.nft\" ] = \" bff3\\\
799 3fbb03ffb
\\\
800 3ff30b0ff03fbf3\\\
801 f3bf3ff03b\\\
802 fbbf3f3\\\
803 fb3ff3
\\\
804 bfbf\\\
805 fb\",\
806 [ \".game/sprites/megaman/slide.nft\" ] = \"\\\
807 bf3f3bffb\\\
808 3fbbff3bbf
\\\
809 f30b0fb03f\\\
810 3ff303f3bffb\\\
811 bbf33fb3fb\\\
812bf f3b3bfbbf\\\
813b fb\",\
814 [ \".game/api/nfte\" ] = \"local tchar, bchar = string.char(31), string.char(30)\\\
815\\\
816local deepCopy = function(tbl)\\\
817 local output = {}\\\
818 for k,v in pairs(tbl) do\\\
819 output[k] = v\\\
820 end\\\
821 return output\\\
822end\\\
823\\\
824local function stringWrite(str,pos,ins,exc)\\\
825 str, ins = tostring(str), tostring(ins)\\\
826 local output, fn1, fn2 = str:sub(1,pos-1)..ins..str:sub(pos+#ins)\\\
827 if exc then\\\
828 repeat\\\
829 fn1, fn2 = str:find(exc,fn2 and fn2+1 or 1)\\\
830 if fn1 then\\\
831 output = stringWrite(output,fn1,str:sub(fn1,fn2))\\\
832 end\\\
833 until not fn1\\\
834 end\\\
835 return output\\\
836end\\\
837\\\
838local checkValid = function(image)\\\
839 if type(image) == \\\"table\\\" then\\\
840 if #image == 3 then\\\
841 if #image[1] + #image[2] + #image[3] >= 3 then\\\
842 return (#image[1] == #image[2] and #image[2] == #image[3])\\\
843 end\\\
844 end\\\
845 end\\\
846 return false\\\
847end\\\
848local bl = {\\\
849 [' '] = 0,\\\
850 ['0'] = 1,\\\
851 ['1'] = 2,\\\
852 ['2'] = 4,\\\
853 ['3'] = 8,\\\
854 ['4'] = 16,\\\
855 ['5'] = 32,\\\
856 ['6'] = 64,\\\
857 ['7'] = 128,\\\
858 ['8'] = 256,\\\
859 ['9'] = 512,\\\
860 ['a'] = 1024,\\\
861 ['b'] = 2048,\\\
862 ['c'] = 4096,\\\
863 ['d'] = 8192,\\\
864 ['e'] = 16384,\\\
865 ['f'] = 32768,\\\
866}\\\
867local lb = {}\\\
868for k,v in pairs(bl) do\\\
869 lb[v] = k\\\
870end\\\
871\\\
872local ldchart = { --it stands for light/dark chart\\\
873 [\\\"0\\\"] = \\\"0\\\",\\\
874 [\\\"1\\\"] = \\\"4\\\",\\\
875 [\\\"2\\\"] = \\\"6\\\",\\\
876 [\\\"3\\\"] = \\\"0\\\",\\\
877 [\\\"4\\\"] = \\\"0\\\",\\\
878 [\\\"5\\\"] = \\\"0\\\",\\\
879 [\\\"6\\\"] = \\\"0\\\",\\\
880 [\\\"7\\\"] = \\\"8\\\",\\\
881 [\\\"8\\\"] = \\\"0\\\",\\\
882 [\\\"9\\\"] = \\\"3\\\",\\\
883 [\\\"a\\\"] = \\\"2\\\",\\\
884 [\\\"b\\\"] = \\\"9\\\",\\\
885 [\\\"c\\\"] = \\\"1\\\",\\\
886 [\\\"d\\\"] = \\\"5\\\",\\\
887 [\\\"e\\\"] = \\\"2\\\",\\\
888 [\\\"f\\\"] = \\\"7\\\"\\\
889}\\\
890\\\
891local getSizeNFP = function(image)\\\
892 local xsize = 0\\\
893 if type(image) ~= \\\"table\\\" then return 0,0 end\\\
894 for y = 1, #image do xsize = math.max(xsize,#image[y]) end\\\
895 return xsize, #image\\\
896end\\\
897\\\
898getSize = function(image)\\\
899 assert(checkValid(image), \\\"Invalid image.\\\")\\\
900 local x, y = 0, #image[1]\\\
901 for y = 1, #image[1] do\\\
902 x = math.max(x, #image[1][y])\\\
903 end\\\
904 return x, y\\\
905end\\\
906\\\
907crop = function(image, x1, y1, x2, y2)\\\
908 assert(checkValid(image), \\\"Invalid image.\\\")\\\
909 local output = {{},{},{}}\\\
910 for y = y1, y2 do\\\
911 output[1][#output[1]+1] = image[1][y]:sub(x1,x2)\\\
912 output[2][#output[2]+1] = image[2][y]:sub(x1,x2)\\\
913 output[3][#output[3]+1] = image[3][y]:sub(x1,x2)\\\
914 end\\\
915 return output\\\
916end\\\
917\\\
918loadImageData = function(image, background) --string image\\\
919 local output = {{},{},{}} --char, text, back\\\
920 local y = 1\\\
921 local text, back = \\\" \\\", background or \\\" \\\"\\\
922 local doSkip, c1, c2 = false\\\
923 local maxX = 0\\\
924 for i = 1, #image do\\\
925 if doSkip then\\\
926 doSkip = false\\\
927 else\\\
928 output[1][y] = output[1][y] or \\\"\\\"\\\
929 output[2][y] = output[2][y] or \\\"\\\"\\\
930 output[3][y] = output[3][y] or \\\"\\\"\\\
931 c1, c2 = image:sub(i,i), image:sub(i+1,i+1)\\\
932 if c1 == tchar then\\\
933 text = c2\\\
934 doSkip = true\\\
935 elseif c1 == bchar then\\\
936 back = c2\\\
937 doSkip = true\\\
938 elseif c1 == \\\"\\\\n\\\" then\\\
939 maxX = math.max(maxX, #output[1][y] + 1)\\\
940 y = y + 1\\\
941 text, back = \\\" \\\", background or \\\" \\\"\\\
942 else\\\
943 output[1][y] = output[1][y]..c1\\\
944 output[2][y] = output[2][y]..text\\\
945 output[3][y] = output[3][y]..back\\\
946 end\\\
947 end\\\
948 end\\\
949 for y = 1, #output[1] do\\\
950 output[1][y] = output[1][y] .. (\\\" \\\"):rep(maxX - #output[1][y])\\\
951 output[2][y] = output[2][y] .. (\\\" \\\"):rep(maxX - #output[2][y])\\\
952 output[3][y] = output[3][y] .. (\\\" \\\"):rep(maxX - #output[3][y])\\\
953 end\\\
954 return output\\\
955end\\\
956\\\
957convertFromNFP = function(image)\\\
958 local output = {{},{},{}}\\\
959 local imageX, imageY = getSizeNFP(image)\\\
960 for y = 1, imageY do\\\
961 output[1][y] = \\\"\\\"\\\
962 output[2][y] = \\\"\\\"\\\
963 output[3][y] = \\\"\\\"\\\
964 for x = 1, imageX do\\\
965 output[1][y] = output[1][y]..lb[image[y][x] or \\\" \\\"]\\\
966 output[2][y] = output[2][y]..lb[image[y][x] or \\\" \\\"]\\\
967 output[3][y] = output[3][y]..lb[image[y][x] or \\\" \\\"]\\\
968 end\\\
969 end\\\
970 return output\\\
971end\\\
972\\\
973loadImage = function(path, background)\\\
974 local file = fs.open(path,\\\"r\\\")\\\
975 local output = loadImageData(file.readAll(), background)\\\
976 file.close()\\\
977 return output\\\
978end\\\
979\\\
980unloadImage = function(image)\\\
981 assert(checkValid(image), \\\"Invalid image.\\\")\\\
982 local output = \\\"\\\"\\\
983 local text, back = \\\" \\\", \\\" \\\"\\\
984 local c, t, b\\\
985 for y = 1, #image[1] do\\\
986 for x = 1, #image[1][y] do\\\
987 c, t, b = image[1][y]:sub(x,x), image[2][y]:sub(x,x), image[3][y]:sub(x,x)\\\
988 if (t ~= text) or (x + y == 2) then output = output..tchar..t end\\\
989 if (b ~= back) or (x + y == 2) then output = output..bchar..b end\\\
990 output = output..c\\\
991 end\\\
992 if y ~= #image[1] then\\\
993 output = output..\\\"\\\\n\\\"\\\
994 text, back = \\\" \\\", \\\" \\\"\\\
995 end\\\
996 end\\\
997 return output\\\
998end\\\
999\\\
1000drawImage = function(image, x, y)\\\
1001 assert(checkValid(image), \\\"Invalid image.\\\")\\\
1002 local cx, cy = term.getCursorPos()\\\
1003 for iy = 1, #image[1] do\\\
1004 term.setCursorPos(x,y+(iy-1))\\\
1005 term.blit(image[1][iy], image[2][iy], image[3][iy])\\\
1006 end\\\
1007 term.setCursorPos(cx,cy)\\\
1008end\\\
1009\\\
1010drawImageTransparent = function(image, x, y)\\\
1011 assert(checkValid(image), \\\"Invalid image. (\\\" .. textutils.serialize(image) .. \\\")\\\")\\\
1012 local cx, cy = term.getCursorPos()\\\
1013 local c, t, b\\\
1014 for iy = 1, #image[1] do\\\
1015 for ix = 1, #image[1][iy] do\\\
1016 c, t, b = image[1][iy]:sub(ix,ix), image[2][iy]:sub(ix,ix), image[3][iy]:sub(ix,ix)\\\
1017 if not (b == \\\" \\\" and c == \\\" \\\") then\\\
1018 term.setCursorPos(x+(ix-1),y+(iy-1))\\\
1019 term.blit(c, t, b)\\\
1020 end\\\
1021 end\\\
1022 end\\\
1023 term.setCursorPos(cx,cy)\\\
1024end\\\
1025\\\
1026drawImageCenter = function(image, x, y)\\\
1027 local scr_x, scr_y = term.getSize()\\\
1028 local imageX, imageY = getSize(image)\\\
1029 return drawImage(image, (x and x or (scr_x/2)) - (imageX/2), (y and y or (scr_y/2)) - (imageY/2))\\\
1030end\\\
1031\\\
1032drawImageCenterTransparent = function(image, x, y)\\\
1033 local scr_x, scr_y = term.getSize()\\\
1034 local imageX, imageY = getSize(image)\\\
1035 return drawImageTransparent(image, (x and x or (scr_x/2)) - (imageX/2), (y and y or (scr_y/2)) - (imageY/2))\\\
1036end\\\
1037\\\
1038colorSwap = function(image, tbl)\\\
1039 local output = {{},{},{}}\\\
1040 for y = 1, #image[1] do\\\
1041 output[1][y] = image[1][y]\\\
1042 output[2][y] = image[2][y]:gsub(\\\".\\\", tbl)\\\
1043 output[3][y] = image[3][y]:gsub(\\\".\\\", tbl)\\\
1044 end\\\
1045 return output\\\
1046end\\\
1047\\\
1048local xflippable = {\\\
1049 [\\\"\\\\129\\\"] = \\\"\\\\130\\\",\\\
1050 [\\\"\\\\131\\\"] = \\\"\\\\131\\\",\\\
1051 [\\\"\\\\132\\\"] = \\\"\\\\136\\\",\\\
1052 [\\\"\\\\133\\\"] = \\\"\\\\138\\\",\\\
1053 [\\\"\\\\134\\\"] = \\\"\\\\137\\\",\\\
1054 [\\\"\\\\135\\\"] = \\\"\\\\139\\\",\\\
1055 [\\\"\\\\140\\\"] = \\\"\\\\140\\\",\\\
1056 [\\\"\\\\141\\\"] = \\\"\\\\142\\\",\\\
1057 [\\\"\\\\143\\\"] = \\\"\\\\143\\\",\\\
1058}\\\
1059local xinvertable = {\\\
1060 [\\\"\\\\144\\\"] = \\\"\\\\159\\\",\\\
1061 [\\\"\\\\145\\\"] = \\\"\\\\157\\\",\\\
1062 [\\\"\\\\146\\\"] = \\\"\\\\158\\\",\\\
1063 [\\\"\\\\147\\\"] = \\\"\\\\156\\\",\\\
1064 [\\\"\\\\148\\\"] = \\\"\\\\151\\\",\\\
1065 [\\\"\\\\152\\\"] = \\\"\\\\155\\\"\\\
1066}\\\
1067for k,v in pairs(xflippable) do\\\
1068 xflippable[v] = k\\\
1069end\\\
1070for k,v in pairs(xinvertable) do\\\
1071 xinvertable[v] = k\\\
1072end\\\
1073\\\
1074flipX = function(image)\\\
1075 assert(checkValid(image), \\\"Invalid image.\\\")\\\
1076 local output = {{},{},{}}\\\
1077 for y = 1, #image[1] do\\\
1078 output[1][y] = image[1][y]:reverse():gsub(\\\".\\\", xflippable):gsub(\\\".\\\", xinvertable)\\\
1079 output[2][y] = \\\"\\\"\\\
1080 output[3][y] = \\\"\\\"\\\
1081 for x = 1, #image[1][y] do\\\
1082 if (not xflippable[image[1][y]:sub(x,x)]) or xinvertable[image[1][y]:sub(x,x)] then\\\
1083 output[2][y] = image[3][y]:sub(x,x) .. output[2][y]\\\
1084 output[3][y] = image[2][y]:sub(x,x) .. output[3][y]\\\
1085 else\\\
1086 output[2][y] = image[2][y]:sub(x,x) .. output[2][y]\\\
1087 output[3][y] = image[3][y]:sub(x,x) .. output[3][y]\\\
1088 end\\\
1089 end\\\
1090 end\\\
1091 return output\\\
1092end\\\
1093\\\
1094flipY = function(image)\\\
1095 assert(checkValid(image), \\\"Invalid image.\\\")\\\
1096 local output = {{},{},{}}\\\
1097 for y = #image[1], 1, -1 do\\\
1098 output[1][#output[1]+1] = image[1][y]\\\
1099 output[2][#output[2]+1] = image[2][y]\\\
1100 output[3][#output[3]+1] = image[3][y]\\\
1101 end\\\
1102 return output\\\
1103end\\\
1104\\\
1105grayOut = function(image)\\\
1106 assert(checkValid(image), \\\"Invalid image.\\\")\\\
1107 local output = {{},{},{}}\\\
1108 local chart = {\\\
1109 [\\\"0\\\"] = \\\"0\\\",\\\
1110 [\\\"1\\\"] = \\\"8\\\",\\\
1111 [\\\"2\\\"] = \\\"8\\\",\\\
1112 [\\\"3\\\"] = \\\"8\\\",\\\
1113 [\\\"4\\\"] = \\\"8\\\",\\\
1114 [\\\"5\\\"] = \\\"8\\\",\\\
1115 [\\\"6\\\"] = \\\"8\\\",\\\
1116 [\\\"7\\\"] = \\\"7\\\",\\\
1117 [\\\"8\\\"] = \\\"8\\\",\\\
1118 [\\\"9\\\"] = \\\"7\\\",\\\
1119 [\\\"a\\\"] = \\\"7\\\",\\\
1120 [\\\"b\\\"] = \\\"7\\\",\\\
1121 [\\\"c\\\"] = \\\"7\\\",\\\
1122 [\\\"d\\\"] = \\\"7\\\",\\\
1123 [\\\"e\\\"] = \\\"7\\\",\\\
1124 [\\\"f\\\"] = \\\"f\\\"\\\
1125 }\\\
1126 for k,v in pairs(chart) do\\\
1127 for y = 1, #image[1] do\\\
1128 output[1][y] = image[1][y]:gsub(k,v)\\\
1129 output[2][y] = image[2][y]:gsub(k,v)\\\
1130 output[3][y] = image[3][y]:gsub(k,v)\\\
1131 end\\\
1132 end\\\
1133 return output\\\
1134end\\\
1135\\\
1136greyOut = grayOut\\\
1137\\\
1138lighten = function(image)\\\
1139 assert(checkValid(image), \\\"Invalid image.\\\")\\\
1140 local output = {{},{},{}}\\\
1141 for k,v in pairs(ldchart) do\\\
1142 for y = 1, #image[1] do\\\
1143 output[1][y] = image[1][y]:gsub(k,v)\\\
1144 output[2][y] = image[2][y]:gsub(k,v)\\\
1145 output[3][y] = image[3][y]:gsub(k,v)\\\
1146 end\\\
1147 end\\\
1148 return output\\\
1149end\\\
1150\\\
1151darken = function(image)\\\
1152 assert(checkValid(image), \\\"Invalid image.\\\")\\\
1153 local output = {{},{},{}}\\\
1154 for k,v in pairs(ldchart) do\\\
1155 for y = 1, #image[1] do\\\
1156 output[1][y] = image[1][y]:gsub(v,k)\\\
1157 output[2][y] = image[2][y]:gsub(v,k)\\\
1158 output[3][y] = image[3][y]:gsub(v,k)\\\
1159 end\\\
1160 end\\\
1161 return output\\\
1162end\\\
1163\\\
1164stretchImage = function(_image, sx, sy, noRepeat)\\\
1165 assert(checkValid(_image), \\\"Invalid image.\\\")\\\
1166 local output = {{},{},{}}\\\
1167 local image = deepCopy(_image)\\\
1168 if sx < 0 then image = flipX(image) end\\\
1169 if sy < 0 then image = flipY(image) end\\\
1170 sx, sy = math.abs(sx), math.abs(sy)\\\
1171 local imageX, imageY = getSize(image)\\\
1172 local tx, ty\\\
1173 for y = 1, sy do\\\
1174 for x = 1, sx do\\\
1175 tx = math.ceil((x / sx) * imageX)\\\
1176 ty = math.ceil((y / sy) * imageY)\\\
1177 if not noRepeat then\\\
1178 output[1][y] = (output[1][y] or \\\"\\\")..image[1][ty]:sub(tx,tx)\\\
1179 else\\\
1180 output[1][y] = (output[1][y] or \\\"\\\")..\\\" \\\"\\\
1181 end\\\
1182 output[2][y] = (output[2][y] or \\\"\\\")..image[2][ty]:sub(tx,tx)\\\
1183 output[3][y] = (output[3][y] or \\\"\\\")..image[3][ty]:sub(tx,tx)\\\
1184 end\\\
1185 end\\\
1186 if noRepeat then\\\
1187 for y = 1, imageY do\\\
1188 for x = 1, imageX do\\\
1189 if image[1][y]:sub(x,x) ~= \\\" \\\" then\\\
1190 tx = math.ceil(((x / imageX) * sx) - ((0.5 / imageX) * sx))\\\
1191 ty = math.ceil(((y / imageY) * sy) - ((0.5 / imageY) * sx))\\\
1192 output[1][ty] = stringWrite(output[1][ty], tx, image[1][y]:sub(x,x))\\\
1193 end\\\
1194 end\\\
1195 end\\\
1196 end\\\
1197 return output\\\
1198end\\\
1199\\\
1200pixelateImage = function(image,amntX, amntY)\\\
1201 assert(checkValid(image), \\\"Invalid image.\\\")\\\
1202 local imageX, imageY = getSize(image)\\\
1203 return stretchImage(stretchImage(image,imageX/math.max(amntX,1), imageY/math.max(amntY,1)), imageX, imageY)\\\
1204end\\\
1205\\\
1206merge = function(...)\\\
1207 local images = {...}\\\
1208 local output = {{},{},{}}\\\
1209 local imageX, imageY = 0, 0\\\
1210 for i = 1, #images do\\\
1211 imageY = math.max(imageY, #images[i][1][1]+(images[i][3]-1))\\\
1212 for y = 1, #images[i][1][1] do\\\
1213 imageX = math.max(imageX, #images[i][1][1][y]+(images[i][2]-1))\\\
1214 end\\\
1215 end\\\
1216 \\\
1217 --will later add code to adjust X/Y positions if negative values are given\\\
1218 \\\
1219 local image, xadj, yadj\\\
1220 local tx, ty\\\
1221 for y = 1, imageY do\\\
1222 output[1][y] = {}\\\
1223 output[2][y] = {}\\\
1224 output[3][y] = {}\\\
1225 for x = 1, imageX do\\\
1226 for i = 1, #images do\\\
1227 image, xadj, yadj = images[i][1], images[i][2], images[i][3]\\\
1228 tx, ty = x-(xadj-1), y-(yadj-1)\\\
1229 output[1][y][x] = output[1][y][x] or \\\" \\\"\\\
1230 output[2][y][x] = output[2][y][x] or \\\" \\\"\\\
1231 output[3][y][x] = output[3][y][x] or \\\" \\\"\\\
1232 if image[1][ty] then\\\
1233 if (image[1][ty]:sub(tx,tx) ~= \\\"\\\") and (tx >= 1) then\\\
1234 output[1][y][x] = (image[1][ty]:sub(tx,tx) == \\\" \\\" and output[1][y][x] or image[1][ty]:sub(tx,tx))\\\
1235 output[2][y][x] = (image[2][ty]:sub(tx,tx) == \\\" \\\" and output[2][y][x] or image[2][ty]:sub(tx,tx))\\\
1236 output[3][y][x] = (image[3][ty]:sub(tx,tx) == \\\" \\\" and output[3][y][x] or image[3][ty]:sub(tx,tx))\\\
1237 end\\\
1238 end\\\
1239 end\\\
1240 end\\\
1241 output[1][y] = table.concat(output[1][y])\\\
1242 output[2][y] = table.concat(output[2][y])\\\
1243 output[3][y] = table.concat(output[3][y])\\\
1244 end\\\
1245 return output\\\
1246end\\\
1247\\\
1248rotateImage = function(image, angle)\\\
1249 local output = {{},{},{}}\\\
1250 local realOutput = {{},{},{}}\\\
1251 local tx, ty\\\
1252 local imageX, imageY = getSize(image)\\\
1253 local originX, originY = imageX / 2, imageY / 2\\\
1254 local adjX, adjY = 1, 1\\\
1255 for y = 1, #image[1] do\\\
1256 for x = 1, #image[1][y] do\\\
1257 if not (image[1][y]:sub(x,x) == \\\" \\\" and image[2][y]:sub(x,x) == \\\" \\\" and image[3][y]:sub(x,x) == \\\" \\\") then\\\
1258 tx = math.floor( (x-originX) * math.cos(angle) - (originY-y) * math.sin(angle) )\\\
1259 ty = math.floor( (x-originX) * math.sin(angle) + (originY-y) * math.cos(angle) )\\\
1260 adjX, adjY = math.min(adjX, tx), math.min(adjY, ty)\\\
1261 output[1][ty] = output[1][ty] or {}\\\
1262 output[2][ty] = output[2][ty] or {}\\\
1263 output[3][ty] = output[3][ty] or {}\\\
1264 output[1][ty][tx] = image[1][y]:sub(x,x)\\\
1265 output[2][ty][tx] = image[2][y]:sub(x,x)\\\
1266 output[3][ty][tx] = image[3][y]:sub(x,x)\\\
1267 end\\\
1268 end\\\
1269 end\\\
1270 for y = adjY, #output[1] do\\\
1271 realOutput[1][y+1-adjY] = {}\\\
1272 realOutput[2][y+1-adjY] = {}\\\
1273 realOutput[3][y+1-adjY] = {}\\\
1274 for x = adjX, #output[1][y] do\\\
1275 realOutput[1][y+1-adjY][x+1-adjX] = output[1][y][x] or \\\" \\\"\\\
1276 realOutput[2][y+1-adjY][x+1-adjX] = output[2][y][x] or \\\" \\\"\\\
1277 realOutput[3][y+1-adjY][x+1-adjX] = output[3][y][x] or \\\" \\\"\\\
1278 end\\\
1279 end\\\
1280 for y = 1, #realOutput[1] do\\\
1281 realOutput[1][y] = table.concat(realOutput[1][y])\\\
1282 realOutput[2][y] = table.concat(realOutput[2][y])\\\
1283 realOutput[3][y] = table.concat(realOutput[3][y])\\\
1284 end\\\
1285 return realOutput, math.ceil(adjX-1+originX), math.ceil(adjY-1+originY)\\\
1286end\\\
1287\\\
1288help = function(input)\\\
1289 local helpOut = {\\\
1290 loadImageData = \\\"Loads an NFT image from a string input.\\\",\\\
1291 loadImage = \\\"Loads an NFT image from a file path.\\\",\\\
1292 convertFromNFP = \\\"Loads a table NFP image into a table NFT image, same as what loadImage outputs.\\\",\\\
1293 drawImage = \\\"Draws an image. Does not support transparency, sadly.\\\",\\\
1294 drawImageTransparent = \\\"Draws an image. Supports transparency, but not as fast as drawImage.\\\",\\\
1295 drawImageCenter = \\\"Draws an image centered around the inputted coordinates. Does not support transparency, sadly.\\\",\\\
1296 drawImageCenterTransparent = \\\"Draws an image centered around the inputted coordinates. Supports transparency, but not as fast as drawImageCenter.\\\",\\\
1297 flipX = \\\"Returns the inputted image, but with the X inverted.\\\",\\\
1298 flipY = \\\"Returns the inputted image, but with the Y inverted.\\\",\\\
1299 grayOut = \\\"Returns the inputted image, but with the colors converted into grayscale as best I could.\\\",\\\
1300 lighten = \\\"Returns the inputted image, but with the colors lightened.\\\",\\\
1301 darken = \\\"Returns the inputted image, but with the colors darkened.\\\",\\\
1302 stretchImage = \\\"Returns the inputted image, but it's been stretched to the inputted size. If the fourth argument is true, it will spread non-space characters evenly in the image.\\\",\\\
1303 pixelateImage = \\\"Returns the inputted image, but pixelated to a variable degree.\\\",\\\
1304 merge = \\\"Merges two or more images together.\\\",\\\
1305 crop = \\\"Crops an image between points (X1,Y1) and (X2,Y2).\\\",\\\
1306 rotateImage = \\\"Rotates an image, and also returns how much the image center's X and Y had been adjusted.\\\",\\\
1307 colorSwap = \\\"Swaps the colors of a given image with another color, according to an inputted table.\\\"\\\
1308 }\\\
1309 return helpOut[input] or \\\"No such function.\\\"\\\
1310end\",\
1311 [ \".game/sprites/megaman/walkshoot2.nft\" ] = \" bff3\\\
1312 3fbb03ffb
\\\
1313 3ff30b0ff03fbf3\\\
1314 f3bf3ff03b\\\
1315 fbbf3f3\\\
1316 fb3ff3
\\\
1317 bfbf\\\
1318 fb\",\
1319 [ \".game/sprites/megaman/walkshoot1.nft\" ] = \" 3ff3\\\
1320 bfbf3\\\
1321 bf3f3b0bb0fbbf\\\
1322bfbf
3ffb0f03ff3b3f\\\
1323bfb33ff03b\\\
1324bffbbf3b\\\
1325b3bf3fb
\\\
1326 fb\",\
1327 [ \".game/sprites/megaman/stand2.nft\" ] = \" bff3\\\
1328 3fbb03ffb
\\\
1329 f30bff0\\\
1330 bf33ff00f3fb\\\
1331bff33fbfb\\\
1332b3fb3b3bffb\\\
1333 bfb3fbffb\\\
1334b fb\",\
1335 [ \".game/sprites/megaman/walk3.nft\" ] = \" 3ff3\\\
1336 bfbf3\\\
1337 b30bb0fbbf\\\
1338 bf33f03f0\\\
1339 fb
bff33bb3ffb\\\
1340bfbf3bb3f3fb\\\
1341b3 f3bfb\\\
1342 fb\",\
1343 [ \".game/sprites/megaman/buster3-1.nft\" ] = \" 0f40f4\\\
1344 4f
0f004ff0\\\
1345 4f004f\\\
1346400f4\\\
1347 04400f\\\
1348 f4004ff04\\\
1349 f04\",\
1350 [ \".game/sprites/megaman/buster2-2.nft\" ] = \"\\\
13514f004f\\\
135240404f4
\",\
1353 },\
1354}")
1355if fs.isReadOnly(outputPath) then
1356 error("Output path is read-only. Abort.")
1357elseif fs.getFreeSpace(outputPath) <= #archive then
1358 error("Insufficient space. Abort.")
1359end
1360
1361if fs.exists(outputPath) and fs.combine("", outputPath) ~= "" then
1362 print("File/folder already exists! Overwrite?")
1363 stc(colors.lightGray)
1364 print("(Use -o when making the extractor to always overwrite.)")
1365 stc(colors.white)
1366 if choice() ~= 1 then
1367 error("Chose not to overwrite. Abort.")
1368 else
1369 fs.delete(outputPath)
1370 end
1371end
1372if selfDelete or (fs.combine("", outputPath) == shell.getRunningProgram()) then
1373 fs.delete(shell.getRunningProgram())
1374end
1375for name, contents in pairs(archive.data) do
1376 stc(colors.lightGray)
1377 write("'" .. name .. "'...")
1378 if contents == true then -- indicates empty directory
1379 fs.makeDir(fs.combine(outputPath, name))
1380 else
1381 file = fs.open(fs.combine(outputPath, name), "w")
1382 if file then
1383 file.write(contents)
1384 file.close()
1385 end
1386 end
1387 if file then
1388 stc(colors.green)
1389 print("good")
1390 else
1391 stc(colors.red)
1392 print("fail")
1393 end
1394end
1395stc(colors.white)
1396write("Unpacked to '")
1397stc(colors.yellow)
1398write(outputPath .. "/")
1399stc(colors.white)
1400print("'.")
1401
1402sleep(0.25)
1403
1404shell.run("/gametest/game.lua")
1405