[Worked Around] math.floor and Canvas
Posted: Sun Jun 08, 2014 2:16 pm
A bit of research lead me to believe that flooring the values of a translation function with a Canvas would help prevent any artefacts, however I am receiving a weird affect where items are 'jiggling' around with what I can assume to be numbers be rounded down (similar to snapping to a grid).
I have two drawing methods and video evidence to go along with this if anyone has any ideas on what could be happening, I'm open to ideas and suggestions.
The troubled code
The working code
With the troubled code, by moving line 12 (the translation) out and to where I am scaling it then everything works until you translate the canvas itself off-screen and can't see it any more because we are now translating the frame itself instead of the content displayed within the frame.
It is this single line of code (using math.floor in the canvas on translation or scaling has no effect) that is causing me headaches and I would like to know what people on the forums thought of it.
Here is a short video visualising my problem.
You can see that verses the trouble code and working code that the game looks 'wobbly' when walking in a diagonal direction. (The screen snapping to the floor'd values perhaps?)
Please don't mind the placeholder art:
Love2D - Canvas Issue
Thank you in advance
and thank you to the hard working developers who continue to work on this powerful engine
EDIT: I found out that using math.floor on the working code simulated the troubled code proving that the Canvas object translate in full integer numbers. So what should I do from here?
EDIT: Okay so what I did is that I took the lost fraction from the math.floor method and added it to the frame buffers (canvas) and added an if statement to translate it with some 'magic numbers'
I would like to one day convert these magic numbers into scientific numbers but for the moment it is what I needed.
My best guess would have to be something to do with the fact that the fraction most affected by flooring would be the half way point (I am using the magic numbers 0.4 and 0.5 which would explain it some-what)
Here is the complete draw code for anyone wondering or in need of a similar solution:
I have two drawing methods and video evidence to go along with this if anyone has any ideas on what could be happening, I'm open to ideas and suggestions.
The troubled code
Code: Select all
-- The troubled code
function Sandbox:draw()
-- Get the scale at which to render the game
local scale = self.tileManager:getCameraScale();
-- Clear the frame buffers
self.backgroundBuffer:clear();
self.entitiesBuffer:clear();
self.foregroundBuffer:clear();
-- Set up the camera
-- ### TROUBLED CODE ###
-- ### By moving this translate out and putting it to where I render the buffers
-- I get a smooth transition however the canvas limit will show as I am moving
-- the canvas itself and not the content displayed within it! ###
love.graphics.translate(-self.cam.x, -self.cam.y);
-- Render the background to a frame buffer
love.graphics.setCanvas(self.backgroundBuffer)
self.tileManager:drawBackground();
-- Render the entiteis to a different frame buffer
love.graphics.setCanvas(self.entitiesBuffer)
for k, v in pairs(self.entitiesToRender) do
v:draw()
end
-- Render the foreground to another different frame buffer
love.graphics.setCanvas(self.foregroundBuffer)
self.tileManager:drawForeground()
love.graphics.setCanvas()
-- Reset the graphics
love.graphics.origin()
-- Scale up the game
love.graphics.scale(scale, scale);
-- Draw the game
love.graphics.draw(self.backgroundBuffer);
love.graphics.draw(self.entitiesBuffer);
love.graphics.draw(self.foregroundBuffer);
-- Reset the graphics (for GUI rendered in a different module)
love.graphics.origin();
end
Code: Select all
-- The working code
function Sandbox:draw()
-- Get the scale at which to render the game
local scale = self.tileManager:getCameraScale();
-- Scale up the game
love.graphics.scale(scale, scale);
-- Set up the camera
love.graphics.translate(-self.cam.x, -self.cam.y);
-- Render the background
self.tileManager:drawBackground();
-- Render the entiteis
for k, v in pairs(self.entitiesToRender) do
v:draw()
end
-- Render the foreground
self.tileManager:drawForeground()
-- Reset the graphics (for GUI rendered in a different module)
love.graphics.origin();
end
It is this single line of code (using math.floor in the canvas on translation or scaling has no effect) that is causing me headaches and I would like to know what people on the forums thought of it.
Here is a short video visualising my problem.
You can see that verses the trouble code and working code that the game looks 'wobbly' when walking in a diagonal direction. (The screen snapping to the floor'd values perhaps?)
Please don't mind the placeholder art:
Love2D - Canvas Issue
Thank you in advance
and thank you to the hard working developers who continue to work on this powerful engine
EDIT: I found out that using math.floor on the working code simulated the troubled code proving that the Canvas object translate in full integer numbers. So what should I do from here?
EDIT: Okay so what I did is that I took the lost fraction from the math.floor method and added it to the frame buffers (canvas) and added an if statement to translate it with some 'magic numbers'
I would like to one day convert these magic numbers into scientific numbers but for the moment it is what I needed.
My best guess would have to be something to do with the fact that the fraction most affected by flooring would be the half way point (I am using the magic numbers 0.4 and 0.5 which would explain it some-what)
Here is the complete draw code for anyone wondering or in need of a similar solution:
Code: Select all
function Sandbox:draw()
local scale = self.tileManager:getCameraScale();
local flooredCam = {math.floor(-self.cam.x), math.floor(-self.cam.y)}
self.foregroundBuffer:clear();
self.entitiesBuffer:clear();
self.finalGameBuffer:clear();
self.finalGUIBuffer:clear();
love.graphics.push()
love.graphics.translate(flooredCam[1], flooredCam[2]);
love.graphics.setCanvas(self.entitiesBuffer)
for k, v in pairs(self.entitiesToRender) do
v:draw();
end
love.graphics.setCanvas(self.foregroundBuffer)
self.tileManager:drawForeground()
love.graphics.setCanvas()
love.graphics.pop();
love.graphics.setCanvas(self.finalGameBuffer);
love.graphics.origin();
love.graphics.translate(flooredCam[1], flooredCam[2]);
self.tileManager:drawBackground()
love.graphics.draw(self.entitiesBuffer, -flooredCam[1], -flooredCam[2])
love.graphics.draw(self.foregroundBuffer, -flooredCam[1], -flooredCam[2])
self.tileManager:renderLighting()
self.daynight:draw();
love.graphics.push();
-- XRAY SHADER
love.graphics.origin();
self.xrayShader:send("stencil", self.foregroundBuffer);
love.graphics.setShader(self.xrayShader)
love.graphics.setColor(0, math.random()*55+200, 0, math.random()*50+100)
love.graphics.draw(self.entitiesBuffer)
love.graphics.setShader()
love.graphics.pop();
love.graphics.setCanvas();
love.graphics.pop();
-- Render the final frame
love.graphics.push()
love.graphics.origin()
local width, height = 0, 0;
if self.splitScreenDirection == 0 then
height = (self.game.index - 1) * (love.window.getHeight());
else
width = (self.game.index - 1) * (love.window.getWidth());
end
love.graphics.push()
-- Render Game
love.graphics.push()
love.graphics.setColor(255, 255, 255, 255)
love.graphics.setBlendMode("premultiplied")
love.graphics.translate(width, height)
love.graphics.scale(scale, scale);
-- Realign the frame bufferes with the camera coordinates and some magic numbers
local wX, wY = (-self.cam.x - flooredCam[1]), (-self.cam.y - flooredCam[2])
if wX > 0.4 and wX < 0.5 then
love.graphics.translate(0.5, 0)
else
love.graphics.translate(wX, 0)
end
if wY > 0.4 and wY < 0.5 then
love.graphics.translate(0, 0.5)
else
love.graphics.translate(0, wY)
end
love.graphics.draw(self.finalGameBuffer);
love.graphics.pop()
-- Render GUI
love.graphics.translate(width, height)
love.graphics.draw(self.finalGUIBuffer);
love.graphics.pop()
love.graphics.pop()
-- reset the colour
love.graphics.setBlendMode("alpha")
love.graphics.origin();
end