2025-08-03 03:39:42 +03:00

71 lines
2.5 KiB
Lua

local Vec3 = require "lib/vec3"
local tree = require "lib/tree"
local EPSILON = 0.001
--- @class Camera
--- @field position Vec3
--- @field velocity Vec3
--- @field speed number
--- @field pixelsPerMeter integer
local camera = {
position = Vec3 {},
velocity = Vec3 {},
acceleration = 0.2,
speed = 5,
pixelsPerMeter = 100,
scale = 1
}
love.wheelmoved = function(x, y)
if camera.scale > 2 and y > 0 then return end;
if camera.scale < 0.5 and y < 0 then return end;
camera.scale = camera.scale + 0.1 * y
end
---@todo Отрефакторить и вынести кнопки управления в controls, не должно быть таких ужасных проверок
function camera:update(dt)
local ps = tree.instance().panning
if ps.delta:length() > 0 then
local worldDelta = ps.delta:scale(1 / (self.pixelsPerMeter * self.scale)):scale(dt):scale(self.speed)
self.velocity = self.velocity + worldDelta
elseif love.keyboard.isDown("w") or love.keyboard.isDown("a") or love.keyboard.isDown("s") or love.keyboard.isDown("d") then
local input = Vec3 {}
if love.keyboard.isDown("w") then input = input + Vec3({ 0, -1 }) end
if love.keyboard.isDown("a") then input = input + Vec3({ -1 }) end
if love.keyboard.isDown("s") then input = input + Vec3({ 0, 1 }) end
if love.keyboard.isDown("d") then input = input + Vec3({ 1 }) end
input = input:normalize() or Vec3 {}
self.velocity = self.velocity:add(input:scale(self.acceleration):scale(dt))
if self.velocity:length() > self.speed then self.velocity = self.velocity:normalize() * self.speed end
end
self.position = self.position + self.velocity
self.velocity = self.velocity -
self.velocity * 5 *
dt -- магическая формула, которая означает "экспоненциально замедлиться до нуля"
if self.velocity:length() < EPSILON then self.velocity = Vec3 {} end
end
function camera:attach()
local wc, hc = love.graphics.getWidth() / 2, love.graphics.getHeight() / 2
love.graphics.push()
love.graphics.translate(wc, hc)
love.graphics.scale(self.pixelsPerMeter * self.scale)
love.graphics.translate(-self.position.x, -self.position.y)
end
function camera:detach()
love.graphics.pop()
end
--- @return Camera
local function new()
return setmetatable({}, {
__index = camera
})
end
return { new = new }