Mothback/data/scripts/level.lua

582 lines
17 KiB
Lua

function LevelLoadTiles()
--[[
on level format:
id = tile identifier
depth = order in the render
force = rendering other tile instead of the one in this position
overlay = render another tile id or, if multiple tiles {id, id, id,} or
overlay_depth = foreground/background overlay depth
type = collision type
]]
LevelData = dofile("Mothback/data/levels/"..currLevel..".lua")
Tiles = dofile("Mothback/data/tileset/library.lua")
LevelTiles = LevelData.tiles
LevelData.Width = LevelGetWidth()
LevelData.Height = LevelGetHeight()
LevelIndexTiles()
TileCreateObjects()
end
function LevelGetHeight()
return #LevelTiles * tileProperties.height
end
function LevelGetWidth()
local width = 0
for i = 1, #LevelTiles do
if width < #LevelTiles[i] then width = #LevelTiles[i] end
end
return width * tileProperties.width
end
function LevelIndexTiles()
TileIndex = {}
-- number of tiles in tileset!
local width = LevelData.tileset:getPixelWidth()/tileProperties.width
local height = LevelData.tileset:getPixelHeight()/tileProperties.height
for i = 0, height do
for j = 0, width do
TileIndex[i*width+j+1] = love.graphics.newQuad(
j*tileProperties.width,
i*tileProperties.height,
tileProperties.width,
tileProperties.height,
LevelData.tileset:getDimensions()
)
end
end
-- init animated tile properties
for _, properties in pairs(Tiles) do
if properties.animation ~= nil then
properties.tileset = love.graphics.newImage("assets/terrain/"..properties.animation..".png")
properties.imgs = {}
properties.current_image = 1
properties.current_subimage = 1
local tileset = properties.tileset
local width = tileset:getPixelWidth()/tileProperties.width
local height = tileset:getPixelHeight()/tileProperties.height
local image_count = 0
for i = 0, height-1 do
for j = 0, width-1 do
local quad =
love.graphics.newQuad(
j*tileProperties.width,
i*tileProperties.height,
tileProperties.width,
tileProperties.height,
tileset:getDimensions()
)
image_count = image_count + 1
table.insert(properties.imgs,quad)
end
end
properties.image_count = image_count
end
end
-- instance level tiles according to the properties
for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do
local id = LevelTiles[i][j]
LevelTiles[i][j] = {}
local tile = LevelTiles[i][j]
tile.id = id
for _, properties in pairs(Tiles) do
if properties.id == tile.id then
if type(properties.overlay) == "table" then
tile.display_overlay = properties.overlay[math.random(#properties.overlay)]
else
tile.display_overlay = properties.overlay
end
if type(properties.force) == "table" then
tile.display = properties.force[math.random(#properties.force)]
else
tile.display = properties.force
end
end
end
end
end
end
function LevelDisplayForeground()
for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then
local depth = TileGetDepth(LevelTiles[i][j])
DrawTile(
LevelTiles[i][j],
tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.width) - Camera.pos.x,
tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) - Camera.pos.y,
"foreground"
)
end
end
end
end
function LevelDisplayBackground()
love.graphics.setColor(0.7,0.7,0.7)
for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then
local depth = TileGetDepth(LevelTiles[i][j])
DrawTile(
LevelTiles[i][j],
tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.width) - Camera.pos.x,
tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) - Camera.pos.y,
"background"
)
end
end
end
love.graphics.setColor(1,1,1)
end
function TileGetType(tile)
for _, properties in ipairs(Tiles) do
if properties.id == tile.id then
return properties.type
end
end
end
function TileGetDepth(tile)
for _, properties in ipairs(Tiles) do
if properties.id == tile.id then
return properties.depth
end
end
end
function TileGetLight(tile)
for _, properties in ipairs(Tiles) do
if properties.id == tile.id then
return properties.light
end
end
end
function GridDisplay()
for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do
love.graphics.rectangle(
"line",
tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.width) - Camera.pos.x,
tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height) - Camera.pos.y,
tileProperties.scale * tileProperties.width,
tileProperties.scale * tileProperties.height
)
end
end
end
function TileCreateObjects()
objects.collisions = {}
objects.platforms = {}
objects.ladders = {}
for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then
local type = TileGetType(LevelTiles[i][j])
local light = TileGetLight(LevelTiles[i][j])
local base_x = tileProperties.scale * j * tileProperties.width + tileProperties.scale * (levelProperties.offset.x - tileProperties.height)
local base_y = tileProperties.scale * i * tileProperties.height + tileProperties.scale * (levelProperties.offset.y - tileProperties.height)
if light ~= 0 and light ~= nil then
CreateLight(
base_x + tileProperties.width/2 * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale,
light
)
end
if type == "whole" then
local col = Collision:New(
base_x,
base_y,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "half_bottom" then
local col = Collision:New(
base_x,
base_y + tileProperties.height/2 * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "half_top" then
local col = Collision:New(
base_x,
base_y ,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "half_right" then
local col = Collision:New(
base_x + tileProperties.height/2 * tileProperties.scale,
base_y,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "half_left" then
local col = Collision:New(
base_x,
base_y,
base_x + tileProperties.height/2 * tileProperties.scale,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "platform" then
local plat = Collision:New(
base_x,
base_y + tileProperties.scale * 2,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2
)
table.insert(objects.platforms,plat)
elseif type == "ramp2_bot_left_whole" then
for k = 1, 8 do
-- do ramp owo
local slope = Collision:New(
base_x,
base_y + k * tileProperties.scale - tileProperties.scale,
base_x + k * 2 * tileProperties.scale,
base_y + k * tileProperties.scale
)
table.insert(objects.collisions,slope)
end
-- fill lower half
local col = Collision:New(
base_x,
base_y + tileProperties.height/2 * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "ramp2_bot_left_half" then
for k = 1, 8 do
-- do ramp owo
local slope = Collision:New(
base_x,
base_y + tileProperties.height/2 * tileProperties.scale + k * tileProperties.scale - tileProperties.scale,
base_x + k * 2 * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale + k * tileProperties.scale
)
table.insert(objects.collisions,slope)
end
elseif type == "ramp2_top_left_whole" then
for k = 1, 8 do
-- do ramp owo
local slope = Collision:New(
base_x,
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale - (k-1) * 2 * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale + tileProperties.scale
)
table.insert(objects.collisions,slope)
end
-- fill higher half
local col = Collision:New(
base_x,
base_y,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "ramp2_top_left_half" then
for k = 1, 8 do
-- do ramp owo
local slope = Collision:New(
base_x,
base_y - tileProperties.scale + k * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale - (k-1) * 2 * tileProperties.scale,
base_y - tileProperties.scale + k * tileProperties.scale + tileProperties.scale
)
table.insert(objects.collisions,slope)
end
elseif type == "ramp2_bot_right_whole" then
for k = 1, 8 do
-- do ramp owo
local slope = Collision:New(
base_x + (k-8) * -2 * tileProperties.scale,
base_y - tileProperties.scale + k * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale,
base_y - tileProperties.scale + k * tileProperties.scale + tileProperties.scale
)
table.insert(objects.collisions,slope)
end
-- fill lower half
local col = Collision:New(
base_x,
base_y + tileProperties.height/2 * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "ramp2_bot_right_half" then
for k = 1, 8 do
-- do ramp owo
local slope = Collision:New(
base_x + (k-8) * -2 * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - tileProperties.scale + k * tileProperties.scale + tileProperties.scale
)
table.insert(objects.collisions,slope)
end
elseif type == "ramp2_top_right_half" then
for k = 1, 8 do
-- do ramp owo
local slope = Collision:New(
base_x + (k-8) * -2 * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale + tileProperties.scale
)
table.insert(objects.collisions,slope)
end
elseif type == "ramp2_top_right_whole" then
for k = 1, 8 do
-- do ramp owo
local slope = Collision:New(
base_x + (k-8) * -2 * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale + tileProperties.height/2 * tileProperties.scale - k * tileProperties.scale + tileProperties.scale
)
table.insert(objects.collisions,slope)
end
-- fill higher half
local col = Collision:New(
base_x,
base_y,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/2 * tileProperties.scale
)
table.insert(objects.collisions,col)
elseif type == "ramp1_bot_left" then
for k = 1, 16 do
-- do ramp owo
local slope = Collision:New(
base_x,
base_y + k * tileProperties.scale - tileProperties.scale,
base_x + k * tileProperties.scale,
base_y + k * tileProperties.scale
)
table.insert(objects.collisions,slope)
end
elseif type == "ladder_right" then
local ladder = Collision:New(
base_x + (tileProperties.width-4)* tileProperties.scale,
base_y,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.ladders,ladder)
elseif type == "ladder_platform_right" then
local ladder = Collision:New(
base_x + (tileProperties.width-4)* tileProperties.scale,
base_y + tileProperties.scale * 2,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.ladders,ladder)
local plat = Collision:New(
base_x,
base_y + tileProperties.scale * 2,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2
)
table.insert(objects.platforms,plat)
elseif type == "ladder_left" then
local ladder = Collision:New(
base_x,
base_y,
base_x + tileProperties.scale * 4,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.ladders,ladder)
elseif type == "ladder_platform_left" then
local ladder = Collision:New(
base_x,
base_y + tileProperties.scale * 2,
base_x + tileProperties.scale * 4,
base_y + tileProperties.height * tileProperties.scale
)
table.insert(objects.ladders,ladder)
local plat = Collision:New(
base_x,
base_y + tileProperties.scale * 2,
base_x + tileProperties.width * tileProperties.scale,
base_y + tileProperties.height/4 * tileProperties.scale + tileProperties.scale * 2
)
table.insert(objects.platforms,plat)
end
end
end
end
end
function AnimateTiles()
for _, properties in pairs(Tiles) do
if properties.animation ~= nil then
-- calculate subimage
properties.current_subimage = properties.current_subimage + current_dt
-- cycle image
if properties.current_subimage >= properties.delay then
properties.current_subimage = properties.current_subimage - properties.delay
properties.current_image = properties.current_image + 1
end
if properties.current_image > properties.image_count then
properties.current_image = properties.current_image - properties.image_count
end
end
end
end
function DrawTile(tile,x,y,depth)
for _, properties in pairs(Tiles) do
if tile.id == properties.id then
if properties.animation ~= nil then
if properties.imgs[properties.current_image] ~= nil
and properties.depth == depth
then love.graphics.draw(
properties.tileset,
properties.imgs[properties.current_image],
x,
y,
0,
tileProperties.scale,
tileProperties.scale
) end
elseif properties.depth == depth then
if properties.force ~= nil then
if properties.force ~= 0 then
love.graphics.draw(
LevelData.tileset,
TileIndex[tile.display],
x,
y,
0,
tileProperties.scale,
tileProperties.scale
)
end
else
love.graphics.draw(
LevelData.tileset,
TileIndex[properties.id],
x,
y,
0,
tileProperties.scale,
tileProperties.scale
)
end
end
if properties.overlay ~= nil then
if properties.overlay_depth == depth or properties.overlay_depth == nil and properties.depth == depth then
if properties.overlay_animated then
for _, overlay_properties in pairs(Tiles) do
if overlay_properties.id == properties.overlay then
love.graphics.draw(
overlay_properties.tileset,
overlay_properties.imgs[overlay_properties.current_image],
x,
y,
0,
tileProperties.scale,
tileProperties.scale
)
end
end
else
love.graphics.draw(
LevelData.tileset,
TileIndex[tile.display_overlay],
x,
y,
0,
tileProperties.scale,
tileProperties.scale
)
end
end
end
--[[
love.graphics.setColor(0,0,1)
love.graphics.print(tostring(tile.display),x+16,y)
love.graphics.setColor(1,1,1)
]]
end
end
end