From f34ec5f8f29ce07d69104e537e87ed357abaf786 Mon Sep 17 00:00:00 2001 From: Aki Date: Wed, 13 Sep 2017 12:50:46 +0200 Subject: Camera and Layers now properly handle different resolution ratios --- not/Camera.lua | 55 ++++++++++------------------------------------------ not/Layer.lua | 15 +++++---------- not/World.lua | 61 ++++++++++++++++++++++++---------------------------------- 3 files changed, 40 insertions(+), 91 deletions(-) diff --git a/not/Camera.lua b/not/Camera.lua index b3b8128..65395cb 100644 --- a/not/Camera.lua +++ b/not/Camera.lua @@ -1,5 +1,5 @@ --- Used in drawing other stuff in places. --- TODO: Support for real scale translations. +-- TODO: Camera is missing documentation on every important method. Camera = require "not.Object":extends() Camera.SHAKE_LENGTH = 0.6 @@ -26,41 +26,19 @@ function Camera:push () love.graphics.push() end -function Camera:scale (scale) - scale = scale or getScale() - love.graphics.scale(scale, scale) -end - -function Camera:translate (ratio) +function Camera:transform (scale, ratio, vw, vh) local px, py = self:getPosition() - local dx, dy = self:getShake() - local ox, oy = self:getHalfViewSize() - if ratio then - dx = dx * ratio - dy = dy * ratio - px = px * ratio - py = py * ratio - end - love.graphics.translate(ox - px - dx, oy - py - dy) -end + local sx, sy = self:getShake() + local dx, dy = (px + sx) * ratio, (py + sy) * ratio --- TODO: TranslateReal is temporary. -function Camera:translateReal (ratio) - local px, py = self:getPosition() - local dx, dy = self:getShake() - local ox, oy = self:getHalfViewSize(getRealScale()) - if ratio then - dx = dx * ratio - dy = dy * ratio - px = px * ratio - py = py * ratio - end - love.graphics.translate(ox - px - dx, oy - py - dy) + vw, vh = vw / scale / 2, vh / scale / 2 + + love.graphics.scale(scale, scale) + love.graphics.translate(vw - dx, vh - dy) end function Camera:pop () love.graphics.pop() - self._scale = nil end function Camera:setPosition (x, y) @@ -73,25 +51,12 @@ function Camera:getPosition () return self.x, self.y end -function Camera:getBoundaries () +function Camera:getBoundaries (scale, vw, vh) local x, y = self:getPosition() - local width, height = self:getHalfViewSize() + local width, height = vw / scale / 2, vh / scale / 2 return x - width, y - height, x + width, y + height end --- TODO: Review getViewSize of Camera. -function Camera:getViewSize (scale) - scale = scale or getScale() - local width = love.graphics.getWidth() / scale - local height = love.graphics.getHeight() / scale - return width, height -end - -function Camera:getHalfViewSize (scale) - local width, height = self:getViewSize(scale) - return width / 2, height / 2 -end - function Camera:startShake () self.shakeTime = Camera.SHAKE_LENGTH end diff --git a/not/Layer.lua b/not/Layer.lua index ebfb28e..14dac32 100644 --- a/not/Layer.lua +++ b/not/Layer.lua @@ -1,11 +1,11 @@ --- A little bit more than just a Canvas. --- TODO: Scaled and RealScaled support should be extended. Layer = require "not.Object":extends() function Layer:new (width, height) self.canvas = love.graphics.newCanvas(width, height) - self.scale = false - self.ratio = false + self.transformScale = getScale() + self.transformRatio = 1 + self.drawScale = 1 end function Layer:delete () @@ -28,8 +28,7 @@ end function Layer:renderToWith (camera, func, ...) camera:push() - camera:scale(self.scale) - camera:translate(self.ratio) + camera:transform(self.transformScale, self.transformRatio, self.canvas:getDimensions()) self:renderTo(func, ...) camera:pop() end @@ -39,12 +38,8 @@ function Layer:clear () end function Layer:draw () - local scale = 1 - if self.scale then - scale = getScale() / self.scale - end love.graphics.setColor(255, 255, 255, 255) - love.graphics.draw(self.canvas, nil, nil, nil, scale, scale) + love.graphics.draw(self.canvas, nil, nil, nil, self.drawScale, self.drawScale) end return Layer diff --git a/not/World.lua b/not/World.lua index 0a560fb..92e9ae0 100644 --- a/not/World.lua +++ b/not/World.lua @@ -64,22 +64,27 @@ end function World:initLayers () self.layers = setmetatable({}, {__call = layersIterator}) self.layers.n = 0 - - local width, height = self.camera:getViewSize() - self.layers.rays = self:addLayer(width, height, 0, 1) - - local width, height = love.graphics.getDimensions() - self.layers.tags = self:addLayer(width, height) - self.layers.platforms = self:addLayer(width, height) - self.layers.effects = self:addLayer(width, height) - self.layers.heroes = self:addLayer(width, height) - self.layers.decorations = self:addLayer(width, height) - self.layers.clouds = self:addLayer(width, height) + do + local width, height = love.graphics.getWidth() / getScale(), love.graphics.getHeight() / getScale() + local rays = self:addLayer(width, height) + rays.transformScale = 1 + rays.transformRatio = 0 + rays.drawScale = getScale() + self.layers.rays = rays + end + do + local width, height = love.graphics.getDimensions() + self.layers.tags = self:addLayer(width, height) + self.layers.platforms = self:addLayer(width, height) + self.layers.effects = self:addLayer(width, height) + self.layers.heroes = self:addLayer(width, height) + self.layers.decorations = self:addLayer(width, height) + self.layers.clouds = self:addLayer(width, height) + end end --- Builds map using one of tables frin config files located in `config/maps/` directory. -- TODO: Clean World@buildMap. Possibly explode into more methods. --- TODO: ScaledLayers and RealScaledLayers should be implemented properly with good Camera support. function World:buildMap () for _,op in pairs(self.map.create) do if op.platform then @@ -102,18 +107,9 @@ function World:buildMap () width = width * getScale() height = height * getScale() end - bg.layer = self:addLayer(width, height, op.ratio, getRealScale()) - bg.layer.renderToWith = function (self, camera, func, ...) - camera:push() - camera:scale(self.scale) - camera:translateReal(self.ratio) - self:renderTo(func, ...) - camera:pop() - end - bg.layer.draw = function (self) - love.graphics.setColor(255, 255, 255, 255) - love.graphics.draw(self.canvas) - end + bg.layer = self:addLayer(width, height) + bg.layer.transformRatio = op.ratio + bg.layer.transformScale = getRealScale() end if op.clouds then local width, height = love.graphics.getDimensions() @@ -123,7 +119,8 @@ function World:buildMap () end local cg = CloudGenerator(op.clouds, animations, op.count, self) if op.ratio then - cg.layer = self:addLayer(width, height, op.ratio) + cg.layer = self:addLayer(width, height) + cg.layer.transformRatio = op.ratio end self:insertEntity(cg) cg:run(op.count, true) @@ -146,16 +143,9 @@ function World:getSpawnPosition () return self.map.respawns[n].x, self.map.respawns[n].y end --- TODO: Possibly automate calculation of new layer's dimensions based on scale. -function World:addLayer (width, height, ratio, scale) +function World:addLayer (width, height) local layer = Layer(width, height) local n = self.layers.n + 1 - if ratio then - layer.ratio = ratio - end - if scale then - layer.scale = scale - end self.layers[n] = layer self.layers.n = n return layer @@ -332,14 +322,13 @@ function World:draw () -- TODO: Debug information could possibly get its own layer so it could follow flow of draw method. if debug then local center = self.map.center - local ax, ay, bx, by = self.camera:getBoundaries() + local ax, ay, bx, by = self.camera:getBoundaries(getScale(), love.graphics.getDimensions()) love.graphics.setLineWidth(1 / getScale()) love.graphics.setLineStyle("rough") self.camera:push() - self.camera:scale() - self.camera:translate() + self.camera:transform(getScale(), 1, love.graphics.getDimensions()) love.graphics.setColor(130,130,130) love.graphics.line(ax,center.y,bx,center.y) -- cgit v1.1