## Drawing a perspective grid (Solved)

Showcase your libraries, tools and other projects that help your fellow love users.
Blart
Prole
Posts: 9
Joined: Sun Mar 01, 2009 7:42 pm

### Drawing a perspective grid (Solved)

Solution found

Code: Select all

GRID_BOTTOM_WIDTH = 768
GRID_TOP_WIDTH = 384

GRID_BOTTOM_XI = 16
GRID_BOTTOM_YI = 472

GRID_BOTTOM_XF = GRID_BOTTOM_XI + GRID_BOTTOM_WIDTH
GRID_BOTTOM_YF = GRID_BOTTOM_YI

GRID_TOP_XI = ((GRID_BOTTOM_WIDTH - GRID_TOP_WIDTH) / 2) + GRID_BOTTOM_XI
GRID_TOP_YI = 256

GRID_TOP_XF = GRID_TOP_XI + GRID_TOP_WIDTH
GRID_TOP_YF = GRID_TOP_YI

GRID_SIZE = 6

GRID_BOTTOM_STEP = GRID_BOTTOM_WIDTH / GRID_SIZE
GRID_TOP_STEP = GRID_TOP_WIDTH / GRID_SIZE

...

love.graphics.line(GRID_BOTTOM_XI, GRID_BOTTOM_YI, GRID_BOTTOM_XF,
GRID_BOTTOM_YF)

love.graphics.line(GRID_TOP_XI, GRID_TOP_YI, GRID_TOP_XF, GRID_TOP_YF)

-- Verticle lines
for i = 0, GRID_SIZE
do
love.graphics.line(GRID_BOTTOM_XI + (GRID_BOTTOM_STEP * i),
GRID_BOTTOM_YI, GRID_TOP_XI + (GRID_TOP_STEP * i), GRID_TOP_YI)
end
The only thing I can't figure out is how to do the horizontal lines properly. They need to be drawn closer together as they get closer to the top.

There is one possibly good technique where first you find the center of the grid. This is done by finding the intersection of the two lines that form an 'x' over the square. This will give you the y-coordinate, while the x-coordinate can possibly be found by doing stuff with the slopes of the outermost vertical lines. Then you split the square into two halves at this line and recurse on them. I hope that wasn't too vague. This approach can only give a number of lines equal to a power of 2, which may be too many.

I was thinking of using some quadratic formula for the horizontal line spacing. But then I need to invent a quadratic formula.
Last edited by Blart on Mon Mar 09, 2009 2:47 am, edited 2 times in total.
osuf oboys
Party member
Posts: 215
Joined: Sun Jan 18, 2009 8:03 pm

### Re: Drawing a perspective grid

Blart wrote: [...] The only thing I can't figure out is how to do the horizontal lines properly. They need to be drawn closer together as they get closer to the top. [...]
That should be pretty easy by applying some trigonometry. However, better than taking this approach of always computing where things should go on the screen, I would suggest that you make a function that takes points in (world_x,world_y,world_z) and produces points in (screenx,screeny).
If I haven't written anything else, you may assume that my work is released under the LPC License - the LÖVE Community. See http://love2d.org/wiki/index.php?title=LPC_License.
Blart
Prole
Posts: 9
Joined: Sun Mar 01, 2009 7:42 pm

### Re: Drawing a perspective grid

osuf oboys wrote:
Blart wrote: However, better than taking this approach of always computing where things should go on the screen, I would suggest that you make a function that takes points in (world_x,world_y,world_z) and produces points in (screenx,screeny).
Good advice, though it's not like I'm doing any 3D stuff.

What the grid is actually supposed to represent is a battlefield for a RPG game. The board is 2D, and has the various heroes and monsters moving around. I'm drawing the grid with perspective for some extra coolness. So, I will have some function that translates the (x, y) coordinates of the board to a position on the screen for drawing the sprites. But first I want to get the grid graphics sorted out.
osuf oboys
Party member
Posts: 215
Joined: Sun Jan 18, 2009 8:03 pm

### Re: Drawing a perspective grid

Blart wrote:
osuf oboys wrote:
Blart wrote: However, better than taking this approach of always computing where things should go on the screen, I would suggest that you make a function that takes points in (world_x,world_y,world_z) and produces points in (screenx,screeny).
Good advice, though it's not like I'm doing any 3D stuff.

What the grid is actually supposed to represent is a battlefield for a RPG game. The board is 2D, and has the various heroes and monsters moving around. I'm drawing the grid with perspective for some extra coolness. So, I will have some function that translates the (x, y) coordinates of the board to a position on the screen for drawing the sprites. But first I want to get the grid graphics sorted out.
Interesting. You can use that function for drawing the lines as well though.
If I haven't written anything else, you may assume that my work is released under the LPC License - the LÖVE Community. See http://love2d.org/wiki/index.php?title=LPC_License.
Blart
Prole
Posts: 9
Joined: Sun Mar 01, 2009 7:42 pm

### Re: Drawing a perspective grid

Here's preliminary work on the horizontal lines. This is the result I don't want, though I did need to figure out how to make the ends of the horizontal lines meet the outermost vertical lines anyway.

