Almost working from 1st try

This commit is contained in:
Alexey 2025-10-29 18:12:43 +03:00
commit c6547c1121
8 changed files with 297 additions and 0 deletions

5
config.lua Normal file
View file

@ -0,0 +1,5 @@
Config = {
cellSize = 64,
gridOffset = 0,
portWidth = 16
}

31
gridpoint.lua Normal file
View file

@ -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

33
main.lua Normal file
View file

@ -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

69
mechanism.lua Normal file
View file

@ -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

19
mouse.lua Normal file
View file

@ -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

42
point.lua Normal file
View file

@ -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

71
port.lua Normal file
View file

@ -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

27
tablefuncs.lua Normal file
View file

@ -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