Wpis z mikrobloga

✨️ Obserwuj #mirkoanonim
Co mógłbym poprawić w tym kodzie z naciskiem na optymalizacje? Nie znam się na programowaniu więc proszę ekspertów. Czytałem że jest bardzo dużo różnych algorytmów, ale nie wiem który jest najszybszy, nie wiem gdzie to sprawdzić. Co poza optymalizacjami jest do poprawy? Jak napisać do tego testy automatyczne?

Żeby to uruchomić należy pobrać https://love2d.org/
Zapisać poniższy kod do pliku main.lua, wkleić ten plik do nowo utworzonego folderu i przenieść ten folder na ikonę love.exe albo lovec.exe

lua
-- Polygon class definition
local Polygon = {}
Polygon._index = Polygon

function Polygon:init(...)
self.vertices = { ... }
self.flat = {}
for _, vertex in ipairs(self.vertices) do
table.insert(self.flat, vertex[1])
table.insert(self.flat, vertex[2])
end
end

function Polygon.new(...)
local instance = setmetatable({}, Polygon)
instance:init(...)
return instance
end

function Polygon:draw(...)
love.graphics.setColor(...)
love.graphics.polygon("line", self.flat)
end

function Polygon:move(dx, dy)
for i, point in ipairs(self.vertices) do
point[1] = point[1] + dx
point[2] = point[2] + dy
self.flat[i * 2 - 1] = point[1]
self.flat[i * 2] = point[2]
end
end

function Polygon:isPointInside(x, y)
local inside = false
local vertices = self.vertices
local pX, pY = vertices[#vertices][1], vertices[#vertices][2]
for i = 1, #vertices do
local x1, y1 = vertices[i][1], vertices[i][2]
if (y > math.min(pY, y1)) then
if (y <= math.max(pY, y1)) then
if (x <= math.max(pX, x1)) then
if (pY ~= y1) then
local xInter = (y - pY) * (x1 - pX) / (y1 - pY) + pX
if (pX == x1 or x <= xInter) then
inside = not inside
end
end
end
end
end
pX, pY = x1, y1
end
return inside
end

function Polygon:getDistanceFromPoly(poly)
local minDistance = math.huge
for _, point1 in ipairs(self.vertices) do
for _, point2 in ipairs(poly.vertices) do
local distance = math.sqrt((point1[1] - point2[1]) ^ 2 + (point1[2] - point2[2]) ^ 2)
minDistance = math.min(minDistance, distance)
end
end
return minDistance
end

function Polygon:isPolyInside(poly)
for _, vertex in ipairs(self.vertices) do
if poly:isPointInside(vertex[1], vertex[2]) then
return true
end
end
return false
end

-- Calculate the distance between a point and a line segment
function Polygon.pointLineSegmentDistance(p, v1, v2)
local x1, y1 = v1[1], v1[2]
local x2, y2 = v2[1], v2[2]
local x3, y3 = p[1], p[2]

local dx = x2 - x1
local dy = y2 - y1
local t = math.max(0, math.min(1, ((x3 - x1) * dx + (y3 - y1) * dy) / (dx * dx + dy * dy)))

local px = x1 + t * dx
local py = y1 + t * dy

return math.sqrt((x3 - px) ^ 2 + (y3 - py) ^ 2)
end

-- Calculate the distance between two polygons considering line segments
function Polygon:getDistanceFromPolySegment(poly)
local minDistance = math.huge

for _, point in ipairs(self.vertices) do
for i = 1, #poly.vertices do
local v1 = poly.vertices[i]
local v2 = poly.vertices[i % #poly.vertices + 1]
local distance = Polygon.pointLineSegmentDistance(point, v1, v2)
minDistance = math.min(minDistance, distance)
end
end

return minDistance
end

-- Define your polygons
local draggingPolygon = nil
local polygon1 = Polygon.new({ 100, 100 }, { 150, 200 }, { 200, 100 })
local polygon2 = Polygon.new({ 300, 300 }, { 350, 400 }, { 400, 300 })

-- Main game loop
function love.draw()
polygon1:draw(1, 0, 0)
polygon2:draw(0, 0, 1)
love.graphics.setColor(0, 1, 0) -- green
love.graphics.print("Is Poly Inside: " .. tostring(polygon1:isPolyInside(polygon2) or polygon2:isPolyInside(polygon1)), 10, 10)
love.graphics.print("Distance Vertex: " .. math.min(polygon1:getDistanceFromPoly(polygon2), polygon2:getDistanceFromPoly(polygon1)), 10, 25)
love.graphics.print("Distance Line Segment: " .. math.min(polygon1:getDistanceFromPolySegment(polygon2), polygon2:getDistanceFromPolySegment(polygon1)), 10, 40)
end

function love.mousepressed(x, y, button)
if button == 1 then -- left mouse button
if polygon1:isPointInside(x, y) then
draggingPolygon = polygon1
elseif polygon2:isPointInside(x, y) then
draggingPolygon = polygon2
end
end
end

function love.mousemoved(x, y, dx, dy)
if love.mouse.isDown(1) and draggingPolygon then -- left mouse button is down
-- Move the polygon being dragged
draggingPolygon:move(dx, dy)
end
end

-- Stop dragging the polygon on mouse release
function love.mousereleased(x, y, button)
if button == 1 then
draggingPolygon = nil -- Stop dragging the polygon
end
end

#programowanie #pytaniedoeksperta



· Akcje: Odpowiedz anonimowo · Więcej szczegółów
· Zaakceptował: Nighthuntero
· Autor wpisu pozostał anonimowy dzięki Mirko Anonim

mirkoanonim - ✨️ Obserwuj #mirkoanonim
Co mógłbym poprawić w tym kodzie z naciskiem n...
  • 3
  • Odpowiedz
Co mógłbym poprawić w tym kodzie z naciskiem na optymalizacje?


@mirko_anonim: czy działa wolno? Kod wygląda dobrze i jedyne co ma prawo działać wolno to biblioteka do pisania gier

Jak napisać do tego testy automatyczne?


Możesz przetestować kawałki kodu np funkcję getDistanceFromPolySegment albo isPointInside. Cały programów graficznych raczej nie testuje się automatycznie, bo jest to cholernie ciężkie
  • Odpowiedz
via mirko.proBOT
  • 0
✨️ Autor wpisu (OP): Trzeba zmienić Polygon._index na index z podwójnym podkreślnikiem, musiałem dać pojedynczy bo nie można było wysłać wiadomości, error z informacją o zamknięciu podkreślenia podwójnego.
poprawione wideo https://streamable.com/gyta8q


· Akcje: Odpowiedz anonimowo · Więcej szczegółów
· Zaakceptował: Nighthuntero
  • Odpowiedz
@mirko_anonim: starym trickiem lua'owym bylo zapisanie funkcji matematycznych w localach (local sqrt = math.sqrt, etc.), sa szybsze, ale to maly zysk

i ogolnie polygon1:getDistanceFromPoly(polygon2) i polygon2:getDistanceFromPoly(polygon1) to nie wyrzucaja tego samego?

polecam ci przerzucic sie na jakis system klas (SECS, middleclass) - chociaz niekonieczne, to ulatwiaja prace, ja osobiscie z ECSami wole pracowac

i do wykrywania kolizji polecam HardonCollider, chociaz jest juz tego troche wiecej, byleby nie box2d wbudowane
  • Odpowiedz