Love2d Isometric Grid Framework Starting Point
Series: dev April 20, 2018
The following is an outline of a Love2D Isometric Framework. It is a complete love2d example that gives you an 8 by 8 isometric grid. You can use the functions to generate grids of tiles.
Here are some ways you can extend this starting point:
- Upgrade it to love 11.
- You could extend this by drawing sprites, animations, or graphics by writing additional functions like
draw_tile_border
,draw_tile_fill
to implement things like drawing sprites, animations, or specific shapes. - You could create additional tools to draw a different border just around the edge of the border.
- Turn it into its own library.
- Add a way of storing our constants in said library so we don’t just pass them all over the place.
- If you’re using big maps, you’ll want to switch from brute-forcing figuring out which tile you’re on.
- It’s something like:
- x = ((screen_x - x_off) / TH + screen_y / (TH / 2)) /2
- y = ((screen_y - y_off) / (TH/2) - (screen_x / TH)) /2
- It’s something like:
- Adding actual gameplay.
Please feel free to reach out via Twitter or Email if you do anything with this!
function love.load()
-- love.mouse.setVisible( false )
TW = 6
TH = 6
X_OFF = 100
Y_OFF = 50
TILE_H = 20
end
-- Overview
-- All of the functions have a few arguments that are pretty much the same for a project.
-- They should be refactored out, but they allow you to change the offset, number of tiles, and the tile height.
function love.draw()
W = {255,255,255,255} --WHITE
U = {0,0,255,255} --BLUE
B = {0,0,0,255} --BLACK
R = {255,0,0,255} --RED
G = {0,255,0,255} --GREEN
MG = {0,255,0,100} -- Mouse (Translucent) Green
C = {0,0,0,0} --CLEAR
map = {
{W,R,C,C},
{W,W,C,W},
{C,W,R,W},
{W,C,C,W}
}
draw_map_fill(map,X_OFF,Y_OFF,TW,TH,TILE_H)
if mouse_map_x ~= nil and mouse_map_y ~= nil then
draw_map_tile_fill(mouse_map_x,mouse_map_y,TW,TH,TILE_H,X_OFF,Y_OFF,MG)
end
draw_map_border(X_OFF,Y_OFF,TW,TH,TILE_H,G)
love.graphics.setColor(MG[1],MG[2],MG[3],MG[4])
love.graphics.points(mouse_x, mouse_y)
end
function love.update(dt)
mouse_x, mouse_y = love.mouse.getPosition( )
mouse_map_x, mouse_map_y = get_map_coords(mouse_x, mouse_y,X_OFF,Y_OFF,TW,TH,TILE_H)
end
-- Draws an isometric line with its bottom point at x,y, with a height from the bottom to top points.
-- The height acts as a scale for the tiles.
function draw_tile_border(x,y,height)
love.graphics.line(x, y, x+(2*height), y+height, x, y+(2*height), x-(2*height), y+height, x, y)
end
-- Fills a tile as above.
function draw_tile_fill(x,y,height,col)
love.graphics.setColor(col[1],col[2],col[3],col[4])
love.graphics.polygon('fill', x, y, x+(2*height), y+height, x, y+(2*height), x-(2*height), y+height, x, y)
end
-- This function takes a map coordinate, turns it into a tile coordinate, and draws a tile
function draw_map_tile_border(x,y,w,h,tile_height,x_off,y_off)
mx = ((4*tile_height)*(w/2))+((2*tile_height)*(x-y))
my = ((tile_height)*(y+x-2))
draw_tile_border(mx+x_off,my+y_off,tile_height)
end
-- Fills a map tile as above
function draw_map_tile_fill(x,y,w,h,tile_height,x_off,y_off,col)
mx = ((4*tile_height)*(w/2))+((2*tile_height)*(x-y))
my = ((tile_height)*(y+x-2))
draw_tile_fill(mx+x_off,my+y_off,tile_height,col)
end
-- Our map has the following coordinates:
-- 0,0
-- 0,1 1,0
-- 0,2 1,1 2,0
-- 1,2 2,1
-- 2,2
-- Draws the edges of a map in a given color.
function draw_map_border(x_off,y_off,width, height, tile_height,col)
love.graphics.setColor(col[1],col[2],col[3],col[4])
for ix=1,width,1 do
for iy=1,height,1 do
draw_map_tile_border(ix,iy,width,height,tile_height,x_off,y_off)
end
end
end
-- Fills in tiles of a map based on a 2d table, each cell of which contains a table of color values
function draw_map_fill(arr,x_off,y_off,w,h,th)
for x=1,#arr,1 do
for y=1,#arr[x],1 do
draw_map_tile_fill(x,y,w,h,th,x_off,y_off,arr[x][y])
end
end
end
-- Finds the x,y map coordinates based on screen coordinates
function get_map_coords(x,y,x_off,y_off,width,height,tile_height)
for ix=1,width,1 do
for iy=1,height,1 do
if tile_contains_point(ix,iy,x-x_off,y-y_off,width, height, tile_height) then
return ix, iy
end
end
end
return nil, nil
-- return 6,6
end
-- Checks if a tile on a map contains a point.
function tile_contains_point(tx,ty,px,py,w,h,th)
-- Get the center of the tile
cx = ((4*th)*(w/2))+((2*th)*(tx-ty))
cy = ((th)*(ty+tx-2))+th
if (math.abs(px-cx)/(2*th))+(math.abs(py-cy)/th) <= 1 then
return true
end
return false
end
function div(a,b)
return (a - a % b) / b
end