local Footer = require('components.footer'); local cursorIndex = 3; local buttonHeight = 128 + 16; local SELECTOR_BAR_OFFSET_FROM_CENTER = 128; local buttons = nil local resx, resy = game.GetResolution() local desw = 1080 local desh = 1920 local scale; local bgImage = gfx.CreateSkinImage('titlescreen/bg.png', 0); local selectorBgImage = gfx.CreateSkinImage('titlescreen/selector_bg.png', 0); local selectorArrowsImage = gfx.CreateSkinImage('titlescreen/selector_arrows.png', 0); local unselectedButtonImage = gfx.CreateSkinImage('titlescreen/unselected_button.png', 0); local selectedButtonBgImage = gfx.CreateSkinImage('titlescreen/selected_button_bg.png', 0); local selectedButtonOverImage = gfx.CreateSkinImage('titlescreen/selected_button_over.png', 0); local skillLabelImage = gfx.CreateSkinImage('titlescreen/labels/skill.png', 0); local friendLabelImage = gfx.CreateSkinImage('titlescreen/labels/friend.png', 0); local normalLabelImage = gfx.CreateSkinImage('titlescreen/labels/normal.png', 0); local nauticaLabelImage = gfx.CreateSkinImage('titlescreen/labels/nautica.png', 0); local settingsLabelImage = gfx.CreateSkinImage('titlescreen/labels/settings.png', 0); local exitLabelImage = gfx.CreateSkinImage('titlescreen/labels/exit.png', 0); -- ANIMS local idolAnimation = gfx.LoadSkinAnimation('idol', 1/30, 0, true); -- AUDIO game.LoadSkinSample('titlescreen/bgm.wav'); game.LoadSkinSample('titlescreen/cursor_change.wav'); game.LoadSkinSample('titlescreen/cursor_select.wav'); local selectorDescriptionLabel = gfx.CreateLabel('Test description. Blah blah blah', 22, 0); local selectorLegendScrollLabel = gfx.CreateLabel('Scroll', 20, 0); local selectorLegendSelectLabel = gfx.CreateLabel('START', 20, 0); local scrollTransitionScale = 1; -- Goes from 0 to 1 when transition is happening, sits at 1 when it's not. local buttonsMovementScale = 0; -- Basically same as `scrollTransitionScale` but with a +/- sign for the scroll direction and goes from 1 to 0 local idolAnimTransitionScale = 0; local oldCursorIndex = 3; local scrollingUp = false; local playedBgm = false; function resetLayoutInformation() resx, resy = game.GetResolution() desw = 1080 desh = 1920 scale = resx / desw end draw_button = function(button, x, y, selected, index) local labelImage = button[1]; local labelWidth = button[2]; local descriptionText = button[4]; if (selected) then -- Draw button background gfx.BeginPath(); gfx.ImageRect(x, y+(196/2 * (1-scrollTransitionScale)), 505, 196*scrollTransitionScale, selectedButtonBgImage, 1, 0); -- Draw button main label gfx.BeginPath(); gfx.ImageRect(x + 256 - (labelWidth/2), (y+58)+(64/2 * (1-scrollTransitionScale)), labelWidth, 64*scrollTransitionScale, labelImage, 1, 0); -- Draw description gfx.GlobalAlpha((scrollTransitionScale - 0.8) * 5) gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE) gfx.FontSize(40); gfx.BeginPath(); gfx.Text(descriptionText, x+256, y+28); gfx.GlobalAlpha(1) -- Draw the glow overlay gfx.BeginPath(); gfx.ImageRect(x+2, (y-42)+(277/2 * (1-scrollTransitionScale)), 501, 277*scrollTransitionScale, selectedButtonOverImage, 1, 0); else if scrollingUp then if (index == 3 or index == 0) then gfx.GlobalAlpha(1-scrollTransitionScale); end if (index == 2 or index == 5) then gfx.GlobalAlpha(scrollTransitionScale); end else if (index == 3 or index == 6) then gfx.GlobalAlpha(1-scrollTransitionScale); end if (index == 1 or index == 4) then gfx.GlobalAlpha(scrollTransitionScale); end end -- Draw button background gfx.BeginPath(); gfx.ImageRect(x, y + buttonsMovementScale*buttonHeight, 1026 / 2, 257 / 2, unselectedButtonImage, 1, 0); -- Draw button main label gfx.BeginPath(); gfx.ImageRect(x+64, y+28 + buttonsMovementScale*buttonHeight, labelWidth, 64, labelImage, 1, 0); -- Draw description gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) gfx.FontSize(28); gfx.BeginPath(); gfx.Text(descriptionText, x+64, y+18 + buttonsMovementScale*buttonHeight); gfx.GlobalAlpha(1) end; end; draw_buttons = function() indexes = { getCorrectedButtonIndex(cursorIndex, -2), getCorrectedButtonIndex(cursorIndex, -1), cursorIndex, getCorrectedButtonIndex(cursorIndex, 1), getCorrectedButtonIndex(cursorIndex, 2), } local yBase = desh/2 + SELECTOR_BAR_OFFSET_FROM_CENTER; centerButtonY = yBase - buttonHeight/2 - 28; -- to fit with the selector bg marginFromDesHCenter = 128; if scrollingUp then draw_button(buttons[indexes[5]], desw - 512, yBase - marginFromDesHCenter - buttonHeight*3, false, 0); -- Placeholder for fadeout transition end draw_button(buttons[indexes[1]], desw - 512, yBase - marginFromDesHCenter - buttonHeight*2, false, 1); draw_button(buttons[indexes[2]], desw - 512, yBase - marginFromDesHCenter- buttonHeight, false, 2); draw_button(buttons[indexes[3]], desw - 512, centerButtonY, true); -- The main selected center button if scrollingUp then draw_button(buttons[indexes[3]], desw - 512, yBase + marginFromDesHCenter - buttonHeight, false, 3); -- Placeholder for transition that goes to the bottom else draw_button(buttons[indexes[3]], desw - 512, centerButtonY, false, 3); -- Placeholder for transition that goes to the top end draw_button(buttons[indexes[4]], desw - 512, yBase + marginFromDesHCenter + 10, false, 4); draw_button(buttons[indexes[5]], desw - 512, yBase + marginFromDesHCenter + buttonHeight + 10, false, 5); if not scrollingUp then draw_button(buttons[indexes[1]], desw - 512, yBase + marginFromDesHCenter + buttonHeight*2, false, 6); end end; function getCorrectedButtonIndex(from, offset) buttonsNum = #buttons; index = from + offset; if index < 1 then index = buttonsNum + (from+offset) -- this only happens if the offset is negative end; if index > buttonsNum then indexesUntilEnd = buttonsNum - from; index = offset - indexesUntilEnd -- this only happens if the offset is positive end; return index; end; function drawTexts() currentFullDescriptionText = buttons[cursorIndex][5]; gfx.BeginPath(); gfx.UpdateLabel(selectorDescriptionLabel, currentFullDescriptionText, 22) gfx.BeginPath(); gfx.UpdateLabel(selectorLegendScrollLabel, 'DEBUG: ' .. buttonsMovementScale, 20); -- descriptionAlpha = math.abs(selectedButtonScaleY - 0.5) * 2; gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE); -- Description gfx.FillColor(255,255,255,math.floor(scrollTransitionScale*255)); gfx.BeginPath(); gfx.DrawLabel(selectorDescriptionLabel, 64, desh/2 + SELECTOR_BAR_OFFSET_FROM_CENTER - 52); -- Legend on the selector gfx.FillColor(217,177,126); gfx.BeginPath(); gfx.DrawLabel(selectorLegendScrollLabel, 118, desh/2 + SELECTOR_BAR_OFFSET_FROM_CENTER + 56); gfx.BeginPath(); gfx.DrawLabel(selectorLegendSelectLabel, 360, desh/2 + SELECTOR_BAR_OFFSET_FROM_CENTER + 56); gfx.FillColor(255,255,255); end; function setButtons() if buttons == nil then buttons = {} buttons[1] = {skillLabelImage, 412, Menu.Challenges, "Idk", "Torture yourself :)"} buttons[2] = {friendLabelImage, 169, Menu.Multiplayer, "Wait, there's multiplayer???", "Yes, but nobody is ever online"} buttons[3] = {normalLabelImage, 210, Menu.Start, "Play shit idk", "Play something blah blah blah blah\nWith newlines"} buttons[4] = {nauticaLabelImage, 230, Menu.DLScreen, "Download more songs", "ksm.dev"} buttons[5] = {settingsLabelImage, 247, Menu.Settings, "Adjust things", "Open settings"} buttons[6] = {exitLabelImage, 110, Menu.Exit, "Leave this cursed game", "C'mon press that button!\nYou know you want to do it"} end end function sign(x) return x>0 and 1 or x<0 and -1 or 0 end function roundToZero(x) if x<0 then return math.ceil(x) elseif x>0 then return math.floor(x) else return 0 end end function deltaKnob(delta) if math.abs(delta) > 1.5 * math.pi then return delta + 2 * math.pi * sign(delta) * -1 end return delta end local lastKnobs = nil local knobProgress = 0 function handle_controller() if lastKnobs == nil then lastKnobs = {game.GetKnob(0), game.GetKnob(1)} else local newKnobs = {game.GetKnob(0), game.GetKnob(1)} knobProgress = knobProgress - deltaKnob(lastKnobs[1] - newKnobs[1]) * 1.2 knobProgress = knobProgress - deltaKnob(lastKnobs[2] - newKnobs[2]) * 1.2 lastKnobs = newKnobs if math.abs(knobProgress) > 1 then cursorIndex = (((cursorIndex - 1) + roundToZero(knobProgress)) % #buttons) + 1 scrollTransitionScale = 0; -- Reset transitions and play them scrollingUp = false; if ((cursorIndex > oldCursorIndex and not (cursorIndex == 6 and oldCursorIndex == 1)) or (cursorIndex == 1 and oldCursorIndex == 6)) then scrollingUp = true; end; game.PlaySample('titlescreen/cursor_change.wav'); oldCursorIndex = cursorIndex; knobProgress = knobProgress - roundToZero(knobProgress) end end end render = function(deltaTime) if not playedBgm then game.PlaySample('titlescreen/bgm.wav', true); playedBgm = true; end resetLayoutInformation(); gfx.Scale(scale, scale); -- Draw background gfx.BeginPath(); gfx.ImageRect(0, 0, desw, desh, bgImage, 1, 0); local idolAnimTickRes = gfx.TickAnimation(idolAnimation, deltaTime); if idolAnimTickRes == 1 then gfx.GlobalAlpha(idolAnimTransitionScale); idolAnimTransitionScale = idolAnimTransitionScale + 1/60; if (idolAnimTransitionScale > 1) then idolAnimTransitionScale = 1; end gfx.BeginPath(); gfx.ImageRect(0, 0, desw, desh, idolAnimation, 1, 0); gfx.GlobalAlpha(1); end -- Draw selector background gfx.BeginPath(); gfx.ImageRect(0, (desh/2 + SELECTOR_BAR_OFFSET_FROM_CENTER) - 280/2, 1079, 280, selectorBgImage, 1, 0); setButtons() buttonY = (desh / 2) - 2 * (257 + 5); draw_buttons(); drawTexts(); -- Draw the arrows around the selected button gfx.BeginPath(); gfx.ImageRect(desw-512, desh/2 + SELECTOR_BAR_OFFSET_FROM_CENTER - buttonHeight - 8, 501, 300, selectorArrowsImage, 1, 0); -- Draw top and bottom bars --Bars.draw(); handle_controller() scrollTransitionScale = scrollTransitionScale + 1/60 * 5; if (scrollTransitionScale > 1) then scrollTransitionScale = 1; end if scrollingUp then buttonsMovementScale = 1-scrollTransitionScale else buttonsMovementScale = -1+scrollTransitionScale end; gfx.BeginPath(); end; mouse_pressed = function(button) return 0 end function button_pressed(button) if button == game.BUTTON_STA then game.PlaySample('titlescreen/cursor_select.wav'); game.StopSample('titlescreen/bgm.wav'); buttons[cursorIndex][3]() elseif button == game.BUTTON_BCK then Menu.Exit() end end -- the thing is... titlescreen script does not have a call to reset function... WHYYYYY function reset() playedBgm = false; end