264 lines
7.6 KiB
Lua
264 lines
7.6 KiB
Lua
-- debug --
|
|
if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == "1" then
|
|
DEBUG = false -- enable with f10
|
|
local lldebugger = require('lldebugger')
|
|
lldebugger.start()
|
|
---@diagnostic disable-next-line: undefined-field
|
|
local run = love.run
|
|
function love.run(...)
|
|
local f = lldebugger.call(run, false, ...)
|
|
return function(...) return lldebugger.call(f, false, ...) end
|
|
end
|
|
end
|
|
print('debug:', DEBUG)
|
|
|
|
-- libraries --
|
|
---@type Object
|
|
Object = require 'lib/classic/classic'
|
|
---@type Baton
|
|
Baton = require 'lib/baton/baton'
|
|
---@type Timer
|
|
Timer = require 'lib/hump/timer'
|
|
|
|
HC = require 'lib/hc'
|
|
|
|
Camera = require 'lib/cameramod/camera'
|
|
require 'lib/cameramod/Shake'
|
|
|
|
-- generic objects --
|
|
Room = require 'obj/Room'
|
|
Area = require 'obj/Area'
|
|
GameObject = require 'obj/GameObject'
|
|
|
|
function love.load()
|
|
-- table of color palette
|
|
COLORS = {
|
|
default = {1,1,1,1},
|
|
bg = {.05,.05,.05,1},
|
|
ammo = {1,1,1,1},
|
|
boost = {1,1,1,1},
|
|
hp = {.8,.1,.1,1},
|
|
skill_point = {1,1,1,1},
|
|
collision = {1,0.4,0.4,1},
|
|
debug = {0.4,1,0.4,1}
|
|
}
|
|
|
|
-- screen setup
|
|
love.graphics.setDefaultFilter("nearest")
|
|
love.graphics.setLineStyle("rough")
|
|
resize(2)
|
|
|
|
---@type Room|nil
|
|
current_room = nil
|
|
|
|
-- load game objects
|
|
local game_objects = {}
|
|
print('loading game objects:')
|
|
recursiveEnumerate('obj/game', game_objects)
|
|
for _,v in ipairs(game_objects) do print('',v) end
|
|
requireFiles(game_objects, true)
|
|
|
|
-- load rooms
|
|
local room_files = {}
|
|
print('loading rooms:')
|
|
recursiveEnumerate('rooms', room_files)
|
|
for _,v in ipairs(room_files) do print('',v) end
|
|
requireFiles(room_files, true)
|
|
|
|
-- load input
|
|
input = Baton.new {
|
|
controls = {
|
|
left = {'key:left', 'key:a'},
|
|
right = {'key:right', 'key:d'},
|
|
up = {'key:up', 'key:w'},
|
|
down = {'key:down', 'key:s'},
|
|
action = {'key:z', 'key:space'},
|
|
|
|
f1 = {'key:f1'}, f2 = {'key:f2'}, f3 = {'key:f3'},
|
|
f10 = {'key:f10'}, f11 = {'key:f11'}, f12 = {'key:f12'}
|
|
},
|
|
pairs = {
|
|
move = {'left', 'right', 'up', 'down'}
|
|
}
|
|
}
|
|
camera = Camera()
|
|
|
|
gotoRoom('Stage')
|
|
end
|
|
|
|
function love.update(dt)
|
|
if current_room then current_room:update(dt) end
|
|
input:update(dt)
|
|
if input:pressed('f1') then gotoRoom('CircleRoom') end
|
|
if input:pressed('f2') and DEBUG then
|
|
-- global debug breakpoint
|
|
print('break')
|
|
end
|
|
if input:pressed('f3') then camera:shake(4, 60, 1) end
|
|
if input:pressed('f10') then
|
|
if DEBUG then
|
|
print('setting DEBUG to false...')
|
|
DEBUG = false
|
|
else
|
|
print('setting DEBUG to true...')
|
|
DEBUG = true
|
|
end
|
|
end
|
|
if input:pressed('f12') then
|
|
print("-------------------------------------")
|
|
print("Before collection: " .. collectgarbage("count")/1024)
|
|
collectgarbage()
|
|
print("After collection: " .. collectgarbage("count")/1024)
|
|
print("Object count: ")
|
|
local counts = type_count()
|
|
for k, v in pairs(counts) do print(k, v) end
|
|
print("-------------------------------------")
|
|
end
|
|
camera:update(dt)
|
|
end
|
|
|
|
function love.draw()
|
|
if current_room then current_room:draw() end
|
|
end
|
|
|
|
---Enumerates files in a folder and inserts them to a provided table.
|
|
---@param folder string path to folder to scan
|
|
---@param file_list table table to be inserted to
|
|
function recursiveEnumerate(folder, file_list)
|
|
local items = love.filesystem.getDirectoryItems(folder)
|
|
for _, item in ipairs(items) do
|
|
local file = folder .. '/' .. item
|
|
local info = love.filesystem.getInfo(file)
|
|
|
|
if info then -- exists (covers both files and directories)
|
|
if info.type == "file" then
|
|
table.insert(file_list, file)
|
|
elseif info.type == "directory" then
|
|
recursiveEnumerate(file, file_list)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
---Load files table as lua modules.
|
|
---@param files table table containing files to be loaded
|
|
---@param should_return boolean|nil whether required files return a table/object
|
|
function requireFiles(files, should_return)
|
|
local returns = should_return or false
|
|
for _, file in ipairs(files) do
|
|
local module = file:sub(1, -5)
|
|
if not returns then require(module) else
|
|
local filename = module:match("([^/]+)$")
|
|
_G[filename] = require(module)
|
|
end
|
|
end
|
|
end
|
|
|
|
---Go to a specific room.
|
|
---@param room_type string the name of the room as registered
|
|
---@param ... any arguments passed to the room constructor
|
|
function gotoRoom(room_type, ...)
|
|
local Class = _G[room_type]
|
|
if not Class then
|
|
error("room '"..room_type.."' not found in _G")
|
|
end
|
|
if type(Class) ~= "table" and type(Class) ~= "function" then
|
|
error("room '"..room_type.."' is not callable (got "..type(Class)..", does room return itself?)")
|
|
end
|
|
if current_room and current_room.destroy then current_room:destroy() end
|
|
current_room = _G[room_type](...)
|
|
end
|
|
|
|
---Generates and returns random UUID string
|
|
---@return string
|
|
function UUID()
|
|
local fn = function(x)
|
|
local r = math.random(16) - 1
|
|
r = (x == "x") and (r + 1) or (r % 4) + 9
|
|
return ("0123456789abcdef"):sub(r, r)
|
|
end
|
|
return (("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"):gsub("[xy]", fn))
|
|
end
|
|
|
|
---Resize window
|
|
---@param s number scale setting
|
|
function resize(s)
|
|
love.window.setMode(s*gw, s*gh)
|
|
sx, sy = s, s
|
|
end
|
|
|
|
---Pushes a transformation stack for rotating and/or scaling
|
|
---@param x number horizontal coordinate to translate
|
|
---@param y number vertical coordinate to translate
|
|
---@param r number|nil angle to rotate
|
|
---@param sx number|nil horizontal scale
|
|
---@param sy number|nil vertical scale
|
|
function pushRotateScale(x, y, r, sx, sy)
|
|
love.graphics.push()
|
|
love.graphics.translate(x, y)
|
|
if r then love.graphics.rotate(r) end
|
|
if sx then love.graphics.scale(sx, sy or sx or 1) end
|
|
love.graphics.translate(-x, -y)
|
|
end
|
|
|
|
---Returns random number
|
|
---@param min number minimum of range
|
|
---@param max number maximum of range
|
|
---@return number
|
|
function random(min, max)
|
|
local min, max = min or 0, max or 1
|
|
return (min > max and (love.math.random()*(min - max) + max)) or (love.math.random()*(max - min) + min)
|
|
end
|
|
|
|
------------------------
|
|
-- garbage collection --
|
|
------------------------
|
|
|
|
---Counts all globals and applies function
|
|
---@param f function
|
|
function count_all(f)
|
|
local seen = {}
|
|
local count_table
|
|
count_table = function(t)
|
|
if seen[t] then return end
|
|
f(t)
|
|
seen[t] = true
|
|
for k,v in pairs(t) do
|
|
if type(v) == "table" then
|
|
count_table(v)
|
|
elseif type(v) == "userdata" then
|
|
f(v)
|
|
end
|
|
end
|
|
end
|
|
count_table(_G)
|
|
end
|
|
|
|
---Count all types of globals
|
|
---@return table
|
|
function type_count()
|
|
local counts = {}
|
|
local enumerate = function (o)
|
|
local t = type_name(o)
|
|
counts[t] = (counts[t] or 0) + 1
|
|
end
|
|
count_all(enumerate)
|
|
return counts
|
|
end
|
|
|
|
global_type_table = nil
|
|
---Resolves an object's true class name via metatable lookup.
|
|
---Caches results in `global_type_table` for speed.
|
|
---Fallbacks: "table" (no metatable), "Unknown" (uncached).
|
|
---@param o any Any object (table, userdata, etc.)
|
|
---@return string Class name (e.g., "Player", "Camera", "ImageData")
|
|
function type_name(o)
|
|
if global_type_table == nil then
|
|
global_type_table = {}
|
|
for k,v in pairs(_G) do
|
|
global_type_table[v] = k
|
|
end
|
|
global_type_table[0] = "table"
|
|
end
|
|
return global_type_table[getmetatable(o) or 0] or "Unknown"
|
|
end
|