Compare commits
7 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 71f98fd831 | |||
| e04b8e523e | |||
| fd1e314ec9 | |||
| a47e14ffca | |||
| 27a0003579 | |||
| 57a69a6e0c | |||
| 7df0478890 |
13 changed files with 260 additions and 131 deletions
2
Makefile
2
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)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
require 'tablefuncs'
|
||||
|
||||
VERSION = 'v0.2'
|
||||
|
||||
-- Global config table
|
||||
---@class Config
|
||||
---@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
|
||||
|
|
@ -15,6 +18,7 @@ Config = {
|
|||
linePointRadius = 0.4,
|
||||
|
||||
cellSize = 30,
|
||||
gridOffset = 160,
|
||||
|
||||
lineStyle = "smooth",
|
||||
lineWidth = 0.1,
|
||||
|
|
|
|||
5
grid.lua
5
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
125
menu.lua
125
menu.lua
|
|
@ -1,114 +1,6 @@
|
|||
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
|
||||
)
|
||||
require 'menu.state'
|
||||
|
||||
-- Menu handler
|
||||
---@class Menu
|
||||
|
|
@ -117,20 +9,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] = require 'menu.levels',
|
||||
-- Level completed menu
|
||||
[MenuStateIndex.completed] = MenuState:new({
|
||||
nextLevelButton, exitToMenuButton
|
||||
}),
|
||||
[MenuStateIndex.completed] = require 'menu.completed',
|
||||
-- Empty state
|
||||
[MenuStateIndex.hidden] = MenuState:new()
|
||||
},
|
||||
|
|
|
|||
24
menu/common.lua
Normal file
24
menu/common.lua
Normal file
|
|
@ -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
|
||||
)
|
||||
}
|
||||
29
menu/completed.lua
Normal file
29
menu/completed.lua
Normal file
|
|
@ -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 }
|
||||
)
|
||||
47
menu/levels.lua
Normal file
47
menu/levels.lua
Normal file
|
|
@ -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)
|
||||
27
menu/pause.lua
Normal file
27
menu/pause.lua
Normal file
|
|
@ -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 }
|
||||
)
|
||||
50
menu/start.lua
Normal file
50
menu/start.lua
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
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,
|
||||
'Start',
|
||||
nil,
|
||||
nil,
|
||||
function()
|
||||
Menu.current_state = MenuStateIndex.levels
|
||||
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'
|
||||
)
|
||||
|
||||
local versionText = Text:new(
|
||||
versionPos,
|
||||
versionSize,
|
||||
string.format("Version %s", VERSION),
|
||||
'left'
|
||||
)
|
||||
|
||||
return MenuState:new(
|
||||
{ startButton, exitGameButton },
|
||||
{ title, versionText }
|
||||
)
|
||||
53
menu/state.lua
Normal file
53
menu/state.lua
Normal file
|
|
@ -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'
|
||||
}
|
||||
|
||||
|
|
@ -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 = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue