1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
local Liquid = {}
Liquid.__index = Liquid
local function buildWorldPolygonPoints(entity)
local points = {}
if not entity.polygon then
return points
end
for i, point in ipairs(entity.polygon) do
points[#points+1] = {
x = entity.x + point.x,
y = entity.y + point.y
}
end
return points
end
function Liquid:new(source)
local self = setmetatable({}, Liquid)
self.entity = source
self.x = source.x or 0
self.y = source.y or 0
self.width = source.width or 0
self.height = source.height or 0
self.shape = source.shape
self.polygon = source.polygon or {}
self.worldPolygon = buildWorldPolygonPoints(source)
self.properties = source.properties or {}
self.type = "liquid"
self.triangles = {}
local flat = {}
for _, p in ipairs(self.worldPolygon) do
table.insert(flat, p.x)
table.insert(flat, p.y)
end
if #flat >= 6 then
self.triangles = love.math.triangulate(flat)
end
return self
end
function Liquid:getWorldPolygon()
return self.worldPolygon
end
function Liquid:containsEntityFully(entity)
local corners = getEntityCorners(entity)
for _, c in ipairs(corners) do
if not self:containsPoint(c.x, c.y) then
return false
end
end
return true
end
function Liquid:containsPoint(px, py)
local points = self.worldPolygon
local count = #points
if count < 3 then return false end
local inside = false
local j = count
for i = 1, count do
local xi, yi = points[i].x, points[i].y
local xj, yj = points[j].x, points[j].y
local intersects = ((yi > py) ~= (yj > py))
and (px < (xj - xi) * (py - yi) / ((yj - yi) + 1e-9) + xi)
if intersects then
inside = not inside
end
j = i
end
return inside
end
function Liquid:containsEntity(entity)
if not entity then return false end
local ex = entity.x or 0
local ey = entity.y or 0
local ew = entity.width or 0
local eh = entity.height or 0
local sampleX = ex + ew * 0.5
local sampleY = ey + eh
return self:containsPoint(sampleX, sampleY)
end
function Liquid:update(dt)
end
return Liquid
|