Code: Select all

...

GRID_RIGHT_SLOPE
= (GRID_TOP_YI - GRID_BOTTOM_YI) / (GRID_TOP_XI - GRID_BOTTOM_XI)
GRID_RIGHT_SLOPE_ADD = GRID_TOP_YI - (GRID_TOP_XI * GRID_RIGHT_SLOPE)

GRID_LEFT_SLOPE
= (GRID_BOTTOM_YF - GRID_TOP_YF) / (GRID_BOTTOM_XF - GRID_TOP_XF)
GRID_LEFT_SLOPE_ADD = GRID_TOP_YF - (GRID_TOP_XF * GRID_LEFT_SLOPE)

STEP = (GRID_BOTTOM_YI - GRID_TOP_YI) / GRID_SIZE

...

-- Horizontal lines
for i = 0, GRID_SIZE
do

local y = (i * STEP) + GRID_TOP_YI -- **** Not actually how I want to calculate y-coordinates ****

local xi = (y - GRID_RIGHT_SLOPE_ADD) / GRID_RIGHT_SLOPE
local xf = (y - GRID_LEFT_SLOPE_ADD) / GRID_LEFT_SLOPE
love.graphics.line(xi, y, xf, y)
end


Also,
osuf oboys wrote: That should be pretty easy by applying some trigonometry.
Mind sharing this trigonometry?
Xcmd
Party member
Posts: 211
Joined: Fri Feb 13, 2009 10:45 pm

### Re: Drawing a perspective grid

I tried doing this long long ago. I FAILED. FAILED HARD. But I was using BASIC and had very little understanding of this thing we call "Maths". This is some good work, however.
We don't borrow, we don't read, we don't rent, we don't lease, we take the minds!
osuf oboys
Party member
Posts: 215
Joined: Sun Jan 18, 2009 8:03 pm

### Re: Drawing a perspective grid

Blart wrote:Mind sharing this trigonometry?
Given a point (x,y) in your game world, what's the point (X,Y) on the screen? You will need to write this function for your game sooner or later, and the same function will yield the answer to your question. Or have I mistaken your question and it is so that you do this in order to get an idea of what the function should be?
If I haven't written anything else, you may assume that my work is released under the LPC License - the LÖVE Community. See http://love2d.org/wiki/index.php?title=LPC_License.
Blart
Prole
Posts: 9
Joined: Sun Mar 01, 2009 7:42 pm

### Re: Drawing a perspective grid

osuf oboys wrote:Or have I mistaken your question and it is so that you do this in order to get an idea of what the function should be?
Here's the idea. So far I have this line:

Code: Select all

y = (i * STEP) + GRID_TOP_YI
This calculates, for a given world-y value i, the screen-y value named y. So, when i = 0 (world coordinates) y = GRID_TOP_YI (screen coordinates). Likewise, i = GRID_SIZE (GRID_SIZE is the maximum width and height of the world grid) should make y = GRID_BOTTOM_YI. I anticipate that I can translate world-x values into screen-x values through the use of slopes, since that's what I've done to make the current horizontal lines be flush with the exterior vertical lines.

The function above is a linear function. What I want is a better function for translating world-y (i) into screen-y (...y) so that the grid overall looks more like it's slanted. I've been thinking recently of using a quadratic function. The "perspective" probably won't be exact, but at least it'll look better. Then again, I've been having trouble coming up with a quadratic function such that f(0) = GRID_TOP_YI and f(GRID_SIZE) = GRID_BOTTOM_YI. And I've lost my graphic calculator.

Edit

Another condition that my quadratic function should have is that f(GRID_SIZE / 2) should equal the y-value of the intersection point between the lines that make an x over the plane.
Blart
Prole
Posts: 9
Joined: Sun Mar 01, 2009 7:42 pm

### Re: Drawing a perspective grid (Solved)

Good news. I've finally figured out how to handle the horizontal lines. It basically involved lots and lost of algebra that I never want to do again (though I probably will).

The full code:

Code: Select all

function intersectionPoint(axi, ayi, axf, ayf, bxi, byi, bxf, byf)
denom = ((byf - byi) * (axf - axi)) - ((bxf - bxi) * (ayf - ayi))

if denom == 0.0
then
return nil, nil
end

u = (((bxf - bxi) * (ayi - byi)) - ((byf - byi) * (axi - bxi)))
/ denom

x = axi + (u * (axf - axi))
y = ayi + (u * (ayf - ayi))

return x, y
end

---------------------------------------------------------------------------

-- Window width and height is (800, 600)

-- Placement of corners

GRID_BOTTOM_WIDTH = 768
GRID_TOP_WIDTH = 384

GRID_BOTTOM_XI = 16
GRID_BOTTOM_YI = 472

GRID_BOTTOM_XF = GRID_BOTTOM_XI + GRID_BOTTOM_WIDTH
GRID_BOTTOM_YF = GRID_BOTTOM_YI

GRID_TOP_XI = ((GRID_BOTTOM_WIDTH - GRID_TOP_WIDTH) / 2) + GRID_BOTTOM_XI
GRID_TOP_YI = 256

