From 7df0478890c7b7016ffde2393c7ce217c5a97ecc Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Thu, 23 Oct 2025 14:47:00 +0300 Subject: [PATCH 1/7] more modular menu --- menu.lua | 122 ++------------------------------------------- menu/common.lua | 24 +++++++++ menu/completed.lua | 29 +++++++++++ menu/pause.lua | 27 ++++++++++ menu/start.lua | 40 +++++++++++++++ menu/state.lua | 53 ++++++++++++++++++++ 6 files changed, 178 insertions(+), 117 deletions(-) create mode 100644 menu/common.lua create mode 100644 menu/completed.lua create mode 100644 menu/pause.lua create mode 100644 menu/start.lua create mode 100644 menu/state.lua diff --git a/menu.lua b/menu.lua index 9a855d0..fda11e6 100644 --- a/menu.lua +++ b/menu.lua @@ -1,114 +1,9 @@ require 'config' require 'button' +require 'menu.state' --- 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 @@ -117,20 +12,13 @@ local backToGameButton = Button:new( Menu = { states = { -- Main menu - [MenuStateIndex.start] = MenuState:new({ - startButton, exitGameButton - }), + [MenuStateIndex.start] = require 'menu.start', -- Pause menu - [MenuStateIndex.pause] = MenuState:new({ - backToGameButton, exitToMenuButton - }), + [MenuStateIndex.pause] = require 'menu.pause', -- Level selector - [MenuStateIndex.levels] = MenuState:new({ - }), + [MenuStateIndex.levels] = MenuState:new(), -- Level completed menu - [MenuStateIndex.completed] = MenuState:new({ - nextLevelButton, exitToMenuButton - }), + [MenuStateIndex.completed] = require 'menu.completed', -- Empty state [MenuStateIndex.hidden] = MenuState:new() }, diff --git a/menu/common.lua b/menu/common.lua new file mode 100644 index 0000000..0c51db6 --- /dev/null +++ b/menu/common.lua @@ -0,0 +1,24 @@ +require 'point' +require 'button' + +local buttonTopPos = Point:new( 240, 160 ) +local buttonBotPos = Point:new( 240, 280 ) +local buttonSize = Point:new( 320, 80 ) +local titlePos = Point:new( 240, 80 ) + +return { + buttonTopPos = buttonTopPos, + buttonBotPos = buttonBotPos, + buttonSize = buttonSize, + titlePos = titlePos, + exitToMenuButton = Button:new( + buttonBotPos, + buttonSize, + 'Return to menu', + nil, + nil, + function() + Menu.current_state = MenuStateIndex.start + end + ) +} diff --git a/menu/completed.lua b/menu/completed.lua new file mode 100644 index 0000000..dab5c85 --- /dev/null +++ b/menu/completed.lua @@ -0,0 +1,29 @@ +require 'menu.state' +require 'button' +require 'text' + +local common = require 'menu.common' + +local nextLevelButton = Button:new( + common.buttonTopPos, + common.buttonSize, + 'Next level', + nil, + nil, + function() + GameGrid = LevelHandler:next() + Menu.updateCellSize() + Menu.current_state = MenuStateIndex.hidden + end +) + +local title = Text:new( + common.titlePos, + common.buttonSize, + 'Level completed!' +) + +return MenuState:new( + { nextLevelButton, common.exitToMenuButton }, + { title } +) diff --git a/menu/pause.lua b/menu/pause.lua new file mode 100644 index 0000000..2e45cd7 --- /dev/null +++ b/menu/pause.lua @@ -0,0 +1,27 @@ +require 'menu.state' +require 'button' +require 'text' + +local common = require 'menu.common' + +local backToGameButton = Button:new( + common.buttonTopPos, + common.buttonSize, + 'Continue', + nil, + nil, + function() + Menu.current_state = MenuStateIndex.hidden + end +) + +local title = Text:new( + common.titlePos, + common.buttonSize, + 'Paused' +) + +return MenuState:new( + { backToGameButton, common.exitToMenuButton }, + { title } +) diff --git a/menu/start.lua b/menu/start.lua new file mode 100644 index 0000000..d4a04d1 --- /dev/null +++ b/menu/start.lua @@ -0,0 +1,40 @@ +require 'menu.state' +require 'button' +require 'text' + +local common = require 'menu.common' + +local startButton = Button:new( + common.buttonTopPos, + common.buttonSize, + 'Start', + nil, + nil, + function() + Menu.current_state = MenuStateIndex.hidden + GameGrid = LevelHandler:first() + Menu.updateCellSize() + end +) + +local exitGameButton = Button:new( + common.buttonBotPos, + common.buttonSize, + 'Exit', + nil, + nil, + function() + love.event.quit() + end +) + +local title = Text:new( + common.titlePos, + common.buttonSize, + 'Lines' +) + +return MenuState:new( + { startButton, exitGameButton }, + { title } +) diff --git a/menu/state.lua b/menu/state.lua new file mode 100644 index 0000000..7bed4b5 --- /dev/null +++ b/menu/state.lua @@ -0,0 +1,53 @@ +-- Menu state class +---@class MenuState +---@field buttons Button[] +---@field text Text[] +MenuState = { + buttons = {}, + text = {} +} + +-- Factory function +---@param buttons Button[] | nil +---@param text Text[] | nil +---@return MenuState +function MenuState:new( buttons, text ) + local state = { + buttons = buttons or MenuState.buttons, + text = text or MenuState.text + } + + setmetatable( state, { __index = self } ) + + return state +end + +-- Draw buttons +function MenuState:draw() + for _, button in ipairs(self.buttons) do + button:draw() + end + for _, txt in ipairs(self.text) do + txt: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' +} + From 57a69a6e0ca7cf83564ee32200968e2ee886568a Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Thu, 23 Oct 2025 15:12:31 +0300 Subject: [PATCH 2/7] Take build version from config.lua --- Makefile | 2 +- config.lua | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4ba0657..da587f7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION=0.1 +VERSION=$(shell grep VERSION config.lua | sed -n -e "s/VERSION = 'v//" -e "s/'//p") IGNORE_FLAGS=--ignore Makefile --ignore build LOVE_PATH := $(shell command -v love) diff --git a/config.lua b/config.lua index 7ea90d2..c2c79e7 100644 --- a/config.lua +++ b/config.lua @@ -1,5 +1,7 @@ require 'tablefuncs' +VERSION = 'v0.2' + -- Global config table ---@class Config ---@field pointRadius number Radius of each grid point, relative to cellSize From 27a000357936ca5800d4537bd10ddc214917c359 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Thu, 23 Oct 2025 15:18:50 +0300 Subject: [PATCH 3/7] Tell lua lsp about nil-ed point --- point.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/point.lua b/point.lua index 3efb509..4795ee0 100644 --- a/point.lua +++ b/point.lua @@ -3,8 +3,8 @@ Point = { x = 1, y = 1 } -- Point factory ----@param x number ----@param y number +---@param x number | nil +---@param y number | nil ---@return any function Point:new( x, y ) local point = { From a47e14ffcaf0dde3f66f6e93157208e529c765ff Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Thu, 23 Oct 2025 15:19:10 +0300 Subject: [PATCH 4/7] print version in the main menu --- menu/start.lua | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/menu/start.lua b/menu/start.lua index d4a04d1..8693b68 100644 --- a/menu/start.lua +++ b/menu/start.lua @@ -1,9 +1,14 @@ require 'menu.state' require 'button' require 'text' +require 'point' +require 'config' local common = require 'menu.common' +local versionPos = Point:new( 0, 468 ) +local versionSize = Point:new( 800 ) + local startButton = Button:new( common.buttonTopPos, common.buttonSize, @@ -34,7 +39,14 @@ local title = Text:new( 'Lines' ) +local versionText = Text:new( + versionPos, + versionSize, + string.format("Version %s", VERSION), + 'left' +) + return MenuState:new( { startButton, exitGameButton }, - { title } + { title, versionText } ) From fd1e314ec96775e73dfcccf4f222c539ce554bb4 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Thu, 23 Oct 2025 16:32:27 +0300 Subject: [PATCH 5/7] Added indexed function --- levelhandler.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/levelhandler.lua b/levelhandler.lua index ed7b874..8c5931c 100644 --- a/levelhandler.lua +++ b/levelhandler.lua @@ -6,7 +6,7 @@ require 'makegrid' ---@field current integer LevelHandler = { levels = { - 'test3', 'test2', 'test' + 'test2', 'test', 'test3' }, current = 1, } @@ -18,13 +18,22 @@ function LevelHandler:next() if self.current > #self.levels then self.current = 1 end - local levelPath = string.format('levels/%s', self.levels[self.current]) + local levelPath = 'levels/' .. self.levels[self.current] return MakeGrid( require( levelPath ) ) end -- Returns first level ---@return Grid function LevelHandler:first() - local levelPath = string.format('levels/%s', self.levels[1]) + local levelPath = 'levels/' .. self.levels[1] + return MakeGrid( require( levelPath ) ) +end + +-- Returns level by its index in table +---@param i number +---@return Grid +function LevelHandler:indexed(i) + self.current = i + local levelPath = 'levels/' .. self.levels[self.current] return MakeGrid( require( levelPath ) ) end From e04b8e523ebdb5b7564f8f42653f61fb57370259 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Thu, 23 Oct 2025 16:32:58 +0300 Subject: [PATCH 6/7] Added levels menu --- menu.lua | 5 +---- menu/levels.lua | 47 +++++++++++++++++++++++++++++++++++++++++++++++ menu/start.lua | 4 +--- 3 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 menu/levels.lua diff --git a/menu.lua b/menu.lua index fda11e6..8906354 100644 --- a/menu.lua +++ b/menu.lua @@ -2,9 +2,6 @@ require 'config' require 'button' require 'menu.state' - - - -- Menu handler ---@class Menu ---@field states MenuState[] @@ -16,7 +13,7 @@ Menu = { -- Pause menu [MenuStateIndex.pause] = require 'menu.pause', -- Level selector - [MenuStateIndex.levels] = MenuState:new(), + [MenuStateIndex.levels] = require 'menu.levels', -- Level completed menu [MenuStateIndex.completed] = require 'menu.completed', -- Empty state diff --git a/menu/levels.lua b/menu/levels.lua new file mode 100644 index 0000000..463566e --- /dev/null +++ b/menu/levels.lua @@ -0,0 +1,47 @@ +require 'menu.state' +require 'button' +require 'text' + +local common = require 'menu.common' + +local size, margin = 60, 30 +local levelSize = Point:new( size, size ) +local yOffset = 160 + +local levelsPerLine = 8 +local levelCount = #LevelHandler.levels + +local buttons = {} + +for i=1,levelCount do + local x = (size + margin) * (i % levelsPerLine) + local y = (size + margin) * math.floor(i / levelsPerLine) + yOffset + local button = Button:new( + Point:new(x, y), + levelSize, + tostring(i), + nil, + nil, + function() + GameGrid = LevelHandler:indexed(i) + Menu.updateCellSize() + Menu.current_state = MenuStateIndex.hidden + end + ) + table.insert(buttons, button) +end + +local exitToMenuButton = Button:new( + Point:new( 240, 40 ), + common.buttonSize, + 'Return to menu', + nil, + nil, + function() + Menu.current_state = MenuStateIndex.start + end + ) + +table.insert(buttons, exitToMenuButton) + +return MenuState:new(buttons) diff --git a/menu/start.lua b/menu/start.lua index 8693b68..8630976 100644 --- a/menu/start.lua +++ b/menu/start.lua @@ -16,9 +16,7 @@ local startButton = Button:new( nil, nil, function() - Menu.current_state = MenuStateIndex.hidden - GameGrid = LevelHandler:first() - Menu.updateCellSize() + Menu.current_state = MenuStateIndex.levels end ) From 71f98fd8319c134667a442446f3fe5138a64d166 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Fri, 24 Oct 2025 12:52:33 +0300 Subject: [PATCH 7/7] Centered grid --- config.lua | 2 ++ grid.lua | 5 +++-- gridpoint.lua | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/config.lua b/config.lua index c2c79e7..08189f4 100644 --- a/config.lua +++ b/config.lua @@ -7,6 +7,7 @@ VERSION = 'v0.2' ---@field pointRadius number Radius of each grid point, relative to cellSize ---@field linePointRadius number Radius of line start/end points, relative to cellSize ---@field cellSize number Size of each grid cell +---@field gridOffset number X offset of grid processing ---@field lineStyle string love2d line style setting ---@field lineWidth number love2d line width setting ---@field menuLineWidth number love2d line width for buttons @@ -17,6 +18,7 @@ Config = { linePointRadius = 0.4, cellSize = 30, + gridOffset = 160, lineStyle = "smooth", lineWidth = 0.1, diff --git a/grid.lua b/grid.lua index fd1e57c..3af32da 100644 --- a/grid.lua +++ b/grid.lua @@ -39,8 +39,9 @@ function Grid:draw() end for y = 1, self.size.y do - local px, py = x * Config.cellSize, y * Config.cellSize - love.graphics.circle( "fill", px - Config.cellSize / 2, py - Config.cellSize / 2, Config.cellSize * Config.pointRadius) + local gp = GridPoint:new(x, y) + local px, py = gp:globalCoords() + love.graphics.circle( "fill", px, py, Config.cellSize * Config.pointRadius) end end -- Draw lines diff --git a/gridpoint.lua b/gridpoint.lua index eff5a8f..e8d57e0 100644 --- a/gridpoint.lua +++ b/gridpoint.lua @@ -9,7 +9,7 @@ GridPoint = Point ---@return Point function GridPoint:absolute() return Point:new( - self.x * Config.cellSize, + self.x * Config.cellSize + Config.gridOffset, self.y * Config.cellSize ) end @@ -17,7 +17,7 @@ end -- Same as coords, but converted to global coords ---@return number, number function GridPoint:globalCoords() - return self.x * Config.cellSize - Config.cellSize / 2, + return self.x * Config.cellSize - Config.cellSize / 2 + Config.gridOffset, self.y * Config.cellSize - Config.cellSize / 2 end @@ -25,7 +25,7 @@ end ---@param point Point ---@return GridPoint function GridPoint.snapCoords( point ) - local x = math.ceil( point.x / Config.cellSize ) + local x = math.ceil( (point.x - Config.gridOffset) / Config.cellSize ) local y = math.ceil( point.y / Config.cellSize ) return GridPoint:new( x, y ) end