summaryrefslogtreecommitdiff
path: root/camera.lua
blob: bb6918352ff0cf6643cff2f30d0e7b8f1c4f9a9c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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 = 22
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

_cull_factor = 1/4
function Camera:render(entity)
    screen_position = (entity.sprite_position or entity.position) - self.position
    if DEBUG and entity.collision then 
        entity_collision_box = { top_left = screen_position + entity.collision_bounds.top_left, bottom_right = screen_position + entity.collision_bounds.bottom_right }
        -- entity_collision_box = { top_left = screen_position, bottom_right = screen_position + vec2(8, 8)}
        -- entity_collision_box = entity_collision_bounds
        rect(entity_collision_box.top_left.x, entity_collision_box.top_left.y, entity_collision_box.bottom_right.x, entity_collision_box.bottom_right.y, 5)
    end
    if screen_position:in_bounds(SCREEN * -_cull_factor, SCREEN * (1 + _cull_factor)) then
        entity:render(screen_position)
    end
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