| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- View = class()
- local g = love.graphics
- function View:init()
- self.x = 0
- self.y = 0
- self.width = 1067
- 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.graphics.getWidth()
- self.frame.height = love.graphics.getHeight()
- self.vx = 0
- self.vy = 0
- self.viewId = 0
- self.draws = {}
- self.guis = {}
- self.effects = {}
- self.toRemove = {}
- self.target = nil
- self:resize()
- self.prevx = 0
- self.prevy = 0
- self.prevscale = self.scale
- self.shake = 0
- ctx.event:on('view.register', function(data)
- self:register(data.object, data.mode)
- end)
- ctx.event:on('view.unregister', function(data)
- self:unregister(data.object)
- end)
- end
- function View:update()
- self.prevx = self.x
- self.prevy = self.y
- self.prevscale = self.scale
- local mx = love.mouse.getX()
- if mx < self.frame.x + (.02 * self.frame.width) then
- self.vx = -1000
- elseif mx > self.frame.x + (.98 * self.frame.width) then
- self.vx = 1000
- end
- self.x = self.x + self.vx * ls.tickrate
- self.y = self.y + self.vy * ls.tickrate
- self:contain()
- self.shake = math.lerp(self.shake, 0, 8 * ls.tickrate)
- while #self.toRemove > 0 do
- local x = self.toRemove[1]
- if x.draw then
- for i = 1, #self.draws do
- if self.draws[i] == x then table.remove(self.draws, i) i = #self.draws + 1 end
- end
- end
- if x.gui then
- for i = 1, #self.guis do
- if self.guis[i] == x then table.remove(self.guis, i) i = #self.guis + 1 end
- end
- end
- for i = 1, #self.effects do
- if self.effects[i] == x then table.remove(self.effects, i) i = #self.effects + 1 end
- end
- table.remove(self.toRemove, 1)
- end
- table.sort(self.draws, function(a, b)
- return a.depth == b.depth and a.viewId < b.viewId or a.depth > b.depth
- end)
- end
- function View:draw()
- local w, h = g.getDimensions()
- local source, target = self.sourceCanvas, self.targetCanvas
- self:worldPush()
- g.setCanvas(source)
- for i = 1, #self.draws do self.draws[i]:draw() end
- g.setCanvas()
- g.pop()
- for i = 1, #self.effects do
- local effect = self.effects[i]
- if effect.active then
- g.setColor(255, 255, 255)
- if effect.applyEffect then
- effect:applyEffect(source, target)
- else
- g.setShader(effect.shader)
- g.setCanvas(target)
- g.draw(source)
- end
- g.setShader()
- source, target = target, source
- end
- end
- g.setCanvas()
- g.setColor(255, 255, 255)
- g.draw(source)
- g.push()
- local fr = self.frame
- local fx, fy, fw, fh = fr.x, fr.y, fr.width, fr.height
- g.translate(fx, fy)
- for i = 1, #self.guis do self.guis[i]:gui() end
- g.pop()
- g.setColor(0, 0, 0)
- g.rectangle('fill', 0, 0, w, fy)
- g.rectangle('fill', 0, 0, fx, h)
- g.rectangle('fill', 0, fy + fh, w, h - (fy + fh))
- g.rectangle('fill', fx + fw, 0, w - (fx + fw), h)
- if false and love.keyboard.isDown('`') then
- local stats = g.getStats()
- local str = 'fps: ' .. love.timer.getFPS() .. '\ndraw calls: ' .. stats.drawcalls .. '\ncanvas switches: ' .. stats.canvasswitches .. '\nvram: ' .. math.round((stats.texturememory / 1024) / 1024) .. 'MB\nimages: ' .. stats.images .. '\ncanvases: ' .. stats.canvases .. '\nfonts: ' .. stats.fonts
- str = str .. '\nminenemyrate: ' .. ctx.units.minEnemyRate .. '\nmaxenemyrate: ' .. ctx.units.maxEnemyRate
- g.setColor(255, 255, 255)
- g.setFont('mesmerize', 10)
- g.printShadow(str, 0, 0)
- end
- end
- function View:resize()
- local w, h = love.graphics.getDimensions()
- local ratio = w / h
- 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)
- x.viewId = self.viewId
- 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
- self.viewId = self.viewId + 1
- end
- function View:unregister(x)
- table.insert(self.toRemove, x)
- 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, ls.accum / ls.tickrate), math.lerp(self.prevy, self.y, ls.accum / ls.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: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:screenPoint(x, y)
- local vx, vy = math.lerp(self.prevx, self.x, ls.accum / ls.tickrate), math.lerp(self.prevy, self.y, ls.accum / ls.tickrate)
- x = (x - vx) * self.scale
- if y then y = (y - vy) * self.scale 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}, ls.accum / ls.tickrate))
- local shakex = 1 - (2 * love.math.noise(self.shake + x + ls.accum))
- local shakey = 1 - (2 * love.math.noise(self.shake + y + ls.accum))
- 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
- function View:guiPush()
- g.push()
- g.translate(self.frame.x, self.frame.y)
- end
|