summaryrefslogtreecommitdiff
path: root/objects/body.lua
blob: f819101950ea56e304060c2f128967d9e1f5dcd7 (plain)
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
local Body = {}
Body.__index = Body

function Body:new(shape, sizeA, sizeB, zoom)
    local obj = {
        shape = shape,
        r = (shape == "circle" and sizeA or nil),
        w = (shape == "rectangle" and sizeA or nil),
        h = (shape == "rectangle" and sizeB or nil),
        zoom = zoom or 1
    }

    setmetatable(obj, Body)

    return obj
end

function Body:collide(other, x1, y1, x2, y2)
    if self.shape == "circle" and other.shape == "circle" then
        -- circle to circle
        local dx = x2 - x1
        local dy = y2 - y1
        local distance = math.sqrt(dx * dx + dy * dy)
        return distance < (self.r + other.r)
    elseif self.shape == "rectangle" and other.shape == "rectangle" then
        -- rect to rect
        return x1 < x2 + other.w and x1 + self.w > x2 and y1 < y2 + other.h and y1 + self.h > y2
    elseif self.shape == "circle" and other.shape == "rectangle" then
        -- circle to rect
        local closestX = math.max(x2, math.min(x1, x2 + other.w))
        local closestY = math.max(y2, math.min(y1, y2 + other.h))
        local dx = x1 - closestX
        local dy = y1 - closestY
        return (dx * dx + dy * dy) < (self.r * self.r)
    elseif self.shape == "rectangle" and other.shape == "circle" then
        return other:collide(self, x2, y2, x1, y1)
    end

    return false
end

function Body:isMet(body, selfX, selfY, currentX, currentY, dv, dir)
    -- x,y should be the predicted next location of this body
    -- dv = speed * dt * direction
    local x, y
    if dir == Direction.LEFT or dir == Direction.RIGHT then
        x = currentX + dv
        y = currentY
    elseif dir == Direction.UP or dir == Direction.DOWN then
        x = currentX
        y = currentY + dv
    end

    return self:collide(body, selfX, selfY, x, y)
end

function Body:draw(x, y)
    if self.shape == "circle" then
        love.graphics.circle("fill", x, y, self.r)
    elseif self.shape == "rectangle" then
        love.graphics.rectangle("fill", x, y, self.w, self.h)
    end
end

function Body:drawSprite(spriteName, x, y, angle)
    local sprite = sprite.get(spriteName)
    local w, h = (self.shape == "circle" and self.r or self.w), (self.shape == "circle" and self.r or self.h)

    love.graphics.draw(sprite, x, y, angle,
        w / sprite:getWidth(),
        h / sprite:getHeight()
    )
end

function Body:drawQuad(sheet, index, x, y, angle)
    if self.shape == "circle" then
        local r = self.r
        local graphicR = r * self.zoom
        sprite.drawQuad(sheet, index, x - r, y - r, graphicR, graphicR, angle or 0)
    else
        local w, h = self.w, self.h
        local graphicW, graphicH = w * self.zoom, h * self.zoom
        sprite.drawQuad(sheet, index, x - w/2, y - h/2, graphicW, graphicH, angle or 0)
    end
end

return Body