view.lua 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. View = class()
  2. local g = love.graphics
  3. function View:init()
  4. self.x = 0
  5. self.y = 0
  6. self.width = 1067
  7. self.height = 600
  8. self.xmin = 0
  9. self.ymin = 0
  10. self.xmax = self.width
  11. self.ymax = self.height
  12. self.frame = {}
  13. self.frame.x = 0
  14. self.frame.y = 0
  15. self.frame.width = love.graphics.getWidth()
  16. self.frame.height = love.graphics.getHeight()
  17. self.vx = 0
  18. self.vy = 0
  19. self.viewId = 0
  20. self.draws = {}
  21. self.guis = {}
  22. self.effects = {}
  23. self.toRemove = {}
  24. self.target = nil
  25. self:resize()
  26. self.prevx = 0
  27. self.prevy = 0
  28. self.prevscale = self.scale
  29. self.shake = 0
  30. ctx.event:on('view.register', function(data)
  31. self:register(data.object, data.mode)
  32. end)
  33. ctx.event:on('view.unregister', function(data)
  34. self:unregister(data.object)
  35. end)
  36. end
  37. function View:update()
  38. self.prevx = self.x
  39. self.prevy = self.y
  40. self.prevscale = self.scale
  41. local mx = love.mouse.getX()
  42. if mx < self.frame.x + (.02 * self.frame.width) then
  43. self.vx = -1000
  44. elseif mx > self.frame.x + (.98 * self.frame.width) then
  45. self.vx = 1000
  46. end
  47. self.x = self.x + self.vx * ls.tickrate
  48. self.y = self.y + self.vy * ls.tickrate
  49. self:contain()
  50. self.shake = math.lerp(self.shake, 0, 8 * ls.tickrate)
  51. while #self.toRemove > 0 do
  52. local x = self.toRemove[1]
  53. if x.draw then
  54. for i = 1, #self.draws do
  55. if self.draws[i] == x then table.remove(self.draws, i) i = #self.draws + 1 end
  56. end
  57. end
  58. if x.gui then
  59. for i = 1, #self.guis do
  60. if self.guis[i] == x then table.remove(self.guis, i) i = #self.guis + 1 end
  61. end
  62. end
  63. for i = 1, #self.effects do
  64. if self.effects[i] == x then table.remove(self.effects, i) i = #self.effects + 1 end
  65. end
  66. table.remove(self.toRemove, 1)
  67. end
  68. table.sort(self.draws, function(a, b)
  69. return a.depth == b.depth and a.viewId < b.viewId or a.depth > b.depth
  70. end)
  71. end
  72. function View:draw()
  73. local w, h = g.getDimensions()
  74. local source, target = self.sourceCanvas, self.targetCanvas
  75. self:worldPush()
  76. g.setCanvas(source)
  77. for i = 1, #self.draws do self.draws[i]:draw() end
  78. g.setCanvas()
  79. g.pop()
  80. for i = 1, #self.effects do
  81. local effect = self.effects[i]
  82. if effect.active then
  83. g.setColor(255, 255, 255)
  84. if effect.applyEffect then
  85. effect:applyEffect(source, target)
  86. else
  87. g.setShader(effect.shader)
  88. g.setCanvas(target)
  89. g.draw(source)
  90. end
  91. g.setShader()
  92. source, target = target, source
  93. end
  94. end
  95. g.setCanvas()
  96. g.setColor(255, 255, 255)
  97. g.draw(source)
  98. g.push()
  99. local fr = self.frame
  100. local fx, fy, fw, fh = fr.x, fr.y, fr.width, fr.height
  101. g.translate(fx, fy)
  102. for i = 1, #self.guis do self.guis[i]:gui() end
  103. g.pop()
  104. g.setColor(0, 0, 0)
  105. g.rectangle('fill', 0, 0, w, fy)
  106. g.rectangle('fill', 0, 0, fx, h)
  107. g.rectangle('fill', 0, fy + fh, w, h - (fy + fh))
  108. g.rectangle('fill', fx + fw, 0, w - (fx + fw), h)
  109. if false and love.keyboard.isDown('`') then
  110. local stats = g.getStats()
  111. 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
  112. str = str .. '\nminenemyrate: ' .. ctx.units.minEnemyRate .. '\nmaxenemyrate: ' .. ctx.units.maxEnemyRate
  113. g.setColor(255, 255, 255)
  114. g.setFont('mesmerize', 10)
  115. g.printShadow(str, 0, 0)
  116. end
  117. end
  118. function View:resize()
  119. local w, h = love.graphics.getDimensions()
  120. local ratio = w / h
  121. self.frame.x, self.frame.y, self.frame.width, self.frame.height = 0, 0, self.width, self.height
  122. if (self.width / self.height) > (w / h) then
  123. self.scale = w / self.width
  124. local margin = math.max(math.round(((h - w * (self.height / self.width)) / 2)), 0)
  125. self.frame.y = margin
  126. self.frame.height = h - 2 * margin
  127. self.frame.width = w
  128. else
  129. self.scale = h / self.height
  130. local margin = math.max(math.round(((w - h * (self.width / self.height)) / 2)), 0)
  131. self.frame.x = margin
  132. self.frame.width = w - 2 * margin
  133. self.frame.height = h
  134. end
  135. self.sourceCanvas = love.graphics.newCanvas(w, h)
  136. self.targetCanvas = love.graphics.newCanvas(w, h)
  137. end
  138. function View:register(x, action)
  139. x.viewId = self.viewId
  140. action = action or 'draw'
  141. if action == 'draw' then
  142. table.insert(self.draws, x)
  143. x.depth = x.depth or 0
  144. elseif action == 'gui' then
  145. table.insert(self.guis, x)
  146. elseif action == 'effect' then
  147. table.insert(self.effects, x)
  148. end
  149. self.viewId = self.viewId + 1
  150. end
  151. function View:unregister(x)
  152. table.insert(self.toRemove, x)
  153. end
  154. function View:convertZ(z)
  155. return (.8 * z) ^ (1 + (.0008 * z))
  156. end
  157. function View:three(x, y, z)
  158. local sx, sy = math.lerp(self.prevx, self.x, ls.accum / ls.tickrate), math.lerp(self.prevy, self.y, ls.accum / ls.tickrate)
  159. z = self:convertZ(z)
  160. return x - (z * ((sx + self.width / 2 - x) / 500)), y - (z * ((sy + self.height / 2 - y) / 500))
  161. end
  162. function View:threeDepth(x, y, z)
  163. return math.clamp(math.distance(x, y, self.x + self.width / 2, self.y + self.height / 2) * self.scale - 1000 - z, -4096, -16)
  164. end
  165. function View:contain()
  166. self.x = math.clamp(self.x, 0, self.xmax - self.width)
  167. self.y = math.clamp(self.y, 0, self.ymax - self.height)
  168. end
  169. function View:worldPoint(x, y)
  170. x = math.round(((x - self.frame.x) / self.scale) + self.x)
  171. if y then y = math.round(((y - self.frame.y) / self.scale) + self.y) end
  172. return x, y
  173. end
  174. function View:screenPoint(x, y)
  175. local vx, vy = math.lerp(self.prevx, self.x, ls.accum / ls.tickrate), math.lerp(self.prevy, self.y, ls.accum / ls.tickrate)
  176. x = (x - vx) * self.scale
  177. if y then y = (y - vy) * self.scale end
  178. return x, y
  179. end
  180. function View:worldMouseX()
  181. return math.round(((love.mouse.getX() - self.frame.x) / self.scale) + self.x)
  182. end
  183. function View:worldMouseY()
  184. return math.round(((love.mouse.getY() - self.frame.y) / self.scale) + self.y)
  185. end
  186. function View:frameMouseX()
  187. return love.mouse.getX() - self.frame.x
  188. end
  189. function View:frameMouseY()
  190. return love.mouse.getY() - self.frame.y
  191. end
  192. function View:screenshake(amount)
  193. if self.shake > amount then self.shake = self.shake + (amount / 2) end
  194. self.shake = amount
  195. end
  196. function View:worldPush()
  197. local x, y, s = unpack(table.interpolate({self.prevx, self.prevy, self.prevscale}, {self.x, self.y, self.scale}, ls.accum / ls.tickrate))
  198. local shakex = 1 - (2 * love.math.noise(self.shake + x + ls.accum))
  199. local shakey = 1 - (2 * love.math.noise(self.shake + y + ls.accum))
  200. x = x + (shakex * self.shake)
  201. y = y + (shakey * self.shake)
  202. g.push()
  203. g.translate(self.frame.x, self.frame.y)
  204. g.scale(s)
  205. g.translate(-x, -y)
  206. end
  207. function View:guiPush()
  208. g.push()
  209. g.translate(self.frame.x, self.frame.y)
  210. end