require 'config' require 'button' -- Menu state class ---@class MenuState ---@field buttons Button[] MenuState = { buttons = {} } -- Factory function ---@param buttons Button[] | nil ---@return MenuState function MenuState:new( buttons ) local state = { buttons = buttons or MenuState.buttons } setmetatable( state, { __index = self } ) return state end -- Draw buttons function MenuState:draw() for _, button in ipairs(self.buttons) do button:draw() end end -- Update buttons ---@param dt number ---@param point Point ---@param pressed boolean function MenuState:update( dt, point, pressed ) for _, button in pairs(self.buttons) do button:update( dt, point, pressed ) end end ---@enum MenuStateIndex MenuStateIndex = { start = 'start', pause = 'pause', levels = 'levels', hidden = 'hidden', completed = 'completed' } local buttonTopPos = Point:new( 240, 120 ) local buttonBotPos = Point:new( 240, 240 ) local buttonSize = Point:new( 320, 80 ) local startButton = Button:new( buttonTopPos, buttonSize, 'Start', nil, nil, function() Menu.current_state = MenuStateIndex.hidden GameGrid = LevelHandler:first() Menu.updateCellSize() end ) local exitToMenuButton = Button:new( buttonBotPos, buttonSize, 'Return to menu', nil, nil, function() Menu.current_state = MenuStateIndex.start end ) local exitGameButton = Button:new( buttonBotPos, buttonSize, 'Exit', nil, nil, function() love.event.quit() end ) local nextLevelButton = Button:new( buttonTopPos, buttonSize, 'Next level', nil, nil, function() GameGrid = LevelHandler:next() Menu.updateCellSize() Menu.current_state = MenuStateIndex.hidden end ) local backToGameButton = Button:new( buttonTopPos, buttonSize, 'Continue', nil, nil, function() Menu.current_state = MenuStateIndex.hidden end ) -- Menu handler ---@class Menu ---@field states MenuState[] ---@field current_state MenuStateIndex Menu = { states = { -- Main menu [MenuStateIndex.start] = MenuState:new({ startButton, exitGameButton }), -- Pause menu [MenuStateIndex.pause] = MenuState:new({ backToGameButton, exitToMenuButton }), -- Level selector [MenuStateIndex.levels] = MenuState:new({ }), -- Level completed menu [MenuStateIndex.completed] = MenuState:new({ nextLevelButton, exitToMenuButton }), -- Empty state [MenuStateIndex.hidden] = MenuState:new() }, current_state = MenuStateIndex.start } -- Draw current state function Menu:draw() self.states[self.current_state]:draw() end -- Update current state ---@param dt number ---@param point Point ---@param pressed boolean function Menu:update( dt, point, pressed ) self.states[self.current_state]:update( dt, point, pressed ) end function Menu.updateCellSize() local width, height = love.graphics.getDimensions() local gridX, gridY = GameGrid.size:coords(); local isWidthBased = (width / height) / (gridX / gridY) Config.cellSize = math.floor(isWidthBased and height / gridY or width / gridX) love.graphics.setLineWidth( Config.cellSize * Config.lineWidth ) end