GRID_TOP_XF = GRID_TOP_XI + GRID_TOP_WIDTH
GRID_TOP_YF = GRID_TOP_YI

-- Placement of vertical lines

GRID_SIZE = 6

GRID_BOTTOM_STEP = GRID_BOTTOM_WIDTH / GRID_SIZE
GRID_TOP_STEP = GRID_TOP_WIDTH / GRID_SIZE

-- Placement of horizontal lines

-- x-coordinates

GRID_RIGHT_SLOPE
= (GRID_TOP_YI - GRID_BOTTOM_YI) / (GRID_TOP_XI - GRID_BOTTOM_XI)
GRID_RIGHT_SLOPE_ADD = GRID_TOP_YI - (GRID_TOP_XI * GRID_RIGHT_SLOPE)

GRID_LEFT_SLOPE
= (GRID_BOTTOM_YF - GRID_TOP_YF) / (GRID_BOTTOM_XF - GRID_TOP_XF)
GRID_LEFT_SLOPE_ADD = GRID_TOP_YF - (GRID_TOP_XF * GRID_LEFT_SLOPE)

-- y-coordinates

-- f(GRID_SIZE / 2) = GRID_HORIZ_MIDDLE
_, GRID_HORIZ_MIDDLE = intersectionPoint(GRID_BOTTOM_XI, GRID_BOTTOM_YI,
GRID_TOP_XF, GRID_TOP_YF, GRID_TOP_XI, GRID_TOP_YI,
GRID_BOTTOM_XF, GRID_BOTTOM_YF)

-- y = ax^2 + bx + c
-- c = GRID_TOP_YI
GRID_HORIZ_FUNC_A
= ((2 * GRID_BOTTOM_YI) + (2 * GRID_TOP_YI) - (4 * GRID_HORIZ_MIDDLE)) /
(GRID_SIZE^2)

GRID_HORIZ_FUNC_B = ((4 * GRID_HORIZ_MIDDLE) - (4 * GRID_TOP_YI)
- ((GRID_SIZE^2) * GRID_HORIZ_FUNC_A)) / (2 * GRID_SIZE)

---------------------------------------------------------------------------

function intersectionPoint(axi, ayi, axf, ayf, bxi, byi, bxf, byf)
denom = ((byf - byi) * (axf - axi)) - ((bxf - bxi) * (ayf - ayi))

if denom == 0.0
then
return nil, nil
end

u = (((bxf - bxi) * (ayi - byi)) - ((byf - byi) * (axi - bxi)))
/ denom

x = axi + (u * (axf - axi))
y = ayi + (u * (ayf - ayi))

return x, y
end

---------------------------------------------------------------------------

function draw()
love.graphics.setColor(0, 255, 0)

-- Verticle lines
for i = 0, GRID_SIZE
do
love.graphics.line(GRID_BOTTOM_XI + (GRID_BOTTOM_STEP * i),
GRID_BOTTOM_YI, GRID_TOP_XI + (GRID_TOP_STEP * i), GRID_TOP_YI)
end

-- Horizontal lines
for i = 0, GRID_SIZE
do
--local y = (i * STEP) + GRID_TOP_YI
local y = (GRID_HORIZ_FUNC_A * (i^2)) + (GRID_HORIZ_FUNC_B * i)
+ GRID_TOP_YI

local xi = (y - GRID_RIGHT_SLOPE_ADD) / GRID_RIGHT_SLOPE
local xf = (y - GRID_LEFT_SLOPE_ADD) / GRID_LEFT_SLOPE

love.graphics.line(xi, y, xf, y)
end

love.graphics.setColor(255, 0, 0)

love.graphics.line(GRID_BOTTOM_XI, GRID_BOTTOM_YI,
GRID_TOP_XF, GRID_TOP_YF)

love.graphics.line(GRID_TOP_XI, GRID_TOP_YI,
GRID_BOTTOM_XF, GRID_BOTTOM_YF)
end
And the results:

Pic 1
Pic 2
Pic 3
Pic 4

osuf oboys
Party member
Posts: 215
Joined: Sun Jan 18, 2009 8:03 pm

### Re: Drawing a perspective grid (Solved)

That's not entirely correct but looks good. Normally, you would compute the angle of the considered in-world point relative the point you're looking from. From this angle, you choose a screen coordinate (e.g. by subtracting something and then multiplying with something). This is easiest to compute first for a point straight ahead but below you. In other words, given the line OA (where O is where your eyes are at and A is the point we're computing), find it's angle from the direction you're looking in. I.e. let B be a point with O's y-coordinate and a large X-coordinate (we don't care which), then compute the angle BOA. For instance, O could be (0,2) and A could be (10, 0), so we let B be (10,2) and want the angle of O in this triangle. (math.atan2 is probably the most suitable for this)
If I haven't written anything else, you may assume that my work is released under the LPC License - the LÖVE Community. See http://love2d.org/wiki/index.php?title=LPC_License.

### Who is online

Users browsing this forum: No registered users and 23 guests