User:Darkfrei/example functions

Prints table

print('{' ..table.concat(line,",")..'},')

Draw grid

function draw_grid ()
	local grid_size = 20
	love.graphics.setLineWidth (1)
	love.graphics.setColor(0.25,0.25,0.25)
	local width, height = love.graphics.getDimensions( )
	for x = grid_size, width-1, grid_size do
		love.graphics.line(x, 0, x, height)
	end
	for y = grid_size, height-1, grid_size do
		love.graphics.line(0, y, width, y)
	end
end

Draw mouse position

function draw_mouse ()
	local mx, my = love.mouse.getPosition ()
	local text = mx..' '..my
	local font = love.graphics.getFont()
	local w = font:getWidth(text)
	local h = font:getHeight()
	love.graphics.setColor(0,0,0)
	love.graphics.rectangle('fill', mx, my-h, w, h)
	love.graphics.setColor(1,1,1)
	love.graphics.print(mx..' '..my,mx,my-h)
end

Beep

Define it:

local rate = 44100
local length = 1/32
local tone = 440 -- Hz
local p = math.floor(rate/tone) -- 128
local soundData = love.sound.newSoundData(length*rate, rate, 16, 1)
for i=0, length*rate-1 do soundData:setSample(i, i%p>p/2 and 1 or -1) end
local source = love.audio.newSource(soundData)
local function beep() source:play() end

Call it:

beep()

Point in area

function is_in_area (mx,my, x,y,w,h) -- mouse position and rectangle
	if (mx > x) and (mx < (x + w)) and
	   (my > y) and (my < (y + h)) then
		return true
	end
end


Is value in list

function is_value_in_list (value, list)
	for i, v in pairs (list) do
		if v == value then
			return true
		end
	end
end


Normalization and multiplication

Set magnitude to this vector:

function normul (x, y, factor) -- normalization and multiplication
	local d = (x*x+y*y)^0.5
	factor= factor or 1
	return factor*x/d, factor*y/d
end


Evaluate a point from any amount of control points

local function evaluate (curve, t)
	local ccpc = curve:getControlPointCount( )
	if ccpc > 1 then
		return curve:evaluate(t)
	elseif ccpc == 1 then
		return curve:getControlPoint(1)
	else
		return 0, 0
	end
end


Split string with separator

local function  split (string, separator)
	local tabl = {}
	for str in string.gmatch(string, "[^"..separator.."]+") do
		table.insert (tabl, str)
	end
	return tabl
end
--split ("123#456", "#") -- results: {"123", "456"}

Split string to list of symbols

local function  split2 (string)
	local tabl = {}
	string:gsub(".", function(c) table.insert(tabl, tonumber (c)) end)
	return tabl
end
--split2 ("123") -- results: {1, 2, 3}

Push rectangle from line

(made with chatGPT Feb 13 2023)

function pushRectOutOfLine(x, y, w, h, x1, y1, x2, y2)
  -- Вычисляем вектор направления линии
  local lineDirX = x2 - x1
  local lineDirY = y2 - y1
  
  -- Нормализуем вектор направления линии
  local lineLength = math.sqrt(lineDirX^2 + lineDirY^2)
  lineDirX = lineDirX / lineLength
  lineDirY = lineDirY / lineLength
  
  -- Вычисляем вектор от начальной точки линии до прямоугольника
  local toRectX = x - x1
  local toRectY = y - y1
  
  -- Проекция вектора от начальной точки линии до прямоугольника на вектор направления линии
  local dot = toRectX * lineDirX + toRectY * lineDirY
  
  -- Находим ближайшую точку на линии
  local nearestX, nearestY
  if dot <= 0 then
    nearestX, nearestY = x1, y1
  elseif dot >= lineLength then
    nearestX, nearestY = x2, y2
  else
    nearestX = x1 + dot * lineDirX
    nearestY = y1 + dot * lineDirY
  end
  
  -- Вычисляем вектор от ближайшей точки на линии до прямоугольника
  local toRectX = x - nearestX
  local toRectY = y - nearestY
  
  -- Если прямоугольник пересекает линию
  if math.abs(toRectX) < w/2 and math.abs(toRectY) < h/2 then
    -- Вычисляем вектор выталкивания
    local pushX = (w/2 - math.abs(toRectX)) * math.sign(toRectX)
    local pushY = (h/2 - math.abs(toRectY)) * math.sign(toRectY)
    
    -- Возвращаем вектор выталкивания и нормаль линии
    return pushX, pushY, lineDirX, lineDirY
  end
  
  return 0, 0, 0, 0
end

Short version:

function PushOutRectangleFromLine(x, y, w, h, x1, y1, x2, y2)
  local toRectX, toRectY = x - x1, y - y1
  local lineDirectionX, lineDirectionY = x2 - x1, y2 - y1
  local lineLength = math.sqrt(lineDirectionX^2 + lineDirectionY^2)
  lineDirectionX, lineDirectionY = lineDirectionX / lineLength, lineDirectionY / lineLength
  local dotProduct = toRectX * lineDirectionX + toRectY * lineDirectionY
  local closestPointX, closestPointY = x1 + dotProduct * lineDirectionX, y1 + dotProduct * lineDirectionY
  local distanceX, distanceY = x - closestPointX, y - closestPointY
  local intersectX, intersectY = closestPointX, closestPointY
  
  if dotProduct < 0 then
    intersectX, intersectY = x1, y1
    distanceX, distanceY = x - x1, y - y1
  elseif dotProduct > lineLength then
    intersectX, intersectY = x2, y2
    distanceX, distanceY = x - x2, y - y2
  end
  
  if math.abs(distanceX) < w / 2 and math.abs(distanceY) < h / 2 then
    local pushX, pushY = 0, 0
    
    if w / 2 - math.abs(distanceX) < h / 2 - math.abs(distanceY) then
      pushX = math.sign(distanceX) * (w / 2 - math.abs(distanceX))
    else
      pushY = math.sign(distanceY) * (h / 2 - math.abs(distanceY))
    end
    
    return pushX, pushY
  end
  
  return 0, 0
end

(fixed normal)

function PushOutRectangleFromLine(x, y, w, h, x1, y1, x2, y2)
    local toRectX, toRectY = x - x1, y - y1
    local lineLength = math.sqrt((x2 - x1) ^ 2 + (y2 - y1) ^ 2)
    local normalX, normalY = (y2 - y1) / lineLength, -(x2 - x1) / lineLength
    local dot = toRectX * normalX + toRectY * normalY
    local intersectX, intersectY = x - dot * normalX, y - dot * normalY

    if intersectX < x then
        intersectX = x
    elseif intersectX > x + w then
        intersectX = x + w
    end

    if intersectY < y then
        intersectY = y
    elseif intersectY > y + h then
        intersectY = y + h
    end

    local distance = (toRectX - intersectX) * normalX + (toRectY - intersectY) * normalY

    if distance < 0 then
        intersectX = intersectX + distance * normalX
        intersectY = intersectY + distance * normalY
    end

    return intersectX, intersectY, normalX, normalY
end