From c6547c112153f5573ce2a9db08b7f19b15b87998 Mon Sep 17 00:00:00 2001 From: 2ndbeam <2ndbeam@disroot.org> Date: Wed, 29 Oct 2025 18:12:43 +0300 Subject: [PATCH] Almost working from 1st try --- config.lua | 5 ++++ gridpoint.lua | 31 ++++++++++++++++++++++ main.lua | 33 +++++++++++++++++++++++ mechanism.lua | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ mouse.lua | 19 ++++++++++++++ point.lua | 42 +++++++++++++++++++++++++++++ port.lua | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ tablefuncs.lua | 27 +++++++++++++++++++ 8 files changed, 297 insertions(+) create mode 100644 config.lua create mode 100644 gridpoint.lua create mode 100644 main.lua create mode 100644 mechanism.lua create mode 100644 mouse.lua create mode 100644 point.lua create mode 100644 port.lua create mode 100644 tablefuncs.lua diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..93d9be9 --- /dev/null +++ b/config.lua @@ -0,0 +1,5 @@ +Config = { + cellSize = 64, + gridOffset = 0, + portWidth = 16 +} diff --git a/gridpoint.lua b/gridpoint.lua new file mode 100644 index 0000000..e8d57e0 --- /dev/null +++ b/gridpoint.lua @@ -0,0 +1,31 @@ +require 'point' +require 'config' + +-- Point table with grid-based coordinates +---@class GridPoint: Point +GridPoint = Point + +-- Convert grid x, y to global x, y +---@return Point +function GridPoint:absolute() + return Point:new( + self.x * Config.cellSize + Config.gridOffset, + 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 + Config.gridOffset, + self.y * Config.cellSize - Config.cellSize / 2 +end + +-- Returns local coords from global +---@param point Point +---@return GridPoint +function GridPoint.snapCoords( point ) + local x = math.ceil( (point.x - Config.gridOffset) / Config.cellSize ) + local y = math.ceil( point.y / Config.cellSize ) + return GridPoint:new( x, y ) +end diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..1893794 --- /dev/null +++ b/main.lua @@ -0,0 +1,33 @@ +require 'point' +require 'gridpoint' +require 'mouse' +require 'mechanism' +require 'port' + +function love.load() + Screenw, Screenh = love.window.getMode() + Gridw, Gridh = Screenw / Config.cellSize, Screenh / Config.cellSize + local port = Port:new( GridPoint:new(-1, 0), PortRotation.left, { 0.8, 0.8, 0, 1 } ) + Mecha1 = Mechanism:new( GridPoint:new(5, 5), GridPoint:new(3, 3), { port }, {0.5, 0.5, 0.5, 1} ) +end + +function love.update( dt ) + dt = dt + Mouse:update() +end + +function love.draw() + for i = 1, Gridw do + love.graphics.line( i * Config.cellSize, 0, i * Config.cellSize, Screenh ) + end + for j = 1, Gridh do + love.graphics.line( 0, j * Config.cellSize, Screenw, j * Config.cellSize ) + end + local mx, my = Mouse.point:globalCoords() + mx = mx - Config.cellSize / 2 + my = my - Config.cellSize / 2 + local mh, mw = Config.cellSize, Config.cellSize + love.graphics.rectangle("fill", mx, my, mh, mw) + + Mecha1:draw() +end diff --git a/mechanism.lua b/mechanism.lua new file mode 100644 index 0000000..9401d58 --- /dev/null +++ b/mechanism.lua @@ -0,0 +1,69 @@ +require 'tablefuncs' +require 'gridpoint' +require 'port' + +---@param xcorner GridPoint +---@param size GridPoint +---@return GridPoint +local function nextxcorner( xcorner, size ) + local cornerLookup = { + GridPoint:new( 0, 0 ), + GridPoint:new( size.x - 1, 0 ), + GridPoint:new( size.x - 1, size.y - 1 ), + GridPoint:new( size.x - 1, size.y - 1 ) + } + local index = TableFind(cornerLookup, xcorner, function(value) value:equals(xcorner) end) + if index < #cornerLookup then + index = index + 1 + else + index = 0 + end + return cornerLookup[index] +end + +---@class Mechanism +---@field position GridPoint +---@field size GridPoint +---@field xcorner GridPoint +---@field ports Port[] +---@field color table +Mechanism = { + position = GridPoint:new( 0, 0 ), + size = GridPoint:new( 1, 1 ), + xcorner = GridPoint:new( 0, 0 ), + ports = {}, + color = { 0.5, 0.5, 0.5, 1 } +} + +function Mechanism:new( position, size, ports, color ) + local mechanism = { + position = position or self.position, + size = size or self.size, + ports = ports or {}, + color = color or self.color + } + + setmetatable( mechanism, { __index = self } ) + + return mechanism +end + +function Mechanism:rotateClockwise() + self.xcorner = nextxcorner(self.xcorner, self.size) + for _, port in ipairs(self.ports) do + port:rotateClockwise() + end +end + +function Mechanism:draw() + love.graphics.setColor(self.color) + local x, y = self.position:globalCoords() + x = x - Config.cellSize / 2 + y = y - Config.cellSize / 2 + local w, h = self.size:globalCoords() + love.graphics.rectangle("fill", x, y, w, h) + for _, port in ipairs(self.ports) do + local offset = GridPoint:new( self.position.x + self.xcorner.x, self.position.y + self.xcorner.y ) + port:draw( offset ) + end +end diff --git a/mouse.lua b/mouse.lua new file mode 100644 index 0000000..c880cd4 --- /dev/null +++ b/mouse.lua @@ -0,0 +1,19 @@ +-- TODO: rewrite +---@class Mouse +---@field x integer +---@field y integer +---@field point GridPoint +Mouse = { + x = 0, + y = 0, + point = GridPoint:new( 0, 0 ) +} + +-- TODO: fix collision with other line's endpoint +function Mouse:update() + Mouse.x, Mouse.y = love.mouse.getPosition() + Mouse.x = Mouse.x + 1 + Mouse.y = Mouse.y + 1 + + Mouse.point = GridPoint.snapCoords( Point:new( Mouse.x, Mouse.y ) ) +end diff --git a/point.lua b/point.lua new file mode 100644 index 0000000..4795ee0 --- /dev/null +++ b/point.lua @@ -0,0 +1,42 @@ +-- Represents 2D point +---@class Point +Point = { x = 1, y = 1 } + +-- Point factory +---@param x number | nil +---@param y number | nil +---@return any +function Point:new( x, y ) + local point = { + x = x or x, + y = y or y + } + + setmetatable( point, { __index = self } ) + + return point +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 + +-- Return vector length between points +---@param point Point +---@return number +function Point:distanceTo( point ) + return math.sqrt( + ( self.x - point.x ) ^ 2 + + ( self.y - point.y ) ^ 2 + ) +end + diff --git a/port.lua b/port.lua new file mode 100644 index 0000000..bed4976 --- /dev/null +++ b/port.lua @@ -0,0 +1,71 @@ +require 'gridpoint' + +---@enum Alignment +Alignment = { + Vertical = true, + Horizontal = false +} + +---@enum PortRotation +PortRotation = { + right = {false, false}, + down = {false, true}, + left = {true, false}, + up = {true, true} +} + +---@class Port +---@field position GridPoint +---@field alignment Alignment +---@field scanOffset number +---@field color table +Port = { + position = GridPoint:new(0, 0), + alignment = Alignment.Vertical, + scanOffset = 0, + color = { 0.8, 0.8, 0, 1 } +} + +---@param position GridPoint +---@param rotation PortRotation +---@param color table +---@return Port +function Port:new(position, rotation, color) + local port = { + position = position or self.position, + alignment = self.alignment, + scanOffset = self.scanOffset, + color = color or self.color + } + if rotation ~= nil then + port.scanOffset = rotation[1] and 1 or 0 + port.alignment = rotation[2] + end + + setmetatable(port, { __index = self }) + + return port +end + +function Port:rotateClockwise() + local swap = self.position.x + self.position.x = -self.position.y + self.position.y = swap + self.scanOffset = (self.scanOffset == 1) == self.alignment and 1 or 0 + self.alignment = not self.alignment +end + +---@param offset GridPoint +function Port:draw( offset ) + love.graphics.setColor(self.color) + local drawPoint = GridPoint:new( + offset.x + self.position.x + self.scanOffset, + offset.y + self.position.y + self.scanOffset + ) + local x, y = drawPoint:globalCoords() + x = self.alignment and x - Config.cellSize / 2 or x - Config.portWidth / 2 - Config.cellSize / 2 + y = self.alignment and y - Config.portWidth / 2 - Config.cellSize / 2 or y - Config.cellSize / 2 + local w = self.alignment and Config.cellSize or Config.portWidth + local h = self.alignment and Config.portWidth or Config.cellSize + love.graphics.rectangle("fill", x, y, w, h) +end diff --git a/tablefuncs.lua b/tablefuncs.lua new file mode 100644 index 0000000..e478747 --- /dev/null +++ b/tablefuncs.lua @@ -0,0 +1,27 @@ +-- Find key by value in table by predicate +---@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 + end + end + return nil +end + +-- Find if value exists in table by predicate +---@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 + end + return false +end