跳转至内容

25. 简化,摄影机,TRS

3.21,继续手写。

Camera

矩阵运算顺序是从下往上读的,简单的 TRS 变换(Translate,Rotate,Scale)如下:

  1. 把目标点移到原点 (0,0)
  2. 做旋转和缩放
  3. 将原点移回中心点 (cx, cy)
lua
local Camera = Object:extend()

function Camera:new(x, y, zoom, rot, smoother)
    self.x = x or love.graphics.getWidth() / 2
    self.y = y or love.graphics.getHeight() / 2
    self.scale = zoom or 1
    self.rot = rot or 0
    self.smoother = smoother or Camera.smooth.none
end

function Camera:attach(x, y, w, h)
    x = x or 0
    y = y or 0
    w = w or love.graphics.getWidth()
    h = h or love.graphics.getHeight()
    local cx, cy = x + w / 2, y + h / 2

    love.graphics.push()
    love.graphics.translate(cx, cy)
    love.graphics.scale(self.scale)
    love.graphics.rotate(self.rot)
    love.graphics.translate(-self.x, -self.y)
end

function Camera:detach()
    love.graphics.pop()
end

return Camera
lua
function Camera:position()
    return self.x, self.y
end

function Camera:lookAt(x, y)
    self.x, self.y = x, y
    return self
end

function Camera:zoomTo(zoom)
    self.scale = zoom
    return self
end

function Camera:rotateTo(phi)
    self.rot = phi
    return self
end

function Camera:move(dx, dy)
    self.x, self.y = self.x + dx, self.y + dy
    return self
end

function Camera:zoom(mul)
    self.scale = self.scale * mul
    return self
end

function Camera:rotate(phi)
    self.rot = self.rot + phi
    return self
end
lua
Camera.smooth = {
    none = function()
        return function(dt, dx, dy)
            return dx, dy
        end
    end,

    linear = function(speed)
        speed = speed or 100
        return function(dt, dx, dy)
            local dist = math.sqrt(dx * dx + dy * dy)
            local dts = math.min(speed * dt, dist)
            if dist > 0 then
                dx, dy = dx / dist, dy / dist
            end
            return dx * dts, dy * dts
        end
    end,

    damped = function(stiffness)
        stiffness = stiffness or 5
        return function(dt, dx, dy)
            local dts = dt * stiffness
            return dx * dts, dy * dts
        end
    end
}

function Camera:lockPosition(dt, x, y, stiffness)
    stiffness = stiffness or self.stiffness
    local dx, dy = self.smoother(dt, x - self.x, y - self.y)
    return self:move(dx, dy)
end