diff --git a/button.lua b/button.lua new file mode 100644 index 0000000..eecb798 --- /dev/null +++ b/button.lua @@ -0,0 +1,83 @@ +require 'point' + +-- Clickable UI button +---@class Button +---@field position Point +---@field size Point +---@field prevPressed boolean +---@field lastPressed boolean +Button = { + position = Point:new( 1, 1 ), + size = Point:new( 1, 1 ), + prevPressed = false, + lastPressed = false +} + +-- Factory function +---@param position Point | nil +---@param size Point | nil +---@param pressed function | nil +---@param held function | nil +---@param released function | nil +---@return Button +function Button:new( position, size, pressed, held, released ) + local button = { + position = position or Button.position, + size = size or Button.size, + prevPressed = false, + lastPressed = false, + pressed = pressed or Button.pressed, + held = held or Button.held, + released = released or Button.released + } + + setmetatable( button, { __index = self } ) + + return button +end + +-- Called when button just clicked +function Button:pressed() end +-- Called when button is held +---@param dt number +function Button:held( dt ) dt = dt end +-- Called when button is just unclicked +function Button:released() end + +-- Drawing function +function Button:draw() + local x, y = self.position:coords() + local w, h = self.size:coords() + love.graphics.rectangle( 'line', x, y, w, h ) +end + +-- Check if given point is in bounds of button +---@param point Point +---@return boolean +function Button:checkPoint( point ) + local px, py = point:coords() + local sx, sy = self.position:coords() + local ex, ey = self.position:coords() + ex = ex + sx + ey = ey + sy + return px >= sx and px <= ex and py >= sy and py <= ey +end + +-- Changing states and calls appropriate functions +---@param dt number +---@param point Point +function Button:update( dt, point, pressed ) + self.prevPressed = self.lastPressed + self.lastPressed = pressed + + if self.lastPressed and not self.prevPressed then + local inBounds = self:checkPoint( point ) + if inBounds then + self:pressed() + end + elseif self.lastPressed and self.prevPressed then + self:held( dt ) + elseif not self.lastPressed and self.prevPressed then + self:released() + end +end diff --git a/config.lua b/config.lua index c582db6..67698c8 100644 --- a/config.lua +++ b/config.lua @@ -2,21 +2,21 @@ require 'tablefuncs' -- Global config table ---@class Config ----@field pointRadius number Radius of each grid point ----@field linePointRadius number Radius of line start/end point +---@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 lineStyle string love2d line style setting ---@field lineWidth number love2d line width setting ---@field dragSensivity number drag sensivity, px Config = { - pointRadius = 7, + pointRadius = 0.3, - linePointRadius = 10, + linePointRadius = 0.4, cellSize = 30, lineStyle = "smooth", - lineWidth = 5, + lineWidth = 0.1, dragSensivity = 5 } diff --git a/grid.lua b/grid.lua index 5faeab4..fd1e57c 100644 --- a/grid.lua +++ b/grid.lua @@ -12,7 +12,7 @@ Grid = { -- Factory function ---@param size Point ----@returns Grid +---@return Grid function Grid:new( size ) local grid = { lines = {}, @@ -40,7 +40,7 @@ function Grid:draw() 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.pointRadius) + love.graphics.circle( "fill", px - Config.cellSize / 2, py - Config.cellSize / 2, Config.cellSize * Config.pointRadius) end end -- Draw lines diff --git a/levelhandler.lua b/levelhandler.lua index e5941e7..ed7b874 100644 --- a/levelhandler.lua +++ b/levelhandler.lua @@ -6,7 +6,7 @@ require 'makegrid' ---@field current integer LevelHandler = { levels = { - 'test2', 'test' + 'test3', 'test2', 'test' }, current = 1, } diff --git a/levels/test3.lua b/levels/test3.lua new file mode 100644 index 0000000..e256e3e --- /dev/null +++ b/levels/test3.lua @@ -0,0 +1,9 @@ +return { + width = 6, + height = 6, + lines = { + { 5, 4, 2, 2, "green" }, + { 2, 5, 4, 1, "red" }, + { 2, 4, 5, 1, "blue" } + } +} diff --git a/line.lua b/line.lua index 4208a66..08d8703 100644 --- a/line.lua +++ b/line.lua @@ -51,9 +51,9 @@ function Line:draw() love.graphics.setColor( self.color ) -- Draw start and end points (should look like rings) local sx, sy = self.startpoint:globalCoords() - love.graphics.circle( "fill", sx, sy, Config.linePointRadius ) + love.graphics.circle( "fill", sx, sy, Config.cellSize * Config.linePointRadius ) local ex, ey = self.endpoint:globalCoords() - love.graphics.circle( "fill", ex, ey, Config.linePointRadius ) + love.graphics.circle( "fill", ex, ey, Config.cellSize * Config.linePointRadius ) if #self.points <= 1 then love.graphics.setColor( Color.white ) return diff --git a/main.lua b/main.lua index 404a262..3c03696 100644 --- a/main.lua +++ b/main.lua @@ -3,44 +3,71 @@ require 'point' require 'line' require 'mouse' require 'levelhandler' +require 'button' Input = require 'input' -function love.load() - love.graphics.setLineStyle( Config.lineStyle ) - love.graphics.setLineWidth( Config.lineWidth ) +InMenu = true - GameGrid = LevelHandler:first() +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 ) + + + love.graphics.setLineStyle( Config.lineStyle ) end function love.update( dt ) 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 - if Input:actionReleased( 'exit' ) then - love.event.quit() - end - - if Input:actionReleased( 'nextlevel' ) then - if GameGrid:isCompleted() then - GameGrid = LevelHandler:next() + if Input:actionReleased( 'nextlevel' ) then + if GameGrid:isCompleted() then + GameGrid = LevelHandler:next() + updateCellSize() + end end end end function love.draw() - GameGrid:draw() + if InMenu then + MenuStartButton:draw() + else + 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 ) - love.graphics.print( text, 64, 256 ) + 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 ) + love.graphics.print( text, 64, 256 ) - if Mouse.dragged then - love.graphics.print( "drag", 64, 300 ) - end - if Mouse.lastLine ~= nil then - love.graphics.print( tostring( Mouse.lastLine ), 128, 300 ) - end + if Mouse.dragged then + love.graphics.print( "drag", 64, 300 ) + end + if Mouse.lastLine ~= nil then + love.graphics.print( tostring( Mouse.lastLine ), 128, 300 ) + end - if GameGrid:isCompleted() then - love.graphics.print( "Grid completed. Press space to proceed to next", 64, 320 ) + if GameGrid:isCompleted() then + love.graphics.print( "Grid completed. Press space to proceed to next", 64, 320 ) + end end end diff --git a/mouse.lua b/mouse.lua index af2ba94..b7ad814 100644 --- a/mouse.lua +++ b/mouse.lua @@ -31,6 +31,11 @@ function Mouse:update() Mouse.lastPoint = Mouse.point Mouse.lastPressed = Mouse.pressed Mouse.pressed = love.mouse.isDown( 1 ) + + if InMenu then + return + end + Mouse.point = GridPoint.snapCoords( Point:new( Mouse.x, Mouse.y ) ) if Mouse.lastLine ~= nil then local pointsLen = #Mouse.lastLine.points