From d7dcda1adaf004a25a0037433f1737d27c376b41 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Wed, 22 Oct 2025 13:45:09 +0300 Subject: [PATCH] added menu handler --- config.lua | 2 + main.lua | 50 +++++++++++----------- menu.lua | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 150 insertions(+), 25 deletions(-) create mode 100644 menu.lua diff --git a/config.lua b/config.lua index 67698c8..7ea90d2 100644 --- a/config.lua +++ b/config.lua @@ -7,6 +7,7 @@ require 'tablefuncs' ---@field cellSize number Size of each grid cell ---@field lineStyle string love2d line style setting ---@field lineWidth number love2d line width setting +---@field menuLineWidth number love2d line width for buttons ---@field dragSensivity number drag sensivity, px Config = { pointRadius = 0.3, @@ -17,6 +18,7 @@ Config = { lineStyle = "smooth", lineWidth = 0.1, + menuLineWidth = 4, dragSensivity = 5 } diff --git a/main.lua b/main.lua index 3c03696..2c0533b 100644 --- a/main.lua +++ b/main.lua @@ -4,56 +4,56 @@ require 'line' require 'mouse' require 'levelhandler' require 'button' +require 'menu' + Input = require 'input' -InMenu = true - -local function 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 function love.load() love.window.setMode( 800, 480 ) - local menuButtonReleased = function() - InMenu = false - GameGrid = LevelHandler:first() - updateCellSize() - end - - MenuStartButton = Button:new( Point:new( 240, 120 ), Point:new( 320, 80 ), nil, nil, menuButtonReleased ) - + InMenu = true love.graphics.setLineStyle( Config.lineStyle ) end function love.update( dt ) + InMenu = Menu.current_state ~= MenuStateIndex.hidden Mouse:update() Input:update() - if InMenu then - MenuStartButton:update( dt, Point:new( Mouse.x, Mouse.y ), Mouse.pressed ) - else - if Input:actionReleased( 'exit' ) then - love.event.quit() - end + local exit = Input:actionReleased( 'exit' ) + + if InMenu then + Menu:update( dt, Point:new( Mouse.x, Mouse.y ), Mouse.pressed ) + else if Input:actionReleased( 'nextlevel' ) then if GameGrid:isCompleted() then GameGrid = LevelHandler:next() - updateCellSize() + Menu.updateCellSize() end end end + -- Switch menu state or exit + if exit then + if not InMenu then + Menu.current_state = MenuStateIndex.pause + elseif Menu.current_state == MenuStateIndex.start then + love.event.quit() + elseif Menu.current_state == MenuStateIndex.pause then + Menu.current_state = MenuStateIndex.hidden + elseif Menu.current_state == MenuStateIndex.levels then + Menu.current_state = MenuStateIndex.start + end + end end function love.draw() if InMenu then - MenuStartButton:draw() + love.graphics.setLineWidth( Config.menuLineWidth ) + Menu:draw() else + love.graphics.setLineWidth( Config.cellSize * Config.lineWidth ) GameGrid:draw() local text = string.format( "%d:%d global\n%d:%d local\n%d:%d from start", Mouse.x, Mouse.y, Mouse.point.x, Mouse.point.y, Mouse.startX - Mouse.x, Mouse.startY - Mouse.y ) diff --git a/menu.lua b/menu.lua new file mode 100644 index 0000000..db77c1a --- /dev/null +++ b/menu.lua @@ -0,0 +1,123 @@ +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' +} + +local startButton = Button:new( + Point:new( 240, 120 ), + Point:new( 320, 80 ), + nil, + nil, + function() + Menu.current_state = MenuStateIndex.hidden + GameGrid = LevelHandler:first() + Menu.updateCellSize() + end +) + +local exitToMenuButton = Button:new( + Point:new( 240, 200 ), + Point:new( 320, 80 ), + nil, + nil, + function() + Menu.current_state = MenuStateIndex.start + end +) + +local exitGameButton = Button:new( + Point:new( 240, 240 ), + Point:new( 320, 80 ), + nil, + nil, + function() + love.event.quit() + 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({ + exitToMenuButton + }), + -- Level selector + [MenuStateIndex.levels] = MenuState:new({ + }), + -- 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