Compare commits

...

4 Commits

Author SHA1 Message Date
binarycat
577b7576cf added level in new format to repo 2022-03-16 14:21:35 -04:00
binarycat
fa4b2c86b5 somewhat kinda got things working again 2022-03-16 13:54:25 -04:00
binarycat
e8cef497d4 reworking level loading logic 2022-03-16 13:54:25 -04:00
binarycat
b3a12305da trying to do chunked level loading 2022-03-16 13:54:24 -04:00
9 changed files with 164 additions and 169 deletions

51
code/chunk.lua Normal file
View File

@ -0,0 +1,51 @@
-- pieces of levels
Chunk = {all = {}}
Chunk.__index = Chunk
-- CLASS METHODS
-- box == nil for global chunks
function Chunk:new(filename, box)
local o = { filename = filename, box = box }
setmetatable(o, self)
self.all[o] = true
end
function Chunk:getExportList()
local r = {}
for chunk in pairs(self.all) do
table.insert(r, {chunk.filename, chunk.box})
end
return r
end
-- INSTANCE METHODS
function Chunk:containsPoint(pt)
return self.box == nil or self.box:containsPoint(pt)
end
function Chunk:load()
if self.loaded then
return
end
logPrint("loading chunk "..self.filename)
self.data = dofile(level_current.."/chunks/"..self.filename)
self.loaded = { rooms = {}, collisions = {} }
LevelTiles = self.data.tiles
indexLevelTiles()
optimizeTileObjects(self.loaded.collisions)
for _, v in ipairs(self.data.rooms or {}) do
local room = Collision:new(v[1],v[2],v[3],v[4])
table.insert(self.data.rooms, room)
table.insert(LoadedObjects.Rooms, room)
end
logPrint("loaded chunk with "..#self.loaded.collisions.." collisions")
end
function Chunk:save(chunkdir)
return love.filesystem.write(chunkdir.."/"..self.filename, "return "..serialize_lua_value(self.data))
end

View File

@ -100,7 +100,7 @@ function stepEditor()
if name_prompt.canceled then return end if name_prompt.canceled then return end
Prompt:new({ Prompt:new({
name = "filename", name = "filename",
input = "level.lua", input = "unnamed_level",
func = function(file_prompt) func = function(file_prompt)
if file_prompt.canceled then return end if file_prompt.canceled then return end
exportLevel(name_prompt.input, file_prompt.input) exportLevel(name_prompt.input, file_prompt.input)

View File

@ -20,7 +20,6 @@ function drawGameworldBackground()
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then if LevelTiles[i][j].id ~= 0 then
local depth = TileData[LevelTiles[i][j].id].depth local depth = TileData[LevelTiles[i][j].id].depth
drawTile( drawTile(
LevelTiles[i][j], LevelTiles[i][j],

View File

@ -1,90 +1,51 @@
function exportLevel(levelname, filename) function exportLevel(levelname, dirname)
love.filesystem.createDirectory("export") dirname = "export/"..dirname
filename = filename or "output.lua"
if string.sub(filename, 1, 1) ~= "/" then if love.filesystem.exists(dirname) then
filename = "export/"..filename -- TODO: prompt to overwrite
error("file already exists")
end
local ok = love.filesystem.createDirectory(dirname)
if not ok then
logPrint("error creating directory")
end end
exportFile = io.open(filename, "w+")
if exportFile then
logPrint("Exporting level \"".. levelname .. "\"...")
exportFile:write("return {")
logPrint("- level name") logPrint("Exporting level \"".. levelname .. "\"...")
exportFile:write("\n name = \"" .. levelname .. "\",") local exportTable = {}
exportTable.name = levelname
logPrint("- tileset") exportTable.tileset = "library"
for k, v in pairs(tileset) do exportTable.properties = LevelData.properties
if v == LevelData.tileset then --exportTable.tiles = LevelTiles
exportFile:write("\n tileset = tileset." .. k .. ",") --logPrint("- objects")
end --exportTable.objects = { spawns = {}, rooms = {} }
end --logPrint(" - spawns")
--for i, v in ipairs(LoadedObjects.Spawns) do
logPrint("- properties") --exportTable.objects.spawns = {v.archetype.name,{},v.args}
exportFile:write("\n properties = {") --end
logPrint(" - darkness: ".. tostring(LevelData.properties.darkness))
exportFile:write("\n darkness = " .. tostring(LevelData.properties.darkness)) --logPrint(" - rooms")
exportFile:write("\n },")
--for i, room in ipairs(LoadedObjects.Rooms) do
logPrint("- tiles") --- table.insert(exportTable.objects.rooms,{room:asRect():getCoords()})
exportFile:write("\n tiles = {") --end
local rows = #LevelTiles exportTable.chunks = Chunk:getExportList()
for i = 1, #LevelTiles do logPrint("Writing to file...")
if i > 1 then local ok, err = love.filesystem.write(dirname.."/level.lua", "return "..serialize_lua_value(exportTable))
exportFile:write(", ")
end if ok then
exportFile:write("\n { ") logPrint("Saving chunks...")
for j = 1, #LevelTiles[i] do local chunkdir = dirname.."/chunks"
if j ~= 1 then love.filesystem.createDirectory(chunkdir)
exportFile:write(", ") for chunk in pairs(Chunk.all) do
end local ok, err = chunk:save(chunkdir)
exportFile:write(tostring(LevelTiles[i][j].id)) if not ok then error(err) end
end end
exportFile:write("}") logPrint("Exporting complete.")
logPrint(" - row "..i.."/"..rows.." "..math.floor(100*((i-1)*100/rows))/100 .."%") else
end -- TODO: clean up created files
exportFile:write("\n },") logPrint("Exporting failed: "..err)
logPrint("- objects")
exportFile:write("\n objects = {")
logPrint(" - spawns")
exportFile:write("\n spawns = {")
for i, v in ipairs(LoadedObjects.Spawns) do
if i > 1 then
exportFile:write(",")
end
exportFile:write("\n {")
exportFile:write(v.archetype.type)
exportFile:write(",{")
for i=1, #v.args do
if i > 1 then
exportFile:write(",")
end
exportFile:write(v.args[i])
end
exportFile:write("}}")
end
exportFile:write("\n },")
logPrint(" - rooms")
exportFile:write("\n rooms = {")
for i, room in ipairs(LoadedObjects.Rooms) do
if i > 1 then
exportFile:write(",")
end
exportFile:write("\n {{")
exportFile:write(room.from.x)
exportFile:write(",")
exportFile:write(room.from.y)
exportFile:write("},{")
exportFile:write(room.to.x)
exportFile:write(",")
exportFile:write(room.to.y)
exportFile:write("}}")
end
exportFile:write("\n },")
exportFile:write("\n },")
logPrint("Exporting complete.")
exportFile:write("\n}")
exportFile:close()
end end
end end

View File

@ -1,7 +1,25 @@
function loadLevelTiles() function loadLevelTiles()
math.randomseed(3) math.randomseed(3)
LevelData = dofile("data/levels/"..level_current) level_current = "data/levels/level1"
LevelData = dofile(level_current.."/level.lua")
LoadedObjects.Collisions = {}
LoadedObjects.Platforms = {}
LoadedObjects.Ladders = {}
LoadedObjects.Hazards = {}
if type(LevelData.tileset) == "string" then
LevelData.tileset_name = LevelData.tileset
end
LevelData.tileset = tileset[LevelData.tileset_name]
getLevelTileData()
for _, v in ipairs(LevelData.chunks) do
Chunk:new(v[1], v[2])
end
local global_chunk = next(Chunk.all)
global_chunk:load()
LoadedObjects.Collisions = global_chunk.loaded.collisions
LevelTiles = global_chunk.data.tiles
--[[ --[[
on level format: on level format:
@ -12,26 +30,26 @@ function loadLevelTiles()
overlay_depth = foreground/background overlay depth overlay_depth = foreground/background overlay depth
type = collision type type = collision type
]] ]]
getLevelTileData()
LevelTiles = LevelData.tiles
updateLevelDimensions() updateLevelDimensions()
indexLevelTiles() --
createTileObjects() --createTileObjects()
createRoomObjects() --createRoomObjects()
getSpawns() --getSpawns()
end end
function createRoomObjects() function createRoomObjects()
LoadedObjects.Rooms = {} LoadedObjects.Rooms = {}
for _, v in pairs(LevelData.objects.rooms) do for _, v in pairs(LevelData.objects.rooms) do
table.insert(LoadedObjects.Rooms, Collision:new(v[1][1],v[1][2],v[2][1],v[2][2])) table.insert(LoadedObjects.Rooms, Collision:new(v[1],v[2],v[3],v[4]))
end end
end end
function getSpawns() function getSpawns()
LoadedObjects.Spawns = {} LoadedObjects.Spawns = {}
for _, v in pairs(LevelData.objects.spawns) do for _, v in pairs(LevelData.objects.spawns) do
addSpawn(v[1],unpack(v[2])) --addSpawn(v[1],unpack(v[2]))
end end
end end
@ -121,11 +139,8 @@ function reduceLevelCanvas(horizontal,vertical)
end end
function getLevelTileData() function getLevelTileData()
for k, v in pairs(tileset) do TileData = dofile("data/tileset/"..LevelData.tileset_name..".lua")
if v == LevelData.tileset then
TileData = dofile("data/tileset/"..k..".lua")
end
end
end end
function reloadLevelTiles() function reloadLevelTiles()
@ -159,10 +174,10 @@ end
function indexLevelTiles() function indexLevelTiles()
TileIndex = {} TileIndex = {}
local this_tileset = LevelData.tileset
-- index from tileset -- index from tileset
local width = LevelData.tileset:getPixelWidth()/tile_properties.width local width = this_tileset:getPixelWidth()/tile_properties.width
local height = LevelData.tileset:getPixelHeight()/tile_properties.height local height = this_tileset:getPixelHeight()/tile_properties.height
for i = 0, height do for i = 0, height do
for j = 0, width do for j = 0, width do
TileIndex[i*width+j+1] = love.graphics.newQuad( TileIndex[i*width+j+1] = love.graphics.newQuad(
@ -170,7 +185,7 @@ function indexLevelTiles()
i*tile_properties.height, i*tile_properties.height,
tile_properties.width, tile_properties.width,
tile_properties.height, tile_properties.height,
LevelData.tileset:getDimensions() this_tileset:getDimensions()
) )
end end
end end
@ -220,6 +235,9 @@ end
function instanceTile(id) function instanceTile(id)
local tile = {} local tile = {}
if type(id) == "table" then
id = id.id
end
tile.id = id tile.id = id
local Properties = TileData[tile.id] local Properties = TileData[tile.id]
@ -258,7 +276,7 @@ function drawGridDisplay()
end end
end end
function optimizeTileObjects() function optimizeTileObjects(dest)
logPrint("Optimizing Objects...") logPrint("Optimizing Objects...")
local unoptimized = 0 local unoptimized = 0
local isTileOptimized = {} local isTileOptimized = {}
@ -270,8 +288,9 @@ function optimizeTileObjects()
end end
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then if LevelTiles[i][j].id ~= 0 and TileData[LevelTiles[i][j].id] then
local type = TileData[LevelTiles[i][j].id].type local tile_dat = TileData[LevelTiles[i][j].id]
local type = tile_dat.type
if type == "whole" and not isTileOptimized[i][j] then if type == "whole" and not isTileOptimized[i][j] then
isTileOptimized[i][j] = true isTileOptimized[i][j] = true
local n = 1 local n = 1
@ -337,29 +356,27 @@ function optimizeTileObjects()
base_x + tile_properties.width * tile_properties.scale * n, base_x + tile_properties.width * tile_properties.scale * n,
base_y + tile_properties.height * tile_properties.scale * m base_y + tile_properties.height * tile_properties.scale * m
) )
table.insert(LoadedObjects.Collisions,col) table.insert(dest,col)
end end
end end
end end
end end
logPrint("collisions optimized from " .. unoptimized .. " to " .. #LoadedObjects.Collisions) --logPrint("collisions optimized from " .. unoptimized .. " to " .. #LoadedObjects.Collisions)
end end
function createTileObjects() -- currently broken
LoadedObjects.Collisions = {} function createTileObjects(dest)
LoadedObjects.Platforms = {}
LoadedObjects.Ladders = {}
LoadedObjects.Hazards = {}
optimizeTileObjects()
optimizeTileObjects(dest.collisions)
for i = 1, #LevelTiles do for i = 1, #LevelTiles do
for j = 1, #LevelTiles[i] do for j = 1, #LevelTiles[i] do
if LevelTiles[i][j].id ~= 0 then if LevelTiles[i][j].id ~= 0 then
local tile_dat = TileData[LevelTiles[i][j].id] or {}
local type = TileData[LevelTiles[i][j].id].type local type = tile_dat.type
local light = TileData[LevelTiles[i][j].id].light local light = tile_dat.light
local base_x = tile_properties.scale * j * tile_properties.width + tile_properties.scale * (level_properties.offset.x - tile_properties.height) local base_x = tile_properties.scale * j * tile_properties.width + tile_properties.scale * (level_properties.offset.x - tile_properties.height)
local base_y = tile_properties.scale * i * tile_properties.height + tile_properties.scale * (level_properties.offset.y - tile_properties.height) local base_y = tile_properties.scale * i * tile_properties.height + tile_properties.scale * (level_properties.offset.y - tile_properties.height)
@ -372,6 +389,9 @@ function createTileObjects()
) )
end end
local col
local list = dest.collisions
-- wholes are handled in optimization now -- wholes are handled in optimization now
--[[if type == "whole" then --[[if type == "whole" then
local col = Collision:new( local col = Collision:new(
@ -383,33 +403,33 @@ function createTileObjects()
table.insert(LoadedObjects.Collisions,col) table.insert(LoadedObjects.Collisions,col)
else]]if type == "half_bottom" then else]]if type == "half_bottom" then
local col = Collision:new( col = Collision:new(
base_x, base_x,
base_y + tile_properties.height/2 * tile_properties.scale, base_y + tile_properties.height/2 * tile_properties.scale,
base_x + tile_properties.width * tile_properties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tile_properties.height * tile_properties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col)
elseif type == "half_top" then elseif type == "half_top" then
local col = Collision:new( col = Collision:new(
base_x, base_x,
base_y , base_y ,
base_x + tile_properties.width * tile_properties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tile_properties.height/2 * tile_properties.scale base_y + tile_properties.height/2 * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col)
elseif type == "half_right" then elseif type == "half_right" then
local col = Collision:new( col = Collision:new(
base_x + tile_properties.height/2 * tile_properties.scale, base_x + tile_properties.height/2 * tile_properties.scale,
base_y, base_y,
base_x + tile_properties.width * tile_properties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tile_properties.height * tile_properties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Collisions,col)
elseif type == "half_left" then elseif type == "half_left" then
@ -580,7 +600,8 @@ function createTileObjects()
end end
elseif type == "ladder_right" then -- TODO: fix ladders
--[[elseif type == "ladder_right" then
local ladder = Collision:new( local ladder = Collision:new(
base_x + (tile_properties.width-4)* tile_properties.scale, base_x + (tile_properties.width-4)* tile_properties.scale,
@ -638,7 +659,7 @@ function createTileObjects()
) )
table.insert(LoadedObjects.Platforms,plat) table.insert(LoadedObjects.Platforms,plat)
elseif type == "bottom_hazard" then ]]elseif type == "bottom_hazard" then
local hazard = Collision:new( local hazard = Collision:new(
@ -647,9 +668,10 @@ function createTileObjects()
base_x + tile_properties.width * tile_properties.scale, base_x + tile_properties.width * tile_properties.scale,
base_y + tile_properties.height * tile_properties.scale base_y + tile_properties.height * tile_properties.scale
) )
table.insert(LoadedObjects.Hazards,hazard) list = dest.hazards
end end
table.insert(list, col)
end end
end end
end end

View File

@ -7,6 +7,7 @@ require "data/sfx"
require "code/locale" require "code/locale"
-- support functions -- support functions
require "code/serialize"
require "code/math" require "code/math"
require "code/draw" require "code/draw"
require "code/hex" require "code/hex"
@ -15,6 +16,7 @@ require "code/in_out"
-- classes -- classes
require "code/point" require "code/point"
require "code/rect" require "code/rect"
require "code/chunk"
require "code/objects" require "code/objects"
require "code/level" require "code/level"
require "code/camera" require "code/camera"

View File

@ -1,42 +0,0 @@
return {
name = "Dev Level",
tileset = tileset.library,
properties = {
darkness = false
},
tiles = {
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 4, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 4, 0, 0, 0, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 13, 13, 13, 13, 13, 13, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 1, 1, 1, 1, 1, 1, 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
},
objects = {
spawns = {
{Fairy,{100,88}},
{HookAnchor,{200,89,100}},
{HookAnchor,{400,89,120}}
},
rooms = {
{{96,64},{544,320}},
{{0,0},{112,176}}
},
},
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
return {[ [[tileset]] ]=[[library]],[ [[chunks]] ]={[ 1 ]={[ 1 ]=[[global.lua]],},},[ [[name]] ]=[[unnamed]],[ [[properties]] ]={[ [[darkness]] ]=false,},}