SCREEN = vec2(128, 128) _chunk_size = vec2(100, 100) _chunk_size:apply(function (v) assert(v % 2 == 0) end) _padding = (SCREEN - _chunk_size) / 2 _interpolate_step = 20 assert(_chunk_size.x < SCREEN.x and _chunk_size.y < SCREEN.y) Camera = {} Camera.__index = Camera function Camera:update() if self.transition_to ~= self.position then delta = (self.transition_to - self.position) snap_x = delta.x == 0 or abs(delta.x) < _interpolate_step snap_y = delta.y == 0 or abs(delta.y) < _interpolate_step if snap_x then self.position.x = self.transition_to.x else self.position.x += normalize_scalar(delta.x) * _interpolate_step end if snap_y then self.position.y = self.transition_to.y else self.position.y += normalize_scalar(delta.y) * _interpolate_step end return end assert(self.tracking.position) tracking_chunk = chunk_from(self.tracking.position) self.transition_to = (tracking_chunk * _chunk_size) - _padding end function chunk_from(position) return vec2(position / _chunk_size):apply(flr) end function from_chunk(chunk) return chunk * _chunk_size end function Camera:render(entity) screen_position = (entity.sprite_position or entity.position) - self.position entity:render(screen_position) end function Camera:new(tracking) cam = setmetatable({ transition_to = from_chunk(chunk_from(tracking.position)), tracking = tracking }, Camera) cam.position = cam.transition_to AddUpdateHook(function (dt) cam:update() end) return cam end