local DEFAULT_CAMERA_SMOOTHING = 30 local SHAKE_NOISE_SPEED = 15 Cam = {} Cam.__index = Cam function Cam.new(x, y) local self = setmetatable({}, Cam) self.x = x or 0 self.y = y or 0 self.realx = self.x self.realy = self.y self.zoom = 1 self.smoothing = DEFAULT_CAMERA_SMOOTHING self.shake_strength = 0 self.shake_timer_max = 0 self.shake_timer = 0 self.shake_direction = 0 self.shake_damp = EASING_FUNCTIONS.Lerp self.shake_noise = lmath.noise return self end function Cam:update(dt) self.realx = dlerp(self.realx, self.x, self.smoothing * dt) self.realy = dlerp(self.realy, self.y, self.smoothing * dt) self.shake_timer = self.shake_timer - dt if self.shake_timer < 0 then self.shake_strength = 0 end end local active_cam = Cam.new() function get_active_camera() return active_cam end function Cam:shake(strength, time, angle) if strength < self.shake_strength then return end self.shake_direction = angle -- if nil we just ignore it and randomize if self.shake_direction then self.shake_direction = math.rad(self.shake_direction) end self.noise_seed = lmath.random() * 1000 self.shake_strength = strength self.shake_timer = time self.shake_timer_max = time end function set_active_camera(new_cam) active_cam = new_cam end function Cam:getshake() if self.shake_timer < 0 then return 0, 0 end local shakex, shakey = 0, 0 if self.shake_direction then local size = self.shake_noise( self.shake_timer * SHAKE_NOISE_SPEED + self.noise_seed) shakex = math.cos(self.shake_direction) * size shakey = math.sin(self.shake_direction) * size else shakex = self.shake_noise( self.shake_timer * SHAKE_NOISE_SPEED + self.noise_seed) shakey = self.shake_noise( -- 100 is a magic number to offset the x and y noise (so its not just a diagonal shake) self.shake_timer * SHAKE_NOISE_SPEED + self.noise_seed, 100) end local anim = self.shake_timer / self.shake_timer_max local strength = self.shake_strength * self.shake_damp(0, 1, anim) shakex = shakex * strength shakey = shakey * strength return shakex, shakey end function use_camera_transform() local w, h = SCR_WIDTH / 2, SCR_HEIGHT / 2 lg.scale(active_cam.zoom) local ox, oy = -active_cam.realx + w / active_cam.zoom, -active_cam.realy + h / active_cam.zoom local shakex, shakey = active_cam:getshake() lg.translate( round(ox + shakex), round(oy + shakey)) end