Oh wow. I didn't even know :renderTo() existed. That's a pretty convenient shortcut.
Anyway, the next step is centering the image. T-bone's method above does look like it takes that into account. Here's what you're doing:
When you have a window that's wider than the drawing area, you'll want to center it by figuring out the proper offsets for the top and left. Most of the time, one of these is going to be 0. Usually the top. So we'll concentrate on figuring out the left offset. The formula is simple:
left offset = (window width - (draw width * draw scale)) / 2
Where window width is obvious, draw width is the pixel amount of what you're drawing, in your case 512 and draw scale is the scale value we calculated before. You then use love.graphics.translate(left offset, top offset) inside the love.graphics.push() stuff we added before. To calculate the top offset, you just replace widths with heights. Simple as pie.
If you are using the canvas, then instead of translating it you can just draw the canvas as an image directly to those coordinates at that scale. But either way will work.
To make things easier, store the draw widths and heights as global variables you can use anywhere you need to.
Now here's the tricky part. If you're not using the canvas method, you will probably want to use setScissor to crop out stuff being drawn off to the sides. That's simple, but it won't be affected by pushing and popping so we'll just need to do some simple math to figure out where to scissor. Using the offsets we got above...
love.graphics.setScissor(left offset, top offset, draw width * draw scale, draw height * draw scale)
Put that before your drawing code, but after all coordinates for drawing are calculated. And then after your drawing code, make sure to reset the Scissor by simply calling an empty setScissor function without any coordinates. What the Scissor does is creates a mask where anything drawn will be trimmed. Very useful indeed.
I will try to create a sample main.lua that you can use for reference soon. For now this information should help.
Fullscreen bug
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
- Jasoco
- Inner party member
- Posts: 3727
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: Fullscreen bug
I'm only double-posting because the previous post is pretty big, and this is pretty important that it'll make sense to keep it separate.
Anyway, here's some sample code to play with. Copy it all and paste into a blank main.lua file and run the project. Resize the window how you like, try out the Fullscreen button in the top right corner. It works perfectly. You don't need a conf.lua for this to work, I made sure it works without it. It's highly commented so any questions can be answered by reading the text.
Hope this helps a lot.
Anyway, here's some sample code to play with. Copy it all and paste into a blank main.lua file and run the project. Resize the window how you like, try out the Fullscreen button in the top right corner. It works perfectly. You don't need a conf.lua for this to work, I made sure it works without it. It's highly commented so any questions can be answered by reading the text.
Code: Select all
-- ALL CAPS variables are globals
-- The rest are lowercase if they're local
-- This is just for demonstration
-- Set up some globals to start with
DRAW_WIDTH = 512
DRAW_HEIGHT = 448
CANVAS_MODE = false
SCISSOR_MODE = false
function love.load()
-- Create the canvas in case you're using canvas mode
MY_CANVAS = love.graphics.newCanvas(DRAW_WIDTH, DRAW_HEIGHT)
-- Make sure to set the filter to "nearest" to draw crisp clean tasty pixels
MY_CANVAS:setFilter("nearest")
-- Set up the window. Fullscreen Type is "desktop" which will resize the actual content
-- instead of changing the screen resolution if fullscreen is enabled. This will keep a lot
-- of people happy. And the Resizable flag is set to true because it will let you size the
-- window yourself and gives it the neat "Lion Fullscreen" option on OS X which is very much
-- appreciated. I set the initial window size to 720p for the heck of it. It gives you a good
-- idea of how the letterboxing will be working for you. And the HighDPI option is enabled
-- because why not. Now that you're independent, it doesnt matter if it's on or not. See
-- love.resize() below for more information.
local success = love.window.setMode( 1280, 720, {
resizable = true,
fullscreentype = "desktop",
highdpi = true
} )
-- Make sure to recalculate everything. Or rather calculate everything for the first time...
love.resize()
end
function love.update(dt)
-- LOL, this isnt needed here! So why is it here? Hahaha. Why did I even put it here?
end
function love.draw()
-- Set the scissor
-- For the purposes of this example, I included an option to disable and reenable the scissor.
-- When SCISSOR is turned off, the background will be purple. This is just for demonstration.
if SCISSOR_MODE then
love.graphics.setScissor(LEFT_OFFSET, TOP_OFFSET, DRAW_WIDTH * DRAW_SCALE, DRAW_HEIGHT * DRAW_SCALE)
end
-- For demonstration to demonstrate the scissor being disabled
love.graphics.setColor(150,0,255)
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
if CANVAS_MODE then
-- IF USING CANVASES this code should do the trick nicely
-- Clear the canvas first, then draw everything to it,
-- then draw the canvas (Make sure to set the color to white)
MY_CANVAS:clear(0,0,0,0)
MY_CANVAS:renderTo(drawAllTheThings)
love.graphics.setColor(255,255,255)
love.graphics.draw(MY_CANVAS, LEFT_OFFSET, TOP_OFFSET, 0, DRAW_SCALE, DRAW_SCALE)
else
-- IF NOT USING CANVASES then this is the method to use
-- Use the push and pop stuff to move the drawing coordinates into place
-- IMPORTANT: Translate MUST be before the Scaling or else it will not draw correctly
love.graphics.push()
love.graphics.translate(LEFT_OFFSET, TOP_OFFSET)
love.graphics.scale(DRAW_SCALE)
drawAllTheThings()
love.graphics.pop()
end
-- Reset the Scissor
love.graphics.setScissor()
-- NOTE: If you're using a canvas, you won't need a scissor at all. As the canvas will act
-- like a scissor in and of itself. But I kept the scissor outside the canvas area just for
-- the heck of it
-- For the example, print whether the canvas and scissor are enabled
love.graphics.push()
love.graphics.scale(PIXEL_SCALE)
love.graphics.setColor(255,255,255)
love.graphics.print("Canvas Mode: " .. tostring(CANVAS_MODE), 10, 10)
love.graphics.print("Scissors: " .. tostring(SCISSOR_MODE), 10, 25)
love.graphics.print("Press S to enable/disable scissor and C for the canvas", 10, 50)
love.graphics.pop()
end
function love.resize(w, h)
-- This is where the magic happens
-- First we get the width and height of the window. It will usually be passed as w and h
-- into love.resize but in case you're calling it naked then this will save you the trouble
-- of having to grab the width and height yourself
local w = w or love.graphics.getWidth()
local h = h or love.graphics.getHeight()
-- Figure out the scaling for both width- and height-based scaling. It's not required,
-- but it's just to make it easier to figure out. Most of the time you'll usually be using
-- the DRAW_SCALE variable instead which will be defined below
SCALE_HORIZONTAL, SCALE_VERTICAL = w / DRAW_WIDTH, h / DRAW_HEIGHT
-- For the next part we need the aspect of both the game drawing area and the window draw area...
local aspect_game = w / h
local aspect_window = DRAW_WIDTH / DRAW_HEIGHT
-- ...which will now be used thusly...
if aspect_window <= aspect_game then
-- ...If the aspect of the window is smaller than the aspect of the game,
-- i.e. if the window is wider, then use the vertical value...
DRAW_SCALE = SCALE_VERTICAL
else
-- ...But if the window is taller, then use the horizontal value.
DRAW_SCALE = SCALE_HORIZONTAL
end
-- And lastly, calculate the offsets for where to draw the image.
LEFT_OFFSET = (w - (DRAW_WIDTH * DRAW_SCALE)) / 2
TOP_OFFSET = (h - (DRAW_HEIGHT * DRAW_SCALE)) / 2
-- The following only applies if you plan on using HighDPI mode. Even though you're using pixel
-- graphics, I still recommend enabling this flag (See the setMode command at the top) because
-- it keeps the sub-pixels crisp. It's a small detail but it'll make Retina MacBook users very
-- happy that you cared enough. I store the pixel scale in a variable just for simplicities sake.
-- This returns 1 if HighDPI is off, 2 if it's on. You use it for scaling other elements on the
-- screen. Like for example, the overlaying text at the end of love.draw() above.
PIXEL_SCALE = love.window.getPixelScale()
end
function love.keypressed(k, r)
if k == "s" then
SCISSOR_MODE = not SCISSOR_MODE
elseif k == "c" then
CANVAS_MODE = not CANVAS_MODE
end
end
-- Just draw something!
function drawAllTheThings()
love.graphics.setColor(0,160,200)
love.graphics.rectangle("fill", 0, 0, DRAW_WIDTH, DRAW_HEIGHT)
love.graphics.setColor(255,0,0)
love.graphics.circle("fill", 0, 0, 20)
love.graphics.setColor(0,255,0)
love.graphics.circle("fill", DRAW_WIDTH, 0, 20)
love.graphics.setColor(0,0,255)
love.graphics.circle("fill", 0, DRAW_HEIGHT, 20)
love.graphics.setColor(255,255,0)
love.graphics.circle("fill", DRAW_WIDTH, DRAW_HEIGHT, 20)
end
-- Goin' crazy with the comments!
Re: Fullscreen bug
Jasoco, couldn't that be made into a library? So that you can just do like this
It would have to modify your existing love.draw function but that's not very difficult.
Code: Select all
function love.load()
-- your code
end
function love.draw()
-- your code
end
-- etc
local rescale = require 'awesomerescalinglibrary'
rescale(512, 448)
My game called Hat Cat and the Obvious Crimes Against the Fundamental Laws of Physics is out now!
Re: Fullscreen bug
From my experience it depends very much on the graphics card and settings how fullscreen looks.
On my colleagues windows machine the game always got stretched to fill the whole screen (but there may be driver options he just never found). On my Linux machine with the current settings is to run it in native resolution and draw a black border around it, but it would also be possible to stretch it to fill the screen (through a xrandr setting).
In general both graphics cards and monitors have a limited set of resolutions they can handle, however, given a screen that's larger than the game it should not be a problem for the graphics card to draw a border around it. This is a matter of configuration on the user side.
On my colleagues windows machine the game always got stretched to fill the whole screen (but there may be driver options he just never found). On my Linux machine with the current settings is to run it in native resolution and draw a black border around it, but it would also be possible to stretch it to fill the screen (through a xrandr setting).
In general both graphics cards and monitors have a limited set of resolutions they can handle, however, given a screen that's larger than the game it should not be a problem for the graphics card to draw a border around it. This is a matter of configuration on the user side.
- Jasoco
- Inner party member
- Posts: 3727
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: Fullscreen bug
It could yes. I had thought about it while I was writing that example, but I wanted to keep it simple. (It only looks more complex because it's like 40-50% comments.)T-Bone wrote:Jasoco, couldn't that be made into a library?
You could easily have a resolutionHandler library with a preRender() and postRender() function that would handle this stuff for you. And I've written libraries for myself in the past, but every time Löve is update it's broken. So lol. It's really quite simple in the end anyway. Just a few variables are required when pushing and popping. The left and top offsets and the overall scale for the most part. Once you calculate those you're golden and the rest is taken care of right then and there. Works best with pixel-y art styles that have low resolution drawing areas. But can also work on a bigger rendering area. I used the same methods for my Eat It! project (I really need to rewrite that. It's broken even in 0.9.1. and it would be a disservice to the nice gentleman that drew my graphics if I never release it.) where I used 1920x1080 as my drawing surface and used the pushing and popping scaling and transforming to draw it at any resolution you wanted to even if it was super high resolution. And it works great.
If I get time tomorrow, maybe I'll whip up a simple library.
See, the problem the OP was having was that he was setting his display resolution to a weird non-standard resolution (512x448 which isn't a standard PC resolution at all) so the display driver was rounding up to the nearest supported resolution (Which would be 640x480) which of course means there's going to be a buffer on the edges since his resolution is 128 pixels too narrow and 32 pixels too short. So it compensates by adding a border.murks wrote:From my experience it depends very much on the graphics card and settings how fullscreen looks.
I noticed this problem for the first time a few weeks ago with GunGodz which sets itself to fullscreen, but on my Retina display ended up with a border on both the top and bottom, as well as the left and right, that ended up window boxing it. Sadly that game did not have any options whatsoever for even using windowed mode so I had to live with it. But this is the explanation for why it does it.
By offering options and using scaling you can completely get around the problem. I recommend not ever ever changing the display's physical resolution at all. Not today. Not in a modern computing age. Where we are multitaskers and like to be able to switch between applications and use multiple displays. It's much better to use the kinder gentler "desktop" fullscreen mode. Or on OS X, the built-in Lion Fullscreen which is basically just windowed without a titlebar or Dock. (Almost, but not quite like maximizing a window in Windows. But more superior in many ways.) By using my method you can make it super simple to never have to worry about incompatibilities with displays again.
Re: Fullscreen bug
Sorry for the necro, but I was giving canvas a try and remembered this thread!
Is it correct to put awesomecanvas:clear() before the renderTo line? If I don't, the old image frames never go away (though maybe I'm messing up with drawing my images?). :ST-Bone wrote:If you're interested in the canvas method, it would look something like this (untested)
Code: Select all
function love.load() awesomecanvas = love.graphics.newCanvas(512, 448) awesomecanvas:setFilter("nearest", "nearest") -- and the rest of your love.load of course end function love.draw2() -- this is your current love.draw function, you just have to rename it to something else ... end function love.draw() awesomecanvas:renderTo(love.draw2) local w = love.window.getWidth() local h = love.window.getHeight() local s = math.floor(h/448) love.graphics.draw(awesomecanvas, w*0.5 - s*512, h*0.5 - s*448, 0, s, s) end
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 9 guests