Hello,
Making my first steps in Love2D, I tried to make simple top-down maze walker.
What I hit very quickly were some specifics of engine's rendering coordinate systems.
In particular, I tried to change default draw coordinate system such that width or height of one square tile is exactly 1 unit. Nothing too hard.
Next I tried to use quads to render tiles. What really surprised me is that both quad mesh's dimensions and its "on-screen" dimensions influence texture coordinates. While I thought that first 4 parameters to newQuad influence only texture coordinates, pixel-wise, and based on images' dimensions.
To sum up, it appears that Love2D is intended to work with pixel-based coordinate and rendering systems, while it seems to not have affine matrix math included in its standard library.
What I'd like to know is what's the usual way of implementing games where level coordinate system doesn't match draw coordinate system?
Quads, sprites and coordinate systems
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
-
- Prole
- Posts: 8
- Joined: Thu Apr 05, 2012 6:41 pm
Re: Quads, sprites and coordinate systems
I can't reproduce the effect you're experiencing. Can you give an example?
This works just fine for me:
It draws a small version of the first sprite, as expected. What you can't do is define quads in your own units. You need the image dimensions in pixels to define a quad, but not to use it.
This works just fine for me:
Code: Select all
local lg = love.graphics
-- this image is 256x256 and has 4 parts
local img = lg.newImage('2x2.png')
local q1 = lg.newQuad( 0, 0, 128, 128, 256, 256)
local q2 = lg.newQuad(128, 0, 128, 128, 256, 256)
local q3 = lg.newQuad( 0, 128, 128, 128, 256, 256)
local q4 = lg.newQuad(128, 128, 128, 128, 256, 256)
function love.draw()
love.graphics.scale(0.2, 0.2)
love.graphics.draw(img, q1)
end
-
- Prole
- Posts: 8
- Joined: Thu Apr 05, 2012 6:41 pm
Re: Quads, sprites and coordinate systems
Hi,
Thanks for your response
I'm trying to do something opposite:
I got already that quads aren't intended for use with "abstract scene units". And the only option I see is to define meshes manually, possibly over texture atlas.
Thanks for your response
I'm trying to do something opposite:
Code: Select all
c_unitPixels = 64
-- Scene transformation and scale applied each frame
g_sceneTrans = { 0, 0 }
g_sceneScale = { 0, 0 }
function love.resize(wx, wy)
-- Recalculate scene coordinate system
g_sceneTrans[1] = wx / 2
g_sceneTrans[2] = wy / 2
g_sceneScale[1] = c_unitPixels
g_sceneScale[2] = -c_unitPixels
end
function love.load()
love.resize(love.graphics.getWidth(), love.graphics.getHeight())
texture = love.graphics.newImage('16x16.png')
-- 1. Unexpectedly gets desired result
quad = love.graphics.newQuad(0, 0, 1, 1, 1, 1)
-- 2. Sprite goes off-screen, textured part is of desired size, the rest looks like stretching of borders
-- I expected it will work as expected
-- quad = love.graphics.newQuad(0, 0, texture:getWidth(), texture:getHeight(), 1, 1)
-- 3. Sprite is properly textured, but stretched beyond screen
-- quad = love.graphics.newQuad(0, 0, texture:getWidth(), texture:getHeight(), texture:getWidth(), texture:getHeight())
-- 4. Sprite is of proper size, but contains single pixel
-- quad = love.graphics.newQuad(0, 0, 1, 1, texture:getWidth(), texture:getHeight())
end
function love.draw()
local g = love.graphics
-- First, transform coordinate system such that
-- Y goes up, zero is at screen center and dimensions are in tiles, not pixels
g.translate(g_sceneTrans[1], g_sceneTrans[2])
g.scale(g_sceneScale[1], g_sceneScale[2])
-- Actual drawing goes here
g.setColor(255, 255, 255)
g.draw(texture, quad, 0, 0)
end
Re: Quads, sprites and coordinate systems
Ah, got it. So you're expecting it to keep its original size when scaled. That's not what scaling does; scaling zooms everything.
The "standard" approach for most uses is your number (3) above, where you say "Sprite is properly textured, but stretched beyond screen"; to compensate for the stretching, you can do this:
An alternative is to multiply the coordinates at render time:
But you can also use your approach (1). If you define "width" and "height" in basic units (of size 64x64 pixels in your case) and count the number of sprites, you can work like that. In the above example, you say you're using a 16x16 image but your coordinates are 64x64, therefore the correct width and height of the image should be 16/64 = 0.25.
Example: you have a sprite sheet of 512x512 pixels, each sprite being 64x64, and your base square is 64x64. You would create a quad with width and height 8, 8 and the quads would be at integral coordinates, like this:
Or alternatively:
Since you invert the Y axis, you may need to flip the sprite and use this instead:
The "standard" approach for most uses is your number (3) above, where you say "Sprite is properly textured, but stretched beyond screen"; to compensate for the stretching, you can do this:
Code: Select all
g.draw(texture, quad, 0, 0, 0, 1/g_sceneScale[1], 1/g_sceneScale[2])
Code: Select all
function love.draw()
local g = love.graphics
-- First, transform coordinate system such that
-- Y goes up, zero is at screen center and dimensions are in tiles, not pixels
g.translate(g_sceneTrans[1], g_sceneTrans[2])
-- Actual drawing goes here
g.setColor(255, 255, 255)
g.draw(texture, quad, 0 * g_sceneScale[1], 0 * g_sceneScale[2])
end
Example: you have a sprite sheet of 512x512 pixels, each sprite being 64x64, and your base square is 64x64. You would create a quad with width and height 8, 8 and the quads would be at integral coordinates, like this:
Code: Select all
local i = 1
for y = 0, 7 do
fox x = 0, 7 do
quads[i] = love.graphics.newQuad(x, y, 1, 1, 8, 8)
i = i + 1
end
end
Code: Select all
local myUnit = 64
local width, height = img:getDimensions()
local i = 1
for y = 0, width - 1, myUnit do
fox x = 0, height - 1, myUnit do
quads[i] = love.graphics.newQuad(x / myUnit, y / myUnit, 1, 1, width / myUnit, height / myUnit)
i = i + 1
end
end
Code: Select all
quads[i] = love.graphics.newQuad(x / myUnit, (y + myUnit - 1) / myUnit, 1, -1, width / myUnit, height / myUnit)
-
- Prole
- Posts: 8
- Joined: Thu Apr 05, 2012 6:41 pm
Re: Quads, sprites and coordinate systems
Thanks for your time
Although samples you provided prove that quads were designed to work with pixel-based units. Meshes may be an option though, especially for static tile grids.
Although samples you provided prove that quads were designed to work with pixel-based units. Meshes may be an option though, especially for static tile grids.
Re: Quads, sprites and coordinate systems
That's not really exclusive of quads, it's all about the transformation functions. When scaling, everything gets zoomed. Even lines get thicker.
Code: Select all
function love.draw()
local lg = love.graphics
lg.translate(400, 300)
lg.scale(100,100)
lg.line(-3,-2,3,2)
end
-
- Prole
- Posts: 8
- Joined: Thu Apr 05, 2012 6:41 pm
Re: Quads, sprites and coordinate systems
Thanks, I know this.
Unfortunately, this still doesn't answer what's the "right" way in Love2D to work with non-pixel scene units.
Unfortunately, this still doesn't answer what's the "right" way in Love2D to work with non-pixel scene units.
Re: Quads, sprites and coordinate systems
My way to handle units is like this. Using it in my current project.
Code: Select all
width, height = love.graphics.getDimensions( )
unit = 0
--To get the same number of units on any resolution
--1 unit is the smallest of width/24 or height/18
if width/24 < height/18 then
unit = width/24
else
unit = height/18
end
img = love.graphics.newImage('img.png')
quad = love.graphics.newQuad( 0, 0, 16, 16, img:getHeight(), img:getWidth())
....
--Draw the quad at position x = 1*unit, y = 1*unit with the size 1*unit
love.graphics.draw(img, quad, unit, unit, 0,16/unit, 16/unit)
Who is online
Users browsing this forum: Amazon [Bot], Bing [Bot], Google [Bot] and 9 guests