w  """""" """  ""     """""""""   """"""    """"  `ffpwgv`v``ffpww ! !  DD@33@0D3C@@D403""""ffDDffDD -0"33 033D3O4  ````ffff``````ffff     ""DD..DD """""""" """""" /     着 ffffffff`ffffff`o`````DDDDDDDD@DDDDDD@O@@@@@ """"""""./"///""" ////.着 ffffffffnofooofff`oooonDDDDDDDDNODOOODDD@OOOON >k?ff DDww @33` @v! 0D` 3Cv ! @ff @D4ww 03 -0"DD 33 .. 033.. D3DD O4NO OO O  O O N .// / / / / ."/","" ̪Ϫ Ϫݯ nofffn}-- title: ADOFAI Demake -- author: SirWobb79 (@admiralerkal79 via discord) -- desc: ADOFAI demake in TIC-80 -- license: MIT License -- version: wip-1-6.0 -- script: lua -- MAPS -- --[[ When making your own, it is not reccomended to use BPMs over what is said; autoplay can't handle things that fast. The special variable has the gameplay modifiers 1 = Speed up 2 = Speed down 3 = Reverse rotation 4 = Checkpoint ]] maps = { { "Custom Map", 120, 2, "r", "0" }, { "Test", 120, 2, "rrrruldrrrrrluudrrrdrrduuuulllrrrrrr", "000000000000000000000000000000000000" }, { "Example Track", 60, 2, "rrruldrrrrdlurrrrdrruullddrrruuullllurrrrrdrrrrrrrruldrrrrrrrrrrrrrrrluuuurdlluuu", "0000000000000004000000000000000000300003000004010000000001020002004" }, { "1-1 | Walk Cycle", 120, 2, "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "0" }, { "1-2 | The Stairwell", 120, 2, "rrrrrrrrururururururrrrdrdrdrdrdrdrrrr", "0" }, { "1-3 | Hairpins!", 120, 2, "rrrrrrrulllllurrrrrulllllurrrrrrr", "0" }, { "1-4 | I'm Feeling Loopy", 120, 2, "rrrrrrrruldrrrrruldrrrrruldrrrrrrrrdlurrrrrdlurrrrrdlurrrrrrrr", "0" }, { "1-5 | Chained Loops", 120, 2, "rrruuldrruuldrruuldrruuldrrrrulddrrulddrrulddrrulddrrrr", "0" }, { "1-6 | Large Loops Are Like A Spiral", 120, 2, "rrrulddrruuulllddddrrrruuuuuullllllldddddddrrrrrrrruuuuuullllllldddddddrrrrrr", "0" }, { "1-7 | Squares of Many Sizes", 135, 2, "rrrrrruuuuullllldddddrrrruuuullllddddrrruuullldddrruullddruldrrrrrrr", "0" }, { "1-8 | Stringy Mess", 135, 2, "rruuuldrrruulddrrruldddrrruldddrrulldddrullldddrulllddruullldruuulll", "0" }, { "1-9 | Seven-Point Turns", 135, 2, "rrrruldrullllurdlurrrruldrullllurdlurrrrr", "000000000003000000003000000003000000003" }, { "1-Finale | The Rollercoaster Ride", 150, 2, "rrruulllldruulldruulldruulldruuuldrruuldrruuldrruuldrruuldrrrulddrrulddrrulddrrulddrruldddddddrruulllddrruuuulldrrruuldrruuldrruuldrrruuulldruullldruullldruullldruullllldrrruulllldrulldddrulllldruldrruuullldddddruldddddruldddruldddrulddrrrulddrrrulddrrrrrrrrrrrrruldrrruldrrruldruuuldruuuldrullldrullldruldddruldddrrrrrrrrulldrrruulddrrruulddrrrulldrrrrrruldrrruldruuuldruuuldrullldrullldruldddruldddruldrrrrrrrrruuuldrrruldddrrruuuldrrruldddrrruuuldrrruldddrrruuuldrrruldddrrullllllllllllllllldrrrrrrrrrrrrrrrrrrr", "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004" }, { "2-1 | My_Circuit.tic", 135, 2, "rrruuldrruurrdrrddllddllddrrruuullllllllurr", "0" }, { "2-2 | My_Circuit (1).tic", 135, 2, "rrruuldrruurrdrrddllddllddrrruuullllllllurr", "0000000000300000000300000000000000100002" }, { "2-3 | After Round Two, Take The Exit", 135, 2, "rrrruldddrullldruuuldrrruldddrullldruuuldrrrrr", "0" }, { "2-4 | Garden Hedge Maze", 135, 2, "rrrruulldruuulldrrrrrrdluurrrdluuuldruurrdldrdddlldlllddrrulddrruruurruuuuuulurrddddddddlldddllllllluullll", "0" }, { "2-Finale | Through The Old Town", 150, 2, -- current = 438 "rrrrrrrrrrrrrrrrrrrrruldddlurrrrrruldddrruldddrrrrrrrrruuuuuuuuullllluuuuurrrrrrrrdddddrrrrrrrrrrrrrrrruldrrrrrrruuulldruuuldruuuuuuuuuuurdlluurrrdddlllluuuurrrrrrrrrrrrrrrrrrrrrrrruuullddrrrruuuullldddrrrrruuuuullllddddrrrrrruuuuuullllldddddrrrrrrrruldddlurrrrrrrrrruldddlurrrrrrrrrrrrrrrrulurulurrrrrdldrdldrrrrruurddrurdrrruururdrruurdddruurddruuuurddruurddddrurdruuurddddrrrrruldrruuuldruuuldrulllldruuuuldlulllllllldlddlululddluuuluuurrrrrrrrrrrrrrrrrrrrrrruuullldddrrruuullldddrrrrrruullddrruullddrrrruldruldrrruldruldrrrruullddrruullddrrrrrruuullldddrrruuullldddrrrrruuuullllllllllllllllllllldddllllllluurruullllddddllllluuuuurrrrrrdddddddrrrruuuuuuulllullllllllldllldllldddddddddddddddddddddddddddddddrruulldddlluurrdrruulldddlluurrdrrrrrrrrrruulluurrrdddddlluurrrdddlllllluurrrruulluurrrdddddlluurrrdddlllllluurrrrrrrrrrrruldddlllurddruuuuurrrrrulddrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrruldrruldrruldrrrrrrr", "000000000000000000000000000000000000000000000000000000000000000000300000000030000000000000000000000000000000040000000000000000000000030000000000000000000003001000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000010000020000000000100000000000200030303000000030303004000000000000000300000000000000000000340000000000000000000000000000000000003000000300000000000000000000000400000300000000030000001000000000000000000020000000000000000000000000000000000000000000004000000000000000000040000000000000000000000000000000000000000000000000000100000000000000000200000000003000300000000000000000000000400000000000000000000000000000000000000000010000000000000000000000000002400000000000000000000000000000000000000000000000000000430000000000000000000000000000000000030000000000000040000000000000000000000000000000000000000000010000000000000000000000000000000000000002" }, { "3-1 | Triplets", 125, 3, "rrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "00000000100200000001002" }, { "3-2 | Flattened Square", 125, 2, --File > New > Don't Save Changes "rrrruldrrrrrrrrrrrrrrrrrrrrrrrrrrrrr", "00000000000010002000000010002" }, { "3-3 | Hidden Modifications", 125, 2, "rrrruldrrrruldrrrrr", "0000000030000003" }, { "3-4 | Rhythm Keeper", 125, 2, "rrrruldrrrruldrrrrruldrrruldrrruuuldruuuldrrrr", "00002000100200010002000102000102102000102001" }, { "3-5 | Do it again, but faster", 150, 2, "rrrruldrrrruldrrrrruldrrruldrrruuuldruuuldrrrr", "00002000100200010002000102000102102000102001" }, { "3-6 | Dead End, Go Back", 130, 2, "rrruldrrruuullldrulllrrrdlurrrdddlllurdllll", "0" }, { "3-7 | Nope, Not This Path", 130, 2, "rrrrruuuldduullluuddlllddrullluudruuu", "0" }, { "3-8 | Three Step Right, One Step Left", 140, 2, "rrrlrrrlrrrlrrrr", "0" }, { "3-9 | \"Four\" Loop", 140, 2, "rrruldruldruldruldrrrr", "0" }, { "3-10 | The Spine", 150, 2, "rrudrdurudrdurudrdurudrdurudrdurudrdurrr", "0" }, { "3-11 | A Ladder to Heaven", 150, 2, "rrrullurrullurruldrullurrullurdlurrullurruldrullurrullurdlurrullurruldrullurrullurdlurrullurrrr", "00000300300300300000030030030000003003003000000300300300000030030030000003003003000000300300300" }, { "3-Finale | The Maze", 150, 2, "rrrrrruldluuurdlluldruuuldrrurdluuudrrulrulllllddrruulllllllluluuuuuurururrrrrruldrrruldddrullldrullddddddrulludldulurlurrulrulldlldddruuuuuuuuuurdruullllruuldrrruuldrrurddddrrulrulrulrulrullllllldruullldddddrullddrullldruuuulddruruuuuuururrrruldddrullluulldlllurdddlurrddllluuuuuuurrdluulurdlurrrrdrdrudruuulduldullddddruldrrrrrrrrdluuruldlluuurrddlurrrrudruulldullullduludlduludlduludlduludlduludlddrullluuurrrullurrullurruldrullurrullurdlurrullurruldrullurrullurdlurrullurruldrullurrullurdlurrullurrrrrrrrrrruldrrrrulllllllddrrrrrrrrrudrudrudrrrrr", "00000000030000000300000000000000000000000000000000000000000000001000200000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000040000000030030030030000003003003000000300300300000030030030000003003003000000300300300000030030030401000000000000000000000000000002" }, { "4-1 | Suns & Pillars", 150, 2, "rrrrrruuuuuuldrruullldddrrrrddddrrrruuuuuuldrruullldddrrrrddddrrrruuuuuuldrruullldddrrrrddddrrrr", "0" }, { "4-2 | Waves of Water", 150, 2, "rrrrrrrrrullulluluururrrullllldldlddddrrrrrrrrrdrrr", "0" }, { "ADOFAI Original - B-X", 150, 2, "rrrrrdrrrrrdrrrrrdrrrrrdrrrrrurrurrurrurruuldddrrrrrrrrrrrrrrrrrrrrrrrrrrrulllllllurrrrrrrrrruuldrrrrdldrrrdldrrrdldrrrdldrrrdldrrrdldrrrdldrrruuldrrrruurrrruurrrruurrrruurrrruuuldrrruuuldrrruuuldrrrdrdrdrrrrrrrrrrdrrrrrrrrrrrdrrdrrdrrdrrdrruuruuruuruuruuruurr", "0000000000000000000000000000000000000000000000000041" }, { "idk what this is lol", 150, 2, "rrrrrrrrrruuuuuuulldrulllddddruuulddrrruldddllluldrulllllddrruuldrruullllddddddddrrruullddrdrruullddrdrruullddrdrruullddrrrrr", "0" }, -- --[[{ "4-1 | Roulette", 130, 6, "rrrrrrr", "0001200" }, { "4-2 | You are speed", 175, 2, "rrrrrrrrrrruldrrrrruuurdluuuuldrruulll", "03" }, --[[{ "test | up up and awayyyyy", 13.5, 6, "ruuuuu", "0" },]] } -- ERROR L:128: 'LEVEL3_9' IS TYPE 'NULL' map_choice = 4--18--#maps -- Usually 4 acc_text = { "Perfect!", "Great!", "Good", "eh.", "ouch..." } function get_direction(offset) local o = offset or 0 local tile = chart:sub(tile+o, tile+o) if tile == "l" then return 0 end if tile == "u" then return 90 end if tile == "r" then return 180 end if tile == "d" then return 270 end end function get_next_angle() local on = chart:sub(tile, tile) local next = chart:sub(tile+1, tile+1) if (on == "r" and next == "r" or on == "u" and next == "u" or on == "l" and next == "l" or on == "d" and next == "d") then return 180 end if (on == "r" and next == "l" or on == "u" and next == "d" or on == "l" and next == "r" or on == "d" and next == "u") then return 360 end if math.abs(speed) == speed and (on == "r" and next == "u" or on == "u" and next == "l" or on == "l" and next == "d" or on == "d" and next == "r") then return 90 end if math.abs(speed) ~= speed and (on == "r" and next == "d" or on == "u" and next == "r" or on == "l" and next == "u" or on == "d" and next == "l") then return 90 end if math.abs(speed) == speed and (on == "r" and next == "d" or on == "u" and next == "r" or on == "l" and next == "u" or on == "d" and next == "l") then return 270 end if math.abs(speed) ~= speed and (on == "r" and next == "u" or on == "u" and next == "l" or on == "l" and next == "d" or on == "d" and next == "r") then return 270 end end function get_now_angle() local on = chart:sub(tile-1, tile-1) local next = chart:sub(tile, tile) if tile == 1 then return 180 end if (on == "r" and next == "r" or on == "u" and next == "u" or on == "l" and next == "l" or on == "d" and next == "d") then return 180 end if (on == "r" and next == "l" or on == "u" and next == "d" or on == "l" and next == "r" or on == "d" and next == "u") then return 360 end if math.abs(speed) == speed and (on == "r" and next == "u" or on == "u" and next == "l" or on == "l" and next == "d" or on == "d" and next == "r") then return 90 end if math.abs(speed) ~= speed and (on == "r" and next == "d" or on == "u" and next == "r" or on == "l" and next == "u" or on == "d" and next == "l") then return 90 end if math.abs(speed) == speed and (on == "r" and next == "d" or on == "u" and next == "r" or on == "l" and next == "u" or on == "d" and next == "l") then return 270 end if math.abs(speed) ~= speed and (on == "r" and next == "u" or on == "u" and next == "l" or on == "l" and next == "d" or on == "d" and next == "r") then return 270 end end function set_map() name = maps[map_choice][1] chart = "r"..maps[map_choice][4] special = "0"..maps[map_choice][5] while #special < #chart do special = special.."0" end end set_map() edit = "" stats = "" c = {x = 0, y = 0} -- Camera (not ball C) ticks = 0 function set_speeds() bpm = maps[map_choice][2] speed_mult = maps[map_choice][3] -- What to multiply/divide speed by (EDITABLE) end function init() a = {x = 0, y = 0} -- Ball A b = {x = 0, y = 0} -- Ball B next = {x = 0, y = 0} get_next = true easing = 15 rot = 0 tile = 1 speed = (bpm/10)/2 -- BPM math radius = 8 percent = 0 best = 0 offset = 0 bpm_max = 500 prev_accuracy = 0 -- Last click's accuracy accuracy = 0 -- In degrees, ideally 0 checkpoint = {} spawn = 0 big = 45 small = 20 window = big -- How many degrees(*2) the window is special_on = false prev = {} active = false auto_click = false clicks = {current = 0, prev = 0} degrees = 0 -- Degrees since last click ball = true -- First ball stationary? calculate_next() end function check4beat() --trace(tostring(tile == #chart-1)) if percent >= 100 and map_choice ~= #maps and map_choice ~= 1 then map_choice = map_choice + 1 set_speeds() init() add_checkpoint() --if ball then table.insert(prev, {round8(a.x), round8(a.y)}) --[[else table.insert(prev, {round8(b.x), round8(b.y)}) end]] set_map() end end function round(num) local decimals = num - math.floor(num) if decimals >= 0.5 then return math.floor(num) else return math.ceil(num) end end --[[function round_3dp(num) local result = "" local decimals = 3 local x end]] function round8(num) local mod = num % 8 local nearest_low = math.floor(num) --trace(mod) while nearest_low % 8 ~= 0 do nearest_low = nearest_low - 1 end if mod >= 5 then return nearest_low+8 else return nearest_low end end function round90(num) local mod = num % 90 local nearest_low = math.floor(num) --trace(mod) while nearest_low % 90 ~= 0 do nearest_low = nearest_low - 1 end if mod >= 45 then return nearest_low+90 else return nearest_low end end function calculate_next() local next_tile = chart:sub(tile+1, tile+1) if next_tile == "r" then next.x = next.x - 8 end if next_tile == "l" then next.x = next.x + 8 end if next_tile == "u" then next.y = next.y + 8 end if next_tile == "d" then next.y = next.y - 8 end end function calculate_now() local now_tile = chart:sub(tile, tile) --if ball then if now_tile == "r" then a.x = a.x - 8 end if now_tile == "l" then a.x = a.x + 8 end if now_tile == "u" then a.y = a.y + 8 end if now_tile == "d" then a.y = a.y - 8 end --[[else if now_tile == "r" then b.x = b.x - 8 end if now_tile == "l" then b.x = b.x + 8 end if now_tile == "u" then b.y = b.y + 8 end if now_tile == "d" then b.y = b.y - 8 end end]] end function add_checkpoint() local current_x, current_y --if ball then current_x = round(a.x) current_y = round(a.y) --[[else current_x = b.x current_y = b.y end]] table.insert(checkpoint, { current_x, current_y, ball, rot, tile, speed, radius, next.x, next.y, } ) spawn = #checkpoint end set_speeds() init() add_checkpoint() function refresh() ball = checkpoint[spawn][3] --if ball then a = {x = checkpoint[spawn][1], y = checkpoint[spawn][2]} --[[else b = {x = checkpoint[spawn][1], y = checkpoint[spawn][2]} end]] rot = checkpoint[spawn][4] tile = checkpoint[spawn][5] speed = checkpoint[spawn][6] radius = checkpoint[spawn][7] next.x = checkpoint[spawn][8] next.y = checkpoint[spawn][9] prev = {} --calculate_next() --if ball then table.insert(prev, {round8(a.x), round8(a.y)}) --[[else table.insert(prev, {round8(b.x), round8(b.y)}) end]] --calculate_next() end --if ball then table.insert(prev, {round8(a.x), round8(a.y)}) --[[else table.insert(prev, {round8(b.x), round8(b.y)}) end]] function display_icon(icon, x, y) rect(x-1, y-1, 10, 10, 0) if icon == "z" then spr(261, x, y, 0) elseif icon == "x" then spr(262, x, y, 0) elseif icon == "a" then spr(263, x, y, 0) elseif icon == "s" then spr(264, x, y, 0) elseif icon == "tiles" then spr(265, x, y, 0) elseif icon == "pencil" then spr(266, x, y, 0) elseif icon == "cog" then spr(267, x, y, 0) elseif icon == "bin" then spr(268, x, y, 0) elseif icon == "auto" and active then spr(269, x, y, 0) elseif icon == "auto" and not active then spr(270, x, y, 0) elseif icon == "left" then spr(277, x, y, 0) elseif icon == "right" then spr(278, x, y, 0) elseif icon == "up" then spr(279, x, y, 0) elseif icon == "down" then spr(280, x, y, 0) elseif icon == "play" then spr(281, x, y, 0) elseif icon == "view" then spr(282, x, y, 0) elseif icon == "checkpoint" then spr(283, x, y, 0) else spr(271, x, y) end end function draw() local x = 0 local y = 0 local current = "" --local long = false for i=2, #chart do current = chart:sub(i, i) if current == "r" then x = x + 8 end if current == "l" then x = x - 8 end if current == "u" then y = y - 8 end if current == "d" then y = y + 8 end --trace(x) end for i=#chart, 2, -1 do current = chart:sub(i, i) local next = chart:sub(i-1, i-1) current_mod = special:sub(i, i) state = 0 --trace(next) --if i == #chart then next = current end if current_mod == "1" then state = 3 end if current_mod == "2" then state = 6 end if current_mod == "3" then state = 9 end if current_mod == "4" then state = 12 end if current == "r" then x = x - 8 if next == "r" then spr(384+state+alt, c.x+x, c.y+y, 0, 1, 0, 0) elseif next == "l" then spr(386+state+alt, c.x+x, c.y+y, 0, 1, 0, 3) elseif next == "u" then spr(385+state+alt, c.x+x, c.y+y, 0, 1, 0, 2) elseif next == "d" then spr(385+state+alt, c.x+x, c.y+y, 0, 1, 0, 1) end end if current == "l" then x = x + 8 if next == "r" then spr(386+state+alt, c.x+x, c.y+y, 0, 1, 0, 1) elseif next == "l" then spr(384+state+alt, c.x+x, c.y+y, 0, 1, 0, 0) elseif next == "u" then spr(385+state+alt, c.x+x, c.y+y, 0, 1, 0, 3) elseif next == "d" then spr(385+state+alt, c.x+x, c.y+y, 0, 1, 0, 0) end end if current == "u" then y = y + 8 if next == "r" then spr(385+state+alt, c.x+x, c.y+y, 0, 1, 0, 0) elseif next == "l" then spr(385+state+alt, c.x+x, c.y+y, 0, 1, 0, 1) elseif next == "u" then spr(384+state+alt, c.x+x, c.y+y, 0, 1, 0, 1) elseif next == "d" then spr(386+state+alt, c.x+x, c.y+y, 0, 1, 0, 2) end end if current == "d" then y = y - 8 if next == "r" then spr(385+state+alt, c.x+x, c.y+y, 0, 1, 0, 3) elseif next == "l" then spr(385+state+alt, c.x+x, c.y+y, 0, 1, 0, 2) elseif next == "u" then spr(386+state+alt, c.x+x, c.y+y, 0, 1, 0, 0) elseif next == "d" then spr(384+state+alt, c.x+x, c.y+y, 0, 1, 0, 1) end end end for i=1, #prev do spr(258, -prev[i][1]+c.x, -prev[i][2]+c.y, 0) end if ball then spr(256, -a.x+c.x, -a.y+c.y, 0) spr(257, -b.x+c.x, -b.y+c.y, 0) else spr(257, -a.x+c.x, -a.y+c.y, 0) spr(256, -b.x+c.x, -b.y+c.y, 0) end --get_next_angle()-degrees --accuracy local text_x = -a.x+c.x local text_y = -a.y+24+c.y local bg = accuracy_text().shade local fg = 15 if mode == "game" then for i=-1, 1 do for j=-2, 0 do print(accuracy_text().text, text_x+i, text_y+j, bg) end end print(accuracy_text().text, text_x, text_y-1, fg) end --print(accuracy_text().text, text_x, text_y-2, accuracy_text().shade) end function add_click() clicks.current = clicks.current + 1 end --trace(round8(29)) function d2r(deg) return deg * (math.pi/180) end function r2d(rad) return rad * (180/math.pi) end --trace(round90(135)) mode = "game" selected = {x = 0, y = 0} function edit_adjust(dir) if dir == "r" then tile = tile + 1 local tile_c = chart:sub(tile, tile) local tile_s = special:sub(tile, tile) if tile_c == "r" then selected.x = selected.x + 8 end if tile_c == "l" then selected.x = selected.x - 8 end if tile_c == "u" then selected.y = selected.y - 8 end if tile_c == "d" then selected.y = selected.y + 8 end end if dir == "l" then tile = tile - 1 local tile_c = chart:sub(tile+1, tile+1) local tile_s = special:sub(tile+1, tile+1) if tile_c == "r" then selected.x = selected.x - 8 end if tile_c == "l" then selected.x = selected.x + 8 end if tile_c == "u" then selected.y = selected.y + 8 end if tile_c == "d" then selected.y = selected.y - 8 end end end function add_to_chart(dir) local c_before = "" local s_before = "" local c_after = "" local s_after = "" local index = 1 for index=1, tile do c_before = c_before..chart:sub(index, index) s_before = s_before..special:sub(index, index) end for index=tile+1, #chart do c_after = c_after..chart:sub(index, index) s_after = s_after..special:sub(index, index) end --trace(c_after) chart = c_before..dir..c_after special = s_before.."0"..s_after edit_adjust("r") --trace(#chart) end function accuracy_text() local acc = math.abs(accuracy) local result = "" local colour = 0 --[[print(accuracy, 0, 64) print(offset, 0, 64+8) print(acc, 0, 64+16)]] values1 = {20, 30, 45, 75} if acc <= values1[1] then result = acc_text[1] colour = 10 end if acc <= values1[2] and acc > values1[1] then result = acc_text[2] colour = 6 end if acc <= values1[3] and acc > values1[2] then result = acc_text[3] colour = 5 end if acc <= values1[4] and acc > values1[3] then result = acc_text[4] colour = 4 end if acc > values1[4] then result = acc_text[5] colour = 2 end return {text = result, shade = colour} end function bg() -- id, x, y, w, h, rot, parallaxMult, loop?, lvlID local objs = { {0, 0, 0, 2, 2, 0, .5, true, 0}, {2, 7639, 760, 2, 2, 0, .4, true, 0}, {0, 3543, 6367, 2, 2, 1, .6, true, 0}, {2, 23658, 542, 2, 2, 1, .55, true, 0}, {0, 64297, 864, 2, 2, 1, .7, true, 0}, {2, 6843, 7495, 2, 2, 1, .35, true, 0}, {0, 10853, 67386, 2, 2, 1, .45, true, 0}, {128, 1160, 266, 2, 2, 0, 1, false, 18}, {128, 966, 100, 2, 2, 0, 1, false, 18}, {128, 1032, 85, 2, 2, 0, 1, false, 18}, {130, 16, 24, 2, 2, 0, 1, false, 27}, } local sW = 240 local sH = 136 for i=1, #objs do local cur = objs[i] if cur[9] == map_choice or cur[9] == 0 then if cur[8] then spr( cur[1], ((cur[2]+(c.x*cur[7])+((cur[4]+1)*8))%(sW+(cur[4]+2)*8))-((cur[4]+1)*8), ((-cur[3]+(c.y*cur[7])+((cur[5]+1)*8))%(sH+(cur[5]+2)*8))-((cur[5]+1)*8)+2, 0, 1, 0, cur[6], cur[4], cur[5] ) else spr( cur[1], ((cur[2]+(c.x*cur[7]))), ((-cur[3]+(c.y*cur[7])))+2, 0, 1, 0, cur[6], cur[4], cur[5] ) end end end end edit_state = "View" temp_tile = 0 next_angle = 0 --trace(get_now_angle(), 15) alt = 0 alt_physics = false function TIC() cls() bg() draw() --rot = 90 --set_speeds() --print(speed, 32, 32) if keyp(17) then if alt == 0 then alt = 16 elseif alt == 16 then alt = 0 end end print(string.format("X=%.4f", -c.x+116), 0, 32, 12) print(string.format("Y=%.4f", c.y-68), 0, 39, 12) print(map_choice, 0, 39+7, 12) if mode == "edit" then if btnp(5) then mode = "game" init() add_checkpoint() refresh() edit = "" add = false end stats = "\nTile No."..tile.."/"..(#chart-1).." | Mode "..edit_state c.x = c.x - ((c.x+selected.x)-116)/easing c.y = c.y - ((c.y+selected.y)-68)/easing spr(259, selected.x+c.x, selected.y+c.y, 0) if edit_state == "View" then display_icon("z", 232-27, 0) display_icon("tiles", 232-27, 9) display_icon("x", 232-18, 0) display_icon("play", 232-18, 9) display_icon("a", 232-9, 0) display_icon("pencil", 232-9, 9) display_icon("s", 232, 0) display_icon("bin", 232, 9) display_icon("left", 232-9, 27) display_icon("right", 232, 27) if (btnp(3) or btn(0)) and tile < #chart-1 then edit_adjust("r") end if (btnp(2) or btn(1)) and tile > 1 then edit_adjust("l") end elseif edit_state == "Add" then display_icon("z", 232-27, 0) display_icon("tiles", 232-27, 9) display_icon("x", 232-18, 0) display_icon("play", 232-18, 9) display_icon("a", 232-9, 0) display_icon("cog", 232-9, 9) display_icon("s", 232, 0) display_icon("bin", 232, 9) spr(260, selected.x+c.x, selected.y+c.y-8, 15, 1, 0, 0) spr(260, selected.x+c.x, selected.y+c.y+8, 15, 1, 0, 2) spr(260, selected.x+c.x-8, selected.y+c.y, 15, 1, 0, 3) spr(260, selected.x+c.x+8, selected.y+c.y, 15, 1, 0, 1) if btnp(0) then add_to_chart("u") end if btnp(1) then add_to_chart("d") end if btnp(2) then add_to_chart("l") end if btnp(3) then add_to_chart("r") end elseif edit_state == "Settings" then display_icon("z", 232-27, 0) display_icon("tiles", 232-27, 9) display_icon("x", 232-18, 0) display_icon("play", 232-18, 9) display_icon("a", 232-9, 0) display_icon("view", 232-9, 9) display_icon("s", 232, 0) display_icon("bin", 232, 9) stats = stats.."\n\nBPM: "..bpm.."/"..bpm_max.." (Up/Down)\nSpeed Mult.: "..speed_mult.."/8 (Left/Right)" if btnp(0) and bpm ~= bpm_max then bpm = bpm + 1 end if btnp(1) and bpm ~= 1 then bpm = bpm - 1 end if btnp(2) and speed_mult ~= .25 then speed_mult = speed_mult - 0.25 end if btnp(3) and speed_mult ~= 8 then speed_mult = speed_mult + 0.25 end end if btnp(4) then special_on = special:sub(tile+1, tile+1) s_be = "" s_af = "" for index=1, tile do s_be = s_be..special:sub(index, index) end for index=tile+2, #chart do s_af = s_af..special:sub(index, index) end if special_on == "0" then special = s_be.."1"..s_af elseif special_on == "1" then special = s_be.."2"..s_af elseif special_on == "2" then special = s_be.."3"..s_af elseif special_on == "3" then special = s_be.."4"..s_af elseif special_on == "4" then special = s_be.."0"..s_af end --trace(#special) end if btnp(7) and #chart-1 ~= 1 then c_be = "" c_af = "" s_be = "" s_af = "" for index=1, tile do c_be = c_be..chart:sub(index, index) s_be = s_be..special:sub(index, index) end for index=tile+2, #chart do c_af = c_af..chart:sub(index, index) s_af = s_af..special:sub(index, index) end chart = c_be..c_af special = s_be..s_af if tile ~= 1 then edit_adjust("l") end --trace(#special) end if btnp(6) then if edit_state == "View" then edit_state = "Add" elseif edit_state == "Add" then edit_state = "Settings" elseif edit_state == "Settings" then edit_state = "View" end end if keyp(52) then chart = "rr" special = "00" end --print(tile, 32, 32) elseif mode == "game" then display_icon("z", 232-27, 0) display_icon("play", 232-27, 9) display_icon("x", 232-18, 0) display_icon("pencil", 232-18, 9) display_icon("a", 232-9, 0) display_icon("auto", 232-9, 9) display_icon("s", 232, 0) display_icon("checkpoint", 232, 9) if spawn ~= 1 then display_icon("left", 232-27, 27) end if spawn ~= #checkpoint then display_icon("right", 232-18, 27) end if map_choice ~= 1 then display_icon("up", 232-9, 27) end if map_choice ~= #maps then display_icon("down", 232, 27) end local current_x, current_y, other_x, other_y if ball then current_x = a.x current_y = a.y other_x = b.x other_y = b.y else current_x = b.x current_y = b.y other_x = a.x other_y = a.y end --print(current_x..","..current_y.."\n"..next.x..","..next.y, 100, 50) --print(round8(other_x)..","..round8(other_y).."\n"..get_next_angle().."\n"..degrees, 140, 32) if btnp(5) then mode = "edit" edit_state = "View" --a = {x = 0, y = 0} --b = {x = 0, y = 0} selected = {x = 0, y = 0} edit = "Editing: " temp_tile = tile tile = 1 for tile=1, temp_tile-1 do edit_adjust("r") end end percent = math.floor((tile/(#chart-1))*100) if percent > best then best = percent end --print(percent, 32, 32) stats = "\n\n"..percent.."%" --if tile == 1 then stats = stats.."\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nPB: "..best.."%" --end if percent == 100 then print("Congratulations!", 77, 64) print("Congratulations!", 75, 64) print("Congratulations!", 76, 65) print("Congratulations!", 76, 63) print("Congratulations!", 76, 64, ((ticks//5)%10)+2) end if btnp(0) and map_choice ~= 1 then map_choice = map_choice - 1 set_speeds() init() add_checkpoint() if ball then table.insert(prev, {round8(a.x), round8(a.y)}) else table.insert(prev, {round8(b.x), round8(b.y)}) end set_map() elseif btnp(1) and map_choice ~= #maps then map_choice = map_choice + 1 set_speeds() init() add_checkpoint() if ball then table.insert(prev, {round8(a.x), round8(a.y)}) else table.insert(prev, {round8(b.x), round8(b.y)}) end set_map() end --if ball then c.x = c.x - ((c.x-a.x)-116)/easing c.y = c.y - ((c.y-a.y)-68)/easing b.x = (math.cos(d2r(rot))*radius)+a.x b.y = (math.sin(d2r(rot))*radius)+a.y --a.x = round8(a.x) --a.y = round8(a.y) if a.x ~= prev[#prev][1] and a.y ~= prev[#prev][2] then --refresh() end --[[else c.x = c.x - ((c.x-b.x)-116)/easing c.y = c.y - ((c.y-b.y)-68)/easing a.x = (math.cos(d2r(rot))*radius)+b.x a.y = (math.sin(d2r(rot))*radius)+b.y --b.x = round8(b.x) --b.y = round8(b.y) if b.x ~= prev[#prev][1] and b.y ~= prev[#prev][2] then --refresh() end]] --end --trace(d2r(rot)%360) --clicked = clicked + 1 if clicks.current == clicks.prev then clicks.current, clicks.prev = 0, 0 end clicks.prev = clicks.current --[[if get_next then calculate_next() get_next = false end]] current_angle = next_angle if chart:sub(tile+1, tile+1) == "u" then next_angle = ((rot+speed)%360) end if chart:sub(tile+1, tile+1) == "r" then next_angle = math.abs((rot+speed)%360 - 180) end if chart:sub(tile+1, tile+1) == "d" then next_angle = math.abs((rot+speed)%360 - 270) end if chart:sub(tile+1, tile+1) == "l" then next_angle = math.abs((rot+speed)%360 - 360) end --print(chart:sub(tile+1, tile+1).."\n"..(rot%360).."\n"..bpm.." ("..speed..")", 32, 32) --trace(next_angle..","..current_angle..","..tostring(next_angle < current_angle)) if not auto_click and tile ~= #chart-1 then local spd = speed//math.abs(speed) local closeness = math.abs(get_now_angle()-degrees) --trace(spd) local conditions = {u = false, r = false, d = false, l = false} local leeway = 0 if spd == 1 then conditions.u = ((rot+speed)%360 >= 90-leeway and (rot+speed)%360 <= 135) conditions.r = ((rot+speed)%360 >= 180-leeway and (rot+speed)%360 <= 225) conditions.d = ((rot+speed)%360 >= 270-leeway and (rot+speed)%360 <= 315) conditions.l = ((rot+speed)%360 >= 0-leeway and (rot+speed)%360 <= 45) else conditions.u = ((rot+speed)%360 >= 45 and (rot+speed)%360 <= 90-leeway) conditions.r = ((rot+speed)%360 >= 135 and (rot+speed)%360 <= 180-leeway) conditions.d = ((rot+speed)%360 >= 225 and (rot+speed)%360 <= 270-leeway) conditions.l = ((rot+speed)%360 >= 315 or (rot+speed)%360 <= 0+leeway) end if --[[round8(other_x) == next.x and round8(other_y) == next.y and (degrees <= get_next_angle()-window and degrees >= get_next_angle()+window)]] (chart:sub(tile+1, tile+1) == "u" --and current_angle%360 >= 90-window --and current_angle%360 <= 90+window and conditions.u) or (chart:sub(tile+1, tile+1) == "r" --and current_angle%360 >= -window --and current_angle%360 <= window and conditions.r) --next_angle > current_angle)= or (chart:sub(tile+1, tile+1) == "d" --and rot%360 >= 270-window --and rot%360 <= 270+window and conditions.d) or --next_angle > current_angle) or (chart:sub(tile+1, tile+1) == "l" --and (rot%360 >= 360-window --or rot%360 <= window and conditions.l)--next_angle > current_angle)]] --and prev_accuracy <= accuracy --and closeness <= 50 then --trace("yeee") if degrees > 45 then auto_click = true --degrees = 0 --[[if active then if (chart:sub(tile+1, tile+1) == "u" and conditions.u) then rot = 90 end if (chart:sub(tile+1, tile+1) == "r" and conditions.r) then rot = 180 end if (chart:sub(tile+1, tile+1) == "d" and conditions.d) then rot = 270 end if (chart:sub(tile+1, tile+1) == "l" and conditions.l) then rot = 0 end add_click() end]] --rot = round90(rot) end --clicked = true end end --if auto_click then trace("Hit rotation = "..rot.." | Degrees per frame = "..speed) end if btnp(6) then active = not active end --print(rot, 64, 64) if not active then auto_click = false window = big else print("AUTOPLAY", 194, 130, 5) --window = small end --print(rot%360, 32, 32) --[[if ball then if not (b.x == next.x and b.y == next.y) then goto continue refresh() goto continue end ::continue:: else if not (a.x == next.x and a.y == next.y) then goto continue refresh() goto continue end ::continue:: end]] if btnp(7) then refresh() end rot = rot + speed rot = rot%360 -- just in case degrees = degrees + math.abs(speed) --print(rot.."\n"..accuracy, 32, 32) if (btnp(4) or keyp(48) or auto_click) and percent < 100 then --[[if not ( (chart:sub(tile+1, tile+1) == "u" and rot%360 >= 90-window and rot%360 <= 90+window) or (chart:sub(tile+1, tile+1) == "r" and rot%360 >= 180-window and rot%360 <= 180+window) or (chart:sub(tile+1, tile+1) == "d" and rot%360 >= 270-window and rot%360 <= 270+window) or (chart:sub(tile+1, tile+1) == "l" and (rot%360 >= 360-window or rot%360 <= window)) ) or tile == #chart-1 then --check4beat() if percent ~= 100 then refresh() end goto continue end]] --if clicks.current > 1 then goto continue end --if ball then table.insert(prev, {round8(a.x), round8(a.y)}) --[[else table.insert(prev, {round8(b.x), round8(b.y)}) end]] ball = not ball rot = rot + 180 tile = tile + 1 calculate_now() --check4beat() --trace(tile-#chart+1) special_on = false prev_accuracy = accuracy --accuracy = get_direction()-rot+180 accuracy = get_now_angle()-degrees target = get_now_angle() --trace(accuracy) offset = -accuracy if not autoplay and alt_physics then rot = rot - accuracy end -- When a hit happens: --local error = (degrees - expected_angle) % 360 -- Apply a small dampening factor so the correction is smooth --speed_adjustment = -error * 0.1 --trace(error) -- Move the 'leftover' error to the next rotation -- This makes the game naturally "tug" the ball back to the correct track --degrees = error degrees = 0 ::continue:: if accuracy_text().text == acc_text[5] then refresh() end auto_click = false --rot = round90(rot) get_next = true calculate_next() elseif (btnp(4) or keyp(48) or auto_click) and percent == 100 then check4beat() end if not special_on then on = special:sub(tile+1, tile+1) if on == "1" then speed = speed * speed_mult end if on == "2" then speed = speed / speed_mult end if on == "3" then speed = speed * -1 end if on == "4" then add_checkpoint() end special_on = true end if btnp(2) and spawn ~= 1 then spawn = spawn - 1 refresh() calculate_next() end if btnp(3) and spawn ~= #checkpoint then spawn = spawn + 1 refresh() calculate_next() end end display = edit..name..stats print(display, 1, 2, 15) print(display, 3, 2, 15) print(display, 2, 1, 15) print(display, 2, 3, 15) print(display, 2, 2, 12) --trace(next.x) -- currently nil?? --print("prev = "..prev[#prev][1]..","..prev[#prev][2].."\ncurrent tile = "..tile+(1).."\nA = "..a.x..","..a.y.."\nB = "..b.x..","..b.y, 1, 32) ticks = ticks + 1 end --[[ if get_next then calculate_next() get_next = false end ]] -- FIX NEXT!! nope. FINE!!