From c7d8fa4f8b9b1cb550aa4bb3c5f4f09cede05784 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Wed, 25 Jun 2025 13:05:41 +0300 Subject: [PATCH] Added lua-language-server annotations --- .luarc.json | 4 ++ config.lua | 29 +++++++++---- grid.lua | 28 +++++++++--- gridpoint.lua | 7 ++- line.lua | 36 ++++++++++++---- main.lua | 117 +++++++++++++++++++++++++------------------------- point.lua | 17 +++++--- 7 files changed, 151 insertions(+), 87 deletions(-) create mode 100644 .luarc.json diff --git a/.luarc.json b/.luarc.json new file mode 100644 index 0000000..54f884d --- /dev/null +++ b/.luarc.json @@ -0,0 +1,4 @@ +{ + "$SCHEMA": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json", + "diagnostics.globals": [ "love" ] +} diff --git a/config.lua b/config.lua index 5458694..cf774fd 100644 --- a/config.lua +++ b/config.lua @@ -1,21 +1,26 @@ -- Global config table +---@class Config +---@field pointRadius number Radius of each grid point +---@field linePointRadius number Radius of line start/end point +---@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 = { - -- Radius of each grid point pointRadius = 7, - -- Radius of line start/end point + linePointRadius = 10, - -- Size of each grid cell + cellSize = 30, - -- love2d line drawing settings lineStyle = "smooth", lineWidth = 5, - -- drag sensivity, px dragSensivity = 5 } -- Colors table +---@enum Color Color = { white = { 1, 1, 1 }, red = { 1, 0, 0 }, @@ -24,7 +29,11 @@ Color = { } -- Find key by value in table by predicate -function tableFind( table, value, pred ) +---@param table table +---@param value any +---@param pred function +---@return any +function TableFind( table, value, pred ) for key, innervalue in pairs( table ) do if pred( value, innervalue ) then return key @@ -34,8 +43,12 @@ function tableFind( table, value, pred ) end -- Find if value exists in table by predicate -function tableHas( table, value, pred ) - for key, innervalue in pairs( table ) do +---@param table table +---@param value any +---@param pred function +---@return boolean +function TableHas( table, value, pred ) + for _, innervalue in pairs( table ) do if pred( value, innervalue ) then return true end diff --git a/grid.lua b/grid.lua index 8f822e9..e8ab752 100644 --- a/grid.lua +++ b/grid.lua @@ -1,9 +1,17 @@ require "config" -- Game grid table, acts as "global level" of some sort -Grid = {} +---@class Grid +---@field lines Line[] +---@field size Point +Grid = { + lines = {}, + size = Point:new( Point:coords() ) +} -- Factory function +---@param size Point +---@returns Grid function Grid:new( size ) local grid = { lines = {}, @@ -16,6 +24,7 @@ function Grid:new( size ) end -- Add new line to grid +---@param line Line function Grid:push( line ) table.insert( self.lines, line ) end @@ -42,13 +51,15 @@ end -- Check all lines and return one, which contains point (if any) -- TODO: rewrite this function to extract clear/reverse behavior +---@param point Point +---@param ignoreEnd boolean function Grid:matchesLine( point, ignoreEnd ) - local line = self.lines[tableFind( self.lines, point, + local line = self.lines[TableFind( self.lines, point, function( value, innervalue ) return innervalue:has( value ) end )] - + if line ~= nil and not ignoreEnd then if line.startpoint:equals( point ) then line:clear() @@ -63,7 +74,7 @@ function Grid:matchesLine( point, ignoreEnd ) -- Try to check endpoint if line == nil and not ignoreEnd then - line = self.lines[tableFind( self.lines, point, + line = self.lines[TableFind( self.lines, point, function( value, innervalue ) if innervalue.endpoint:equals( value ) then innervalue:clear() @@ -77,13 +88,20 @@ function Grid:matchesLine( point, ignoreEnd ) return line end +-- Checks if specified point does belong to any line endpoint but not specified line +---@param line Line +---@param point GridPoint +---@return boolean function Grid:isOtherEndpoint( line, point ) - return tableHas( self.lines, { line=line, point=point }, function( value, innervalue ) + return TableHas( self.lines, { line=line, point=point }, function( value, innervalue ) return innervalue ~= value.line and innervalue.endpoint:equals( value.point ) end ) end +-- Checks if point is in grid bounds +---@param point GridPoint +---@return boolean function Grid:inBounds( point ) return point.x <= self.size.x and point.y <= self.size.y end diff --git a/gridpoint.lua b/gridpoint.lua index fcf6a1d..735390a 100644 --- a/gridpoint.lua +++ b/gridpoint.lua @@ -2,17 +2,20 @@ require "point" require "config" -- Point table with grid-based coordinates -GridPoint = Point:new() +---@class GridPoint: Point +GridPoint = Point -- Convert grid x, y to global x, y +---@return Point function GridPoint:absolute() - return Point:new( + return Point:new( self.x * Config.cellSize, self.y * Config.cellSize ) end -- Same as coords, but converted to global coords +---@return number, number function GridPoint:globalCoords() return self.x * Config.cellSize - Config.cellSize / 2, self.y * Config.cellSize - Config.cellSize / 2 end diff --git a/line.lua b/line.lua index d89e24b..d0058ec 100644 --- a/line.lua +++ b/line.lua @@ -1,18 +1,32 @@ require "gridpoint" --- Line table, interactive game object --- NOTE: uses GridPoint -Line = {} +-- Interactive game object +---@class Line +---@field startpoint GridPoint +---@field endpoint GridPoint +---@field points GridPoint[] +---@field color Color +Line = { + + startpoint = GridPoint:new( GridPoint:coords() ), + endpoint = GridPoint:new( GridPoint:coords() ), + points = { }, + color = Color.red +} -- Factory function +---@param startpoint GridPoint +---@param endpoint GridPoint +---@param color Color +---@return Line function Line:new( startpoint, endpoint, color ) local line = { - startpoint = startpoint, - endpoint = endpoint, + startpoint = startpoint or self.startpoint, + endpoint = endpoint or self.endpoint, points = { - startpoint + startpoint or self.startpoint }, - color = color + color = color or self.color } setmetatable( line, { __index = self } ) @@ -21,11 +35,13 @@ function Line:new( startpoint, endpoint, color ) end -- Push point to the end of points stack +---@param point GridPoint function Line:push( point ) table.insert( self.points, point ) end -- Pop point from points stack +---@return GridPoint function Line:pop() return table.remove( self.points ) end @@ -64,13 +80,15 @@ end function Line:reverse() local swap = self.startpoint self.startpoint = self.endpoint - self.endpoint = swap + self.endpoint = swap self:push( self.startpoint ) end -- Check if line has the exact point +---@param point GridPoint +---@return boolean function Line:has( point ) - return tableHas( self.points, point, + return TableHas( self.points, point, function( value, innervalue ) return innervalue:equals( value ) end diff --git a/main.lua b/main.lua index 99d0704..1907390 100644 --- a/main.lua +++ b/main.lua @@ -2,31 +2,42 @@ require "grid" require "point" require "line" +-- Returns local coords from global +local function snapCoords( point ) + local x = math.ceil( point.x / Config.cellSize ) + local y = math.ceil( point.y / Config.cellSize ) + return GridPoint:new( x, y ) +end + +local function vectorLength( startpoint, endpoint ) + return math.sqrt( ( startpoint.x - endpoint.x ) ^ 2 + ( startpoint.y - endpoint.y ) ^ 2 ) +end + function love.load() love.graphics.setLineStyle( Config.lineStyle ) love.graphics.setLineWidth( Config.lineWidth ) - gameGrid = Grid:new( Point:new( 5, 5 ) ) + GameGrid = Grid:new( Point:new( 5, 5 ) ) local line = Line:new( GridPoint:new( 1, 1 ), GridPoint:new( 3, 3 ), Color.red ) - gameGrid:push( line ) + GameGrid:push( line ) local line1 = Line:new( GridPoint:new( 1, 5 ), GridPoint:new( 5, 2 ), Color.green ) - gameGrid:push( line1 ) + GameGrid:push( line1 ) local line2 = Line:new( GridPoint:new( 2, 5 ), GridPoint:new( 5, 3 ), Color.blue ) - gameGrid:push( line2 ) + GameGrid:push( line2 ) - mouse = { + Mouse = { x = 0, y = 0, pressed = false, @@ -43,75 +54,65 @@ end -- TODO: move input interactions into module -- TODO: fix collision with other line's endpoint function love.update( dt ) - mouse.x, mouse.y = love.mouse.getPosition() - mouse.x = mouse.x + 1 - mouse.y = mouse.y + 1 - mouse.lastPoint = mouse.point - mouse.lastPressed = pressed - mouse.pressed = love.mouse.isDown( 1 ) - mouse.point = snapCoords( Point:new( mouse.x, mouse.y ) ) - if mouse.lastLine ~= nil then - local pointsLen = #mouse.lastLine.points - local lastLinePoint = mouse.lastLine.points[pointsLen] - if vectorLength( mouse.point, lastLinePoint ) == 1 - and gameGrid:inBounds( mouse.point ) - and gameGrid:matchesLine( mouse.point, true ) == nil - and not lastLinePoint:equals( mouse.lastLine.endpoint ) - and not gameGrid:isOtherEndpoint( mouse.lastLine, mouse.point ) then - mouse.lastLine:push( mouse.point ) - elseif mouse.lastLine:has( mouse.point ) - and not mouse.point:equals( lastLinePoint ) then - while not mouse.lastLine.points[#mouse.lastLine.points]:equals( mouse.point ) do - mouse.lastLine:pop() + Mouse.x, Mouse.y = love.mouse.getPosition() + Mouse.x = Mouse.x + 1 + Mouse.y = Mouse.y + 1 + Mouse.lastPoint = Mouse.point + Mouse.lastPressed = Mouse.pressed + Mouse.pressed = love.mouse.isDown( 1 ) + Mouse.point = snapCoords( Point:new( Mouse.x, Mouse.y ) ) + if Mouse.lastLine ~= nil then + local pointsLen = #Mouse.lastLine.points + local lastLinePoint = Mouse.lastLine.points[pointsLen] + if vectorLength( Mouse.point, lastLinePoint ) == 1 + and GameGrid:inBounds( Mouse.point ) + and GameGrid:matchesLine( Mouse.point, true ) == nil + and not lastLinePoint:equals( Mouse.lastLine.endpoint ) + and not GameGrid:isOtherEndpoint( Mouse.lastLine, Mouse.point ) then + Mouse.lastLine:push( Mouse.point ) + elseif Mouse.lastLine:has( Mouse.point ) + and not Mouse.point:equals( lastLinePoint ) then + while not Mouse.lastLine.points[#Mouse.lastLine.points]:equals( Mouse.point ) do + Mouse.lastLine:pop() end end end - - mouse.dragged = mouse.pressed - and mouse.startX > 0 - and vectorLength( - Point:new( mouse.x, mouse.y ), - Point:new( mouse.startX, mouse.startY ) + + Mouse.dragged = Mouse.pressed + and Mouse.startX > 0 + and vectorLength( + Point:new( Mouse.x, Mouse.y ), + Point:new( Mouse.startX, Mouse.startY ) ) > Config.dragSensivity - if not mouse.pressed and mouse.startX > 0 then - mouse.startX = -1 - mouse.startY = -1 - mouse.lastLine = nil + if not Mouse.pressed and Mouse.startX > 0 then + Mouse.startX = -1 + Mouse.startY = -1 + Mouse.lastLine = nil end - if not mouse.lastPressed - and mouse.pressed - and mouse.startX < 0 then - mouse.startX = mouse.x - mouse.startY = mouse.y - mouse.lastLine = gameGrid:matchesLine( mouse.point, false ) + if not Mouse.lastPressed + and Mouse.pressed + and Mouse.startX < 0 then + Mouse.startX = Mouse.x + Mouse.startY = Mouse.y + Mouse.lastLine = GameGrid:matchesLine( Mouse.point, false ) end end function love.draw() - gameGrid:draw() + 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 ) + 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 ) + + if Mouse.dragged then + love.graphics.print( "drag", 64, 300 ) end - if mouse.lastLine ~= nil then - love.graphics.print( tostring( mouse.lastLine ), 128, 300 ) + if Mouse.lastLine ~= nil then + love.graphics.print( tostring( Mouse.lastLine ), 128, 300 ) end - end --- Returns local coords from global -function snapCoords( point ) - local x = math.ceil( point.x / Config.cellSize ) - local y = math.ceil( point.y / Config.cellSize ) - return GridPoint:new( x, y ) -end -function vectorLength( startpoint, endpoint ) - return math.sqrt( ( startpoint.x - endpoint.x ) ^ 2 + ( startpoint.y - endpoint.y ) ^ 2 ) -end diff --git a/point.lua b/point.lua index d474252..4a85d06 100644 --- a/point.lua +++ b/point.lua @@ -1,11 +1,15 @@ --- Point table -Point = {} +-- Represents 2D point +---@class Point +Point = { x = 1, y = 1 } --- Factory function +-- Point factory +---@param x number +---@param y number +---@return any function Point:new( x, y ) local point = { - x = x or 1, - y = y or 1 + x = x or x, + y = y or y } setmetatable( point, { __index = self } ) @@ -14,11 +18,14 @@ function Point:new( x, y ) end -- Comparing function +---@param point self +---@return boolean function Point:equals( point ) return self.x == point.x and self.y == point.y end -- Get self coordinates +---@return number, number function Point:coords() return self.x, self.y end