## Quads, sprites and coordinate systems

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
target.san
Prole
Posts: 8
Joined: Thu Apr 05, 2012 6:41 pm

### Quads, sprites and coordinate systems

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?

pgimeno
Party member
Posts: 1629
Joined: Sun Oct 18, 2015 2:58 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:

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

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.

target.san
Prole
Posts: 8
Joined: Thu Apr 05, 2012 6:41 pm

### Re: Quads, sprites and coordinate systems

Hi,

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

love.resize(love.graphics.getWidth(), love.graphics.getHeight())
texture = love.graphics.newImage('16x16.png')
-- 1. Unexpectedly gets desired result
-- 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
-- 3. Sprite is properly textured, but stretched beyond screen
-- 4. Sprite is of proper size, but contains single pixel
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)
end

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.

pgimeno
Party member
Posts: 1629
Joined: Sun Oct 18, 2015 2:58 pm

### 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:

Code: Select all

g.draw(texture, quad, 0, 0, 0, 1/g_sceneScale[1], 1/g_sceneScale[2])

An alternative is to multiply the coordinates at render time:

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

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:

Code: Select all

  local i = 1
for y = 0, 7 do
fox x = 0, 7 do
i = i + 1
end
end

Or alternatively:

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

Since you invert the Y axis, you may need to flip the sprite and use this instead:

Code: Select all

      quads[i] = love.graphics.newQuad(x / myUnit, (y + myUnit - 1) / myUnit, 1, -1, width / myUnit, height / myUnit)


target.san
Prole
Posts: 8
Joined: Thu Apr 05, 2012 6:41 pm

### Re: Quads, sprites and coordinate systems

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.

pgimeno
Party member
Posts: 1629
Joined: Sun Oct 18, 2015 2:58 pm

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

Attachments
thicker-line.png (6.62 KiB) Viewed 937 times

target.san
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.

sefan
Prole
Posts: 22
Joined: Fri Jul 31, 2015 7:03 am
Contact:

### 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')