[Worked Around] math.floor and Canvas

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
OnlyFails
Prole
Posts: 6
Joined: Fri May 02, 2014 9:00 pm

[Worked Around] math.floor and Canvas

Post by OnlyFails »

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

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
The working code

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
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
Image


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
Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests