diff --git a/input.lua b/input.lua new file mode 100644 index 0000000..1708e1f --- /dev/null +++ b/input.lua @@ -0,0 +1,98 @@ +-- Input system +-- TODO: replace this with universal system +local Input = { + keyboardButtons = { '1', '2', '3', '4', 'r' }, + keyboardPressed = {}, + lastKeyboardPressed = {}, + actions = {} +} + +local function mapAction( input, action, keys ) + input.actions[action] = {} + for _, key in pairs( keys ) do + table.insert( input.actions[action], key ) + end +end + +local function loadMap( input ) + mapAction( input, 'first', { '1' } ) + mapAction( input, 'second', { '2' } ) + mapAction( input, 'third', { '3' } ) + mapAction( input, 'none', { '4' } ) + mapAction( input, 'rotate', { 'r' } ) +end + +local function predHolded( pressed, _ ) + return pressed +end + +local function predPressed( pressed, lastPressed ) + return pressed and not lastPressed +end + +local function predReleased( pressed, lastPressed ) + return not pressed and lastPressed +end + +local function testAction( input, action, predicate ) + for _, key in ipairs( input.actions[action] ) do + local pressed, lastPressed + + pressed = input.keyboardPressed + lastPressed = input.lastKeyboardPressed + + if predicate( pressed[key], lastPressed[key] ) then + return true + end + end + + return false +end + +function Input.init() + for btn in ipairs( Input.keyboardButtons ) do + Input.keyboardPressed[Input.keyboardButtons[btn]] = false + Input.lastKeyboardPressed[Input.keyboardButtons[btn]] = false + end + + loadMap( Input ) + + return Input +end + +function Input:update() + for k, _ in pairs( self.keyboardPressed ) do + self.lastKeyboardPressed[k] = self.keyboardPressed[k] + end + + for button in ipairs( self.keyboardButtons ) do + self.keyboardPressed[self.keyboardButtons[button]] = love.keyboard.isDown( self.keyboardButtons[button] ) + end +end + +function Input:actionHolded( action ) + return testAction( self, action, predHolded ) +end + +function Input:actionReleased( action ) + return testAction( self, action, predReleased ) +end + +function Input:actionPressed( action ) + return testAction( self, action, predPressed ) +end + +function Input:actionDiff( negative, positive ) + local negResult = testAction( self, negative, predHolded ) + local posResult = testAction( self, positive, predHolded ) + + if negResult and not posResult then + return -1 + elseif posResult and not negResult then + return 1 + else + return 0 + end +end + +return Input.init() diff --git a/main.lua b/main.lua index 6e60897..8316543 100644 --- a/main.lua +++ b/main.lua @@ -4,48 +4,53 @@ require 'mouse' require 'mechanism' require 'port' require 'tablefuncs' +Input = require 'input' +require 'selector' function love.load() Screenw, Screenh = love.window.getMode() Gridw, Gridh = Screenw / Config.cellSize, Screenh / Config.cellSize - local port1 = Port:new( GridPoint:new(-1, 0), PortRotation.left, { 0.8, 0.8, 0, 1 } ) - local port2 = Port:new( GridPoint:new(0, -1), PortRotation.up, { 0.8, 0, 0.8, 1 } ) - local port3 = Port:new( GridPoint:new(3, 2), PortRotation.right, { 0.8, 0, 0, 1 } ) - local port4 = Port:new( GridPoint:new(2, 3), PortRotation.down, { 0, 0, 0.8, 1 } ) - local mecha1 = Mechanism:new( GridPoint:new(5, 5), GridPoint:new(3, 3), { port1, port2, port3, port4 }, {0.5, 0.5, 0.5, 1} ) + Mechs = {} - local port5 = Port:new( GridPoint:new(-1, 0), PortRotation.left, { 0.8, 0.8, 0, 1 } ) - local port6 = Port:new( GridPoint:new(0, -1), PortRotation.up, { 0.8, 0, 0.8, 1 } ) - local port7 = Port:new( GridPoint:new(2, 1), PortRotation.right, { 0.8, 0, 0, 1 } ) - local port8 = Port:new( GridPoint:new(1, 2), PortRotation.down, { 0, 0, 0.8, 1 } ) - local mecha2 = Mechanism:new( GridPoint:new(10, 5), GridPoint:new(2, 2), { port5, port6, port7, port8 }, {0.5, 1, 0.5, 1} ) - - local port9 = Port:new( GridPoint:new(-1, 0), PortRotation.left, { 0.8, 0.8, 0, 1 } ) - local port10 = Port:new( GridPoint:new(0, -1), PortRotation.up, { 0.8, 0, 0.8, 1 } ) - local port11 = Port:new( GridPoint:new(2, 0), PortRotation.right, { 0.8, 0, 0, 1 } ) - local port12 = Port:new( GridPoint:new(1, 1), PortRotation.down, { 0, 0, 0.8, 1 } ) - local mecha3 = Mechanism:new( GridPoint:new(13, 5), GridPoint:new(2, 1), { port9, port10, port11, port12 }, {1, 0.5, 0.5, 1} ) - - local port13 = Port:new( GridPoint:new(-1, 0), PortRotation.left, { 0.8, 0.8, 0, 1 } ) - local port14 = Port:new( GridPoint:new(0, -1), PortRotation.up, { 0.8, 0, 0.8, 1 } ) - local port15 = Port:new( GridPoint:new(2, 0), PortRotation.right, { 0.8, 0, 0, 1 } ) - local port16 = Port:new( GridPoint:new(1, 1), PortRotation.down, { 0, 0, 0.8, 1 } ) - local mecha4 = Mechanism:new( GridPoint:new(16, 5), GridPoint:new(2, 1), { port13, port14, port15, port16 }, {0.5, 0.5, 1, 1} ) - Mechs = {mecha1, mecha2, mecha3, mecha4} + Selected = nil end function love.update( dt ) dt = dt - Mouse:update() - if Mouse.lastPressed and not Mouse.pressed then - local index = TableFind(Mechs, Mouse.point, function(mp, mech) - return mp.x >= mech.position.x and mp.x < mech.position.x + mech.size.x and - mp.y >= mech.position.y and mp.y < mech.position.y + mech.size.y + Mouse:update() + Input:update() + selectorUpdate() + + Selected = getSelected() + + if Selected ~= nil then + Selected.position = Mouse.point + if Mouse.lastPressed and not Mouse.pressed then + local intersects = TableHas( Mechs, Selected, function(this, other) + return this:intersectsOther( other ) + end + ) + if not intersects then + local mech = Selected:clone() + mech.position = GridPoint:new( Mouse.point.x, Mouse.point.y ) + mech.xcorner = GridPoint:new( Selected.xcorner.x, Selected.xcorner.y ) + table.insert( Mechs, mech ) + end end - ) - if index ~= nil then - Mechs[index]:rotateClockwise() + end + + if Input:actionReleased( 'rotate' ) then + if Selected ~= nil then + Selected:rotateClockwise() + else + local index = TableFind(Mechs, Mouse.point, function(mp, mech) + return mech:intersectsPoint( mp ) + end + ) + if index ~= nil then + Mechs[index]:rotateClockwise() + end end end end @@ -67,4 +72,8 @@ function love.draw() for _, mech in ipairs(Mechs) do mech:draw() end + + if Selected ~= nil then + Selected:draw() + end end diff --git a/mechanism.lua b/mechanism.lua index 01f755b..ec0d730 100644 --- a/mechanism.lua +++ b/mechanism.lua @@ -55,6 +55,7 @@ function Mechanism:new( position, size, ports, color ) return mechanism end +---@return Mechanism function Mechanism:clone() local ports = {} for _, port in ipairs(self.ports) do @@ -67,6 +68,25 @@ function Mechanism:clone() ports = ports, color = self.color } + setmetatable( mechanism, { __index = self } ) + + return mechanism +end + +function Mechanism:intersectsPoint( point ) + return point.x >= self.position.x and + point.x < self.position.x + self.size.x and + point.y >= self.position.y and + point.y < self.position.y + self.size.y +end + +function Mechanism:intersectsOther( mechanism ) + return mechanism.position.x + mechanism.size.x > self.position.x and + mechanism.position.x < + self.position.x + self.size.x and + mechanism.position.y + mechanism.size.y > self.position.y and + mechanism.position.y < self.position.y + self.size.y + end function Mechanism:rotateClockwise() diff --git a/selector.lua b/selector.lua new file mode 100644 index 0000000..e55713c --- /dev/null +++ b/selector.lua @@ -0,0 +1,35 @@ +local port1 = Port:new( GridPoint:new(-1, 0), PortRotation.left, { 0.8, 0.8, 0, 1 } ) +local port2 = Port:new( GridPoint:new(0, -1), PortRotation.up, { 0.8, 0, 0.8, 1 } ) +local port3 = Port:new( GridPoint:new(3, 2), PortRotation.right, { 0.8, 0, 0, 1 } ) +local port4 = Port:new( GridPoint:new(2, 3), PortRotation.down, { 0, 0, 0.8, 1 } ) +local port5 = Port:new( GridPoint:new(2, 0), PortRotation.right, {0.8, 0.8, 0, 1} ) +local port6 = Port:new( GridPoint:new(0, 2), PortRotation.down, { 0.8, 0.4, 0.4, 1 } ) + +local mecha1 = Mechanism:new( GridPoint:new(5, 5), GridPoint:new(3, 3), { port1:clone(), port2:clone(), port3:clone(), port4:clone() }, {0.5, 0.5, 0.5, 1} ) + +local mecha2 = Mechanism:new( GridPoint:new(10, 5), GridPoint:new(2, 2), { port1:clone(), port2:clone(), port5:clone(), port6:clone() }, {0.5, 1, 0.5, 1} ) + +local mecha3 = Mechanism:new( GridPoint:new(13, 5), GridPoint:new(2, 1), { port1:clone(), port2:clone(), port5:clone() }, {1, 0.5, 0.5, 1} ) + +local mechs = { mecha1, mecha2, mecha3 } +local actions = { 'none', 'first', 'second', 'third' } + +local selected = 0 + +function selectorUpdate() + for index, action in ipairs(actions) do + if Input:actionReleased(action) then + selected = index - 1 + break + end + end +end + +---@return Mechanism|nil +function getSelected() + if selected > 0 then + return mechs[selected] + else + return nil + end +end