| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- View = class()
- local g = love.graphics
- function View:init()
- self.x = 0
- self.y = 0
- self.width = 800
- self.height = 600
- self.xmin = 0
- self.ymin = 0
- self.xmax = self.width
- self.ymax = self.height
- self.frame = {}
- self.frame.x = 0
- self.frame.y = 0
- self.frame.width = love.window.getWidth()
- self.frame.height = love.window.getHeight()
- self.draws = {}
- self.guis = {}
- self.effects = {}
- self.target = nil
- self:resize()
- self.prevx = 0
- self.prevy = 0
- self.prevscale = self.scale
- self.shake = 0
- end
- function View:update()
- self.prevx = self.x
- self.prevy = self.y
- self.prevscale = self.scale
-
- self:follow()
- self:contain()
- self.shake = math.lerp(self.shake, 0, 8 * tickRate)
- table.sort(self.draws, function(a, b)
- return a.depth > b.depth
- end)
- end
- function View:draw()
- local w, h = g.getDimensions()
- self:worldPush()
- self.sourceCanvas:clear()
- self.targetCanvas:clear()
- self.sourceCanvas:renderTo(function()
- for i = 1, #self.draws do self.draws[i]:draw() end
- end)
- g.pop()
- for i = 1, #self.effects do
- g.setColor(255, 255, 255)
- if self.effects[i].applyEffect then
- self.effects[i]:applyEffect(self.sourceCanvas, self.targetCanvas)
- else
- g.setShader(self.effects[i].shader)
- g.setCanvas(self.targetCanvas)
- g.draw(self.sourceCanvas)
- end
- g.setCanvas()
- g.setShader()
- self.sourceCanvas, self.targetCanvas = self.targetCanvas, self.sourceCanvas
- end
- g.setColor(255, 255, 255)
- g.draw(self.sourceCanvas)
- g.push()
- g.translate(self.frame.x, self.frame.y)
- for i = 1, #self.guis do self.guis[i]:gui() end
-
- g.pop()
- g.setColor(0, 0, 0, 255)
- g.rectangle('fill', 0, 0, w, self.frame.y)
- g.rectangle('fill', 0, 0, self.frame.x, h)
- g.rectangle('fill', 0, self.frame.y + self.frame.height, w, h - (self.frame.y + self.frame.height))
- g.rectangle('fill', self.frame.x + self.frame.width, 0, w - (self.frame.x + self.frame.width), h)
- end
- function View:resize()
- local w, h = love.graphics.getDimensions()
- self.frame.x, self.frame.y, self.frame.width, self.frame.height = 0, 0, self.width, self.height
- if (self.width / self.height) > (w / h) then
- self.scale = w / self.width
- local margin = math.max(math.round(((h - w * (self.height / self.width)) / 2)), 0)
- self.frame.y = margin
- self.frame.height = h - 2 * margin
- self.frame.width = w
- else
- self.scale = h / self.height
- local margin = math.max(math.round(((w - h * (self.width / self.height)) / 2)), 0)
- self.frame.x = margin
- self.frame.width = w - 2 * margin
- self.frame.height = h
- end
- self.sourceCanvas = love.graphics.newCanvas(w, h)
- self.targetCanvas = love.graphics.newCanvas(w, h)
- end
- function View:register(x, action)
- action = action or 'draw'
- if action == 'draw' then
- table.insert(self.draws, x)
- x.depth = x.depth or 0
- elseif action == 'gui' then
- table.insert(self.guis, x)
- elseif action == 'effect' then
- table.insert(self.effects, x)
- end
- end
- function View:unregister(x)
- if x.draw then
- for i = 1, #self.draws do
- if self.draws[i] == x then table.remove(self.draws, i) return end
- end
- end
- if x.gui then
- for i = 1, #self.guis do
- if self.guis[i] == x then table.remove(self.guis, i) return end
- end
- end
- for i = 1, #self.effects do
- if self.effects[i] == x then table.remove(self.effects, i) return end
- end
- end
- function View:convertZ(z)
- return (.8 * z) ^ (1 + (.0008 * z))
- end
- function View:three(x, y, z)
- local sx, sy = math.lerp(self.prevx, self.x, tickDelta / tickRate), math.lerp(self.prevy, self.y, tickDelta / tickRate)
- z = self:convertZ(z)
- return x - (z * ((sx + self.width / 2 - x) / 500)), y - (z * ((sy + self.height / 2 - y) / 500))
- end
- function View:threeDepth(x, y, z)
- return math.clamp(math.distance(x, y, self.x + self.width / 2, self.y + self.height / 2) * self.scale - 1000 - z, -4096, -16)
- end
- function View:contain()
- self.x = math.clamp(self.x, 0, self.xmax - self.width)
- self.y = math.clamp(self.y, 0, self.ymax - self.height)
- end
- function View:follow()
- if not self.target then return end
- local dis, dir = math.vector(self.target.x, self.target.y, self:worldMouseX(), self:worldMouseY())
- local margin = 0.8
-
- dis = dis / 2
-
- self.x = math.lerp(self.x, self.target.x + math.dx(dis, dir) - (self.width / 2), math.min(25 * tickRate, 1))
- self.y = math.lerp(self.y, self.target.y + math.dy(dis, dir) - (self.height / 2), math.min(25 * tickRate, 1))
-
- self.x = math.clamp(self.x, self.target.x - (self.width * margin), self.target.x + (self.width * margin) - self.width)
- self.y = math.clamp(self.y, self.target.y - (self.height * margin), self.target.y + (self.height * margin) - self.height)
- end
- function View:worldPoint(x, y)
- x = math.round(((x - self.frame.x) / self.scale) + self.x)
- if y then y = math.round(((y - self.frame.y) / self.scale) + self.y) end
- return x, y
- end
- function View:worldMouseX()
- return math.round(((love.mouse.getX() - self.frame.x) / self.scale) + self.x)
- end
- function View:worldMouseY()
- return math.round(((love.mouse.getY() - self.frame.y) / self.scale) + self.y)
- end
- function View:frameMouseX()
- return love.mouse.getX() - self.frame.x
- end
- function View:frameMouseY()
- return love.mouse.getY() - self.frame.y
- end
- function View:screenshake(amount)
- if self.shake > amount then self.shake = self.shake + (amount / 2) end
- self.shake = amount
- end
- function View:worldPush()
- local x, y, s = unpack(table.interpolate({self.prevx, self.prevy, self.prevscale}, {self.x, self.y, self.scale}, tickDelta / tickRate))
- local shakex = 1 - (2 * love.math.noise(self.shake + x + tickDelta))
- local shakey = 1 - (2 * love.math.noise(self.shake + y + tickDelta))
- x = x + (shakex * self.shake)
- y = y + (shakey * self.shake)
- g.push()
- g.translate(self.frame.x, self.frame.y)
- g.scale(s)
- g.translate(-x, -y)
- end
|