Created
April 18, 2017 23:24
-
-
Save dvdfu/fab4213ddc66e119bb5405ebf71038e1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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