Skip to content

Instantly share code, notes, and snippets.

@dvdfu
Created April 18, 2017 23:24
Show Gist options
  • Save dvdfu/fab4213ddc66e119bb5405ebf71038e1 to your computer and use it in GitHub Desktop.
Save dvdfu/fab4213ddc66e119bb5405ebf71038e1 to your computer and use it in GitHub Desktop.
local Class = require 'modules.middleclass.middleclass'
local Timer = require 'modules.hump.timer'
local Vector = require 'modules.hump.vector'
local Const = require 'src.const'
local Util = require 'src.util'
local Camera = Class('Camera')
function Camera:initialize(settings)
settings = settings or {}
self.damping = settings.damping or 1 -- camera movement damping
self.bounds = settings.bounds or Vector(640, 640) -- map boundaries
self.buffer = settings.buffer or Vector() -- camera locking buffer
self.focii = settings.focii or {} -- array of focal points in level
self.target = nil
self.pos = Vector()
self.timer = Timer.new()
self.shakeVec = Vector()
if self.bounds.x < Const.SCREEN_WIDTH then self.bounds.x = Const.SCREEN_WIDTH end
if self.bounds.y < Const.SCREEN_HEIGHT then self.bounds.y = Const.SCREEN_HEIGHT end
end
function Camera:update(dt)
self.timer:update(dt)
-- restrain camera to map boundaries
local target = self.target:getPointVec()
local buffer = self.buffer
for _, focus in pairs(self.focii) do
if focus:isNear(target) then
target = focus.pos
buffer = Vector() -- cancel buffering if targeting focus
break
end
end
local screen = Vector(Const.SCREEN_WIDTH, Const.SCREEN_HEIGHT) / 2 - buffer
target.x = Util.clamp(target.x, screen.x, self.bounds.x - screen.x)
target.y = Util.clamp(target.y, screen.y, self.bounds.y - screen.y)
local delta = target - self.pos
-- camera movement buffer
if delta.x > buffer.x then
delta.x = delta.x - buffer.x
elseif delta.x < -buffer.x then
delta.x = delta.x + buffer.x
else
delta.x = 0
end
if delta.y > buffer.y then
delta.y = delta.y - buffer.y
elseif delta.y < -buffer.y then
delta.y = delta.y + buffer.y
else
delta.y = 0
end
-- damp camera movement if non-trivial
if delta:len2() > 0.1 then
delta = delta / self.damping
end
self.pos = self.pos + delta * dt
love.audio.setPosition(self.pos.x, self.pos.y, 0)
-- love.audio.setVelocity(delta.x, delta.y, 0)
end
function Camera:follow(target)
self.target = target
end
function Camera:lookAt(target)
self:follow(target)
-- restrain camera to map boundaries
local target = self.target:getPointVec()
local screen = Vector(Const.SCREEN_WIDTH, Const.SCREEN_HEIGHT) / 2
target.x = Util.clamp(target.x, screen.x, self.bounds.x - screen.x)
target.y = Util.clamp(target.y, screen.y, self.bounds.y - screen.y)
self.pos = target
end
function Camera:shake(shake, direction)
shake = shake or 4
direction = direction or math.random(math.pi * 2)
self.shakeVec = self.shakeVec + Vector(shake, 0):rotated(-direction)
self.timer:clear()
self.timer:tween(30, self.shakeVec, {
x = 0,
y = 0
}, 'out-elastic')
end
function Camera:getPosition()
return self.pos + self.shakeVec
end
function Camera:draw(callback)
local halfScreen = Vector(Const.SCREEN_WIDTH, Const.SCREEN_HEIGHT) / 2
local translation = halfScreen - self:getPosition()
love.graphics.push()
love.graphics.translate(Util.round(translation.x), Util.round(translation.y))
callback()
love.graphics.pop()
end
return Camera
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment