Add LuaPreprocess for asset-processing.
Rename image assets to match var names.
14
Makefile
|
@ -1,14 +1,18 @@
|
||||||
SOURCE_FILES := src/utils.lua src/constants.lua src/draw/* src/dbg.lua src/npc.lua src/announcer.lua src/graphics.lua src/main.lua
|
SOURCE_FILES := src/utils.lua src/constants.lua src/assets.lua src/draw/* src/dbg.lua src/npc.lua src/announcer.lua src/graphics.lua src/main.lua
|
||||||
|
GENERATED_FILES := src/assets.lua
|
||||||
|
|
||||||
all:
|
all:
|
||||||
pdc src BatterUp.pdx
|
pdc --skip-unknown src BatterUp.pdx
|
||||||
|
|
||||||
check:
|
assets:
|
||||||
stylua -c --indent-type Spaces src/
|
lua lib/preprocess-cl.lua src/assets.lua2p
|
||||||
|
|
||||||
|
check: assets
|
||||||
|
stylua -c --indent-type Spaces -g "*.lua" -g "!${GENERATEED_FILES}" src/
|
||||||
cat __stub.ext.lua <(sed 's/^function/-- selene: allow(unused_variable)\nfunction/' ${PLAYDATE_SDK_PATH}/CoreLibs/__types.lua) ${SOURCE_FILES} | grep -v '^import' | sed 's/<const>//g' | selene -
|
cat __stub.ext.lua <(sed 's/^function/-- selene: allow(unused_variable)\nfunction/' ${PLAYDATE_SDK_PATH}/CoreLibs/__types.lua) ${SOURCE_FILES} | grep -v '^import' | sed 's/<const>//g' | selene -
|
||||||
|
|
||||||
test: check
|
test: check
|
||||||
(cd src; find ./test -name '*lua' | xargs -L1 lua)
|
(cd src; find ./test -name '*lua' | xargs -L1 lua)
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
stylua --indent-type Spaces src/
|
stylua --indent-type Spaces -g "*.lua" -g "!${GENERATEED_FILES}" src/
|
||||||
|
|
|
@ -0,0 +1,651 @@
|
||||||
|
#!/bin/sh
|
||||||
|
_=[[
|
||||||
|
exec lua "$0" "$@"
|
||||||
|
]]and nil
|
||||||
|
--==============================================================
|
||||||
|
--=
|
||||||
|
--= LuaPreprocess command line program
|
||||||
|
--= by Marcus 'ReFreezed' Thunström
|
||||||
|
--=
|
||||||
|
--= Requires preprocess.lua to be in the same folder!
|
||||||
|
--=
|
||||||
|
--= License: MIT (see the bottom of this file)
|
||||||
|
--= Website: http://refreezed.com/luapreprocess/
|
||||||
|
--= Documentation: http://refreezed.com/luapreprocess/docs/command-line/
|
||||||
|
--=
|
||||||
|
--= Tested with Lua 5.1, 5.2, 5.3, 5.4 and LuaJIT.
|
||||||
|
--=
|
||||||
|
--==============================================================
|
||||||
|
local help = [[
|
||||||
|
|
||||||
|
Script usage:
|
||||||
|
lua preprocess-cl.lua [options] [--] filepath1 [filepath2 ...]
|
||||||
|
OR
|
||||||
|
lua preprocess-cl.lua --outputpaths [options] [--] inputpath1 outputpath1 [inputpath2 outputpath2 ...]
|
||||||
|
|
||||||
|
File paths can be "-" for usage of stdin/stdout.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
lua preprocess-cl.lua --saveinfo=logs/info.lua --silent src/main.lua2p src/network.lua2p
|
||||||
|
lua preprocess-cl.lua --debug src/main.lua2p src/network.lua2p
|
||||||
|
lua preprocess-cl.lua --outputpaths --linenumbers src/main.lua2p output/main.lua src/network.lua2p output/network.lua
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--backtickstrings
|
||||||
|
Enable the backtick (`) to be used as string literal delimiters.
|
||||||
|
Backtick strings don't interpret any escape sequences and can't
|
||||||
|
contain other backticks.
|
||||||
|
|
||||||
|
--data|-d="Any data."
|
||||||
|
A string with any data. If this option is present then the value
|
||||||
|
will be available through the global 'dataFromCommandLine' in the
|
||||||
|
processed files (and any message handler). Otherwise,
|
||||||
|
'dataFromCommandLine' is nil.
|
||||||
|
|
||||||
|
--faststrings
|
||||||
|
Force fast serialization of string values. (Non-ASCII characters
|
||||||
|
will look ugly.)
|
||||||
|
|
||||||
|
--handler|-h=pathToMessageHandler
|
||||||
|
Path to a Lua file that's expected to return a function or a
|
||||||
|
table of functions. If it returns a function then it will be
|
||||||
|
called with various messages as it's first argument. If it's
|
||||||
|
a table, the keys should be the message names and the values
|
||||||
|
should be functions to handle the respective message.
|
||||||
|
(See 'Handler messages' and tests/quickTestHandler*.lua)
|
||||||
|
The file shares the same environment as the processed files.
|
||||||
|
|
||||||
|
--help
|
||||||
|
Show this help.
|
||||||
|
|
||||||
|
--jitsyntax
|
||||||
|
Allow LuaJIT-specific syntax, specifically literals for 64-bit
|
||||||
|
integers, complex numbers and binary numbers.
|
||||||
|
(https://luajit.org/ext_ffi_api.html#literals)
|
||||||
|
|
||||||
|
--linenumbers
|
||||||
|
Add comments with line numbers to the output.
|
||||||
|
|
||||||
|
--loglevel=levelName
|
||||||
|
Set maximum log level for the @@LOG() macro. Can be "off",
|
||||||
|
"error", "warning", "info", "debug" or "trace". The default is
|
||||||
|
"trace", which enables all logging.
|
||||||
|
|
||||||
|
--macroprefix=prefix
|
||||||
|
String to prepend to macro names.
|
||||||
|
|
||||||
|
--macrosuffix=suffix
|
||||||
|
String to append to macro names.
|
||||||
|
|
||||||
|
--meta OR --meta=pathToSaveMetaprogramTo
|
||||||
|
Output the metaprogram to a temporary file (*.meta.lua). Useful if
|
||||||
|
an error happens when the metaprogram runs. This file is removed
|
||||||
|
if there's no error and --debug isn't enabled.
|
||||||
|
|
||||||
|
--nogc
|
||||||
|
Stop the garbage collector. This may speed up the preprocessing.
|
||||||
|
|
||||||
|
--nonil
|
||||||
|
Disallow !(expression) and outputValue() from outputting nil.
|
||||||
|
|
||||||
|
--nostrictmacroarguments
|
||||||
|
Disable checks that macro arguments are valid Lua expressions.
|
||||||
|
|
||||||
|
--novalidate
|
||||||
|
Disable validation of outputted Lua.
|
||||||
|
|
||||||
|
--outputextension=fileExtension
|
||||||
|
Specify what file extension generated files should have. The
|
||||||
|
default is "lua". If any input files end in .lua then you must
|
||||||
|
specify another file extension with this option. (It's suggested
|
||||||
|
that you use .lua2p (as in "Lua To Process") as extension for
|
||||||
|
unprocessed files.)
|
||||||
|
|
||||||
|
--outputpaths|-o
|
||||||
|
This flag makes every other specified path be the output path
|
||||||
|
for the previous path.
|
||||||
|
|
||||||
|
--release
|
||||||
|
Enable release mode. Currently only disables the @@ASSERT() macro.
|
||||||
|
|
||||||
|
--saveinfo|-i=pathToSaveProcessingInfoTo
|
||||||
|
Processing information includes what files had any preprocessor
|
||||||
|
code in them, and things like that. The format of the file is a
|
||||||
|
lua module that returns a table. Search this file for 'SavedInfo'
|
||||||
|
to see what information is saved.
|
||||||
|
|
||||||
|
--silent
|
||||||
|
Only print errors to the console. (This flag is automatically
|
||||||
|
enabled if an output path is stdout.)
|
||||||
|
|
||||||
|
--version
|
||||||
|
Print the version of LuaPreprocess to stdout and exit.
|
||||||
|
|
||||||
|
--debug
|
||||||
|
Enable some preprocessing debug features. Useful if you want
|
||||||
|
to inspect the generated metaprogram (*.meta.lua). (This also
|
||||||
|
enables the --meta option.)
|
||||||
|
|
||||||
|
--
|
||||||
|
Stop options from being parsed further. Needed if you have paths
|
||||||
|
starting with "-" (except for usage of stdin/stdout).
|
||||||
|
|
||||||
|
Handler messages:
|
||||||
|
"init"
|
||||||
|
Sent before any other message.
|
||||||
|
Arguments:
|
||||||
|
inputPaths: Array of file paths to process. Paths can be added or removed freely.
|
||||||
|
outputPaths: If the --outputpaths option is present this is an array of output paths for the respective path in inputPaths, otherwise it's nil.
|
||||||
|
|
||||||
|
"insert"
|
||||||
|
Sent for each @insert"name" statement. The handler is expected to return a Lua code string.
|
||||||
|
Arguments:
|
||||||
|
path: The file being processed.
|
||||||
|
name: The name of the resource to be inserted (could be a file path or anything).
|
||||||
|
|
||||||
|
"beforemeta"
|
||||||
|
Sent before a file's metaprogram runs, if a metaprogram is generated.
|
||||||
|
Arguments:
|
||||||
|
path: The file being processed.
|
||||||
|
luaString: The generated metaprogram.
|
||||||
|
|
||||||
|
"aftermeta"
|
||||||
|
Sent after a file's metaprogram has produced output (before the output is written to a file).
|
||||||
|
Arguments:
|
||||||
|
path: The file being processed.
|
||||||
|
luaString: The produced Lua code. You can modify this and return the modified string.
|
||||||
|
|
||||||
|
"filedone"
|
||||||
|
Sent after a file has finished processing and the output written to file.
|
||||||
|
Arguments:
|
||||||
|
path: The file being processed.
|
||||||
|
outputPath: Where the output of the metaprogram was written.
|
||||||
|
info: Info about the processed file. (See 'ProcessInfo' in preprocess.lua)
|
||||||
|
|
||||||
|
"fileerror"
|
||||||
|
Sent if an error happens while processing a file (right before the program exits).
|
||||||
|
Arguments:
|
||||||
|
path: The file being processed.
|
||||||
|
error: The error message.
|
||||||
|
|
||||||
|
"alldone"
|
||||||
|
Sent after all other messages (right before the program exits).
|
||||||
|
Arguments:
|
||||||
|
(none)
|
||||||
|
]]
|
||||||
|
--==============================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local startTime = os.time()
|
||||||
|
local startClock = os.clock()
|
||||||
|
|
||||||
|
local args = arg
|
||||||
|
|
||||||
|
if not args[0] then error("Expected to run from the Lua interpreter.") end
|
||||||
|
local pp = dofile((args[0]:gsub("[^/\\]+$", "preprocess.lua")))
|
||||||
|
|
||||||
|
-- From args:
|
||||||
|
local addLineNumbers = false
|
||||||
|
local allowBacktickStrings = false
|
||||||
|
local allowJitSyntax = false
|
||||||
|
local canOutputNil = true
|
||||||
|
local customData = nil
|
||||||
|
local fastStrings = false
|
||||||
|
local hasOutputExtension = false
|
||||||
|
local hasOutputPaths = false
|
||||||
|
local isDebug = false
|
||||||
|
local outputExtension = "lua"
|
||||||
|
local outputMeta = false -- flag|path
|
||||||
|
local processingInfoPath = ""
|
||||||
|
local silent = false
|
||||||
|
local validate = true
|
||||||
|
local macroPrefix = ""
|
||||||
|
local macroSuffix = ""
|
||||||
|
local releaseMode = false
|
||||||
|
local maxLogLevel = "trace"
|
||||||
|
local strictMacroArguments = true
|
||||||
|
|
||||||
|
--==============================================================
|
||||||
|
--= Local functions ============================================
|
||||||
|
--==============================================================
|
||||||
|
local F = string.format
|
||||||
|
|
||||||
|
local function formatBytes(n)
|
||||||
|
if n >= 1024*1024*1024 then
|
||||||
|
return F("%.2f GiB", n/(1024*1024*1024))
|
||||||
|
elseif n >= 1024*1024 then
|
||||||
|
return F("%.2f MiB", n/(1024*1024))
|
||||||
|
elseif n >= 1024 then
|
||||||
|
return F("%.2f KiB", n/(1024))
|
||||||
|
elseif n == 1 then
|
||||||
|
return F("1 byte", n)
|
||||||
|
else
|
||||||
|
return F("%d bytes", n)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function printfNoise(s, ...)
|
||||||
|
print(s:format(...))
|
||||||
|
end
|
||||||
|
local function printError(s)
|
||||||
|
io.stderr:write(s, "\n")
|
||||||
|
end
|
||||||
|
local function printfError(s, ...)
|
||||||
|
io.stderr:write(s:format(...), "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function errorLine(err)
|
||||||
|
printError(pp.tryToFormatError(err))
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local loadLuaFile = (
|
||||||
|
(_VERSION >= "Lua 5.2" or jit) and function(path, env)
|
||||||
|
return loadfile(path, "bt", env)
|
||||||
|
end
|
||||||
|
or function(path, env)
|
||||||
|
local chunk, err = loadfile(path)
|
||||||
|
if not chunk then return nil, err end
|
||||||
|
|
||||||
|
if env then setfenv(chunk, env) end
|
||||||
|
|
||||||
|
return chunk
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
--==============================================================
|
||||||
|
--= Preprocessor script ========================================
|
||||||
|
--==============================================================
|
||||||
|
|
||||||
|
io.stdout:setvbuf("no")
|
||||||
|
io.stderr:setvbuf("no")
|
||||||
|
|
||||||
|
math.randomseed(os.time()) -- In case math.random() is used anywhere.
|
||||||
|
math.random() -- Must kickstart...
|
||||||
|
|
||||||
|
local processOptions = true
|
||||||
|
local messageHandlerPath = ""
|
||||||
|
local pathsIn = {}
|
||||||
|
local pathsOut = {}
|
||||||
|
|
||||||
|
for _, arg in ipairs(args) do
|
||||||
|
if processOptions and (arg:find"^%-%-?help$" or arg == "/?" or arg:find"^/[Hh][Ee][Ll][Pp]$") then
|
||||||
|
print("LuaPreprocess v"..pp.VERSION)
|
||||||
|
print((help:gsub("\t", " ")))
|
||||||
|
os.exit()
|
||||||
|
|
||||||
|
elseif not (processOptions and arg:find"^%-.") then
|
||||||
|
local paths = (hasOutputPaths and #pathsOut < #pathsIn) and pathsOut or pathsIn
|
||||||
|
table.insert(paths, arg)
|
||||||
|
|
||||||
|
if arg == "-" and (not hasOutputPaths or paths == pathsOut) then
|
||||||
|
silent = true
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif arg == "--" then
|
||||||
|
processOptions = false
|
||||||
|
|
||||||
|
elseif arg:find"^%-%-data=" or arg:find"^%-d=" then
|
||||||
|
customData = arg:gsub("^.-=", "")
|
||||||
|
|
||||||
|
elseif arg == "--backtickstrings" then
|
||||||
|
allowBacktickStrings = true
|
||||||
|
|
||||||
|
elseif arg == "--debug" then
|
||||||
|
isDebug = true
|
||||||
|
outputMeta = outputMeta or true
|
||||||
|
|
||||||
|
elseif arg:find"^%-%-handler=" or arg:find"^%-h=" then
|
||||||
|
messageHandlerPath = arg:gsub("^.-=", "")
|
||||||
|
|
||||||
|
elseif arg == "--jitsyntax" then
|
||||||
|
allowJitSyntax = true
|
||||||
|
|
||||||
|
elseif arg == "--linenumbers" then
|
||||||
|
addLineNumbers = true
|
||||||
|
|
||||||
|
elseif arg == "--meta" then
|
||||||
|
outputMeta = true
|
||||||
|
elseif arg:find"^%-%-meta=" then
|
||||||
|
outputMeta = arg:gsub("^.-=", "")
|
||||||
|
|
||||||
|
elseif arg == "--nonil" then
|
||||||
|
canOutputNil = false
|
||||||
|
|
||||||
|
elseif arg == "--novalidate" then
|
||||||
|
validate = false
|
||||||
|
|
||||||
|
elseif arg:find"^%-%-outputextension=" then
|
||||||
|
if hasOutputPaths then
|
||||||
|
errorLine("Cannot specify both --outputextension and --outputpaths")
|
||||||
|
end
|
||||||
|
hasOutputExtension = true
|
||||||
|
outputExtension = arg:gsub("^.-=", "")
|
||||||
|
|
||||||
|
elseif arg == "--outputpaths" or arg == "-o" then
|
||||||
|
if hasOutputExtension then
|
||||||
|
errorLine("Cannot specify both --outputpaths and --outputextension")
|
||||||
|
elseif pathsIn[1] then
|
||||||
|
errorLine(arg.." must appear before any input path.")
|
||||||
|
end
|
||||||
|
hasOutputPaths = true
|
||||||
|
|
||||||
|
elseif arg:find"^%-%-saveinfo=" or arg:find"^%-i=" then
|
||||||
|
processingInfoPath = arg:gsub("^.-=", "")
|
||||||
|
|
||||||
|
elseif arg == "--silent" then
|
||||||
|
silent = true
|
||||||
|
|
||||||
|
elseif arg == "--faststrings" then
|
||||||
|
fastStrings = true
|
||||||
|
|
||||||
|
elseif arg == "--nogc" then
|
||||||
|
collectgarbage("stop")
|
||||||
|
|
||||||
|
elseif arg:find"^%-%-macroprefix=" then
|
||||||
|
macroPrefix = arg:gsub("^.-=", "")
|
||||||
|
|
||||||
|
elseif arg:find"^%-%-macrosuffix=" then
|
||||||
|
macroSuffix = arg:gsub("^.-=", "")
|
||||||
|
|
||||||
|
elseif arg == "--release" then
|
||||||
|
releaseMode = true
|
||||||
|
|
||||||
|
elseif arg:find"^%-%-loglevel=" then
|
||||||
|
maxLogLevel = arg:gsub("^.-=", "")
|
||||||
|
|
||||||
|
elseif arg == "--version" then
|
||||||
|
io.stdout:write(pp.VERSION)
|
||||||
|
os.exit()
|
||||||
|
|
||||||
|
elseif arg == "--nostrictmacroarguments" then
|
||||||
|
strictMacroArguments = false
|
||||||
|
|
||||||
|
else
|
||||||
|
errorLine("Unknown option '"..arg:gsub("=.*", "").."'.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if silent then
|
||||||
|
printfNoise = function()end
|
||||||
|
end
|
||||||
|
|
||||||
|
local header = "= LuaPreprocess v"..pp.VERSION..os.date(", %Y-%m-%d %H:%M:%S =", startTime)
|
||||||
|
printfNoise(("="):rep(#header))
|
||||||
|
printfNoise("%s", header)
|
||||||
|
printfNoise(("="):rep(#header))
|
||||||
|
|
||||||
|
if hasOutputPaths and #pathsOut < #pathsIn then
|
||||||
|
errorLine("Missing output path for "..pathsIn[#pathsIn])
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Prepare metaEnvironment.
|
||||||
|
pp.metaEnvironment.dataFromCommandLine = customData -- May be nil.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Load message handler.
|
||||||
|
local messageHandler = nil
|
||||||
|
|
||||||
|
local function hasMessageHandler(message)
|
||||||
|
if not messageHandler then
|
||||||
|
return false
|
||||||
|
|
||||||
|
elseif type(messageHandler) == "function" then
|
||||||
|
return true
|
||||||
|
|
||||||
|
elseif type(messageHandler) == "table" then
|
||||||
|
return messageHandler[message] ~= nil
|
||||||
|
|
||||||
|
else
|
||||||
|
assert(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sendMessage(message, ...)
|
||||||
|
if not messageHandler then
|
||||||
|
return
|
||||||
|
|
||||||
|
elseif type(messageHandler) == "function" then
|
||||||
|
local returnValues = pp.pack(messageHandler(message, ...))
|
||||||
|
return pp.unpack(returnValues, 1, returnValues.n)
|
||||||
|
|
||||||
|
elseif type(messageHandler) == "table" then
|
||||||
|
local _messageHandler = messageHandler[message]
|
||||||
|
if not _messageHandler then return end
|
||||||
|
|
||||||
|
local returnValues = pp.pack(_messageHandler(...))
|
||||||
|
return pp.unpack(returnValues, 1, returnValues.n)
|
||||||
|
|
||||||
|
else
|
||||||
|
assert(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if messageHandlerPath ~= "" then
|
||||||
|
-- Make the message handler and the metaprogram share the same environment.
|
||||||
|
-- This way the message handler can easily define globals that the metaprogram uses.
|
||||||
|
local mainChunk, err = loadLuaFile(messageHandlerPath, pp.metaEnvironment)
|
||||||
|
if not mainChunk then
|
||||||
|
errorLine("Could not load message handler...\n"..pp.tryToFormatError(err))
|
||||||
|
end
|
||||||
|
|
||||||
|
messageHandler = mainChunk()
|
||||||
|
|
||||||
|
if type(messageHandler) == "function" then
|
||||||
|
-- void
|
||||||
|
elseif type(messageHandler) == "table" then
|
||||||
|
for message, _messageHandler in pairs(messageHandler) do
|
||||||
|
if type(message) ~= "string" then
|
||||||
|
errorLine(messageHandlerPath..": Table of handlers must only contain messages as keys.")
|
||||||
|
elseif type(_messageHandler) ~= "function" then
|
||||||
|
errorLine(messageHandlerPath..": Table of handlers must only contain functions as values.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
errorLine(messageHandlerPath..": File did not return a table or a function.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Init stuff.
|
||||||
|
sendMessage("init", pathsIn, (hasOutputPaths and pathsOut or nil)) -- @Incomplete: Use pcall and format error message better?
|
||||||
|
|
||||||
|
if not hasOutputPaths then
|
||||||
|
for i, pathIn in ipairs(pathsIn) do
|
||||||
|
pathsOut[i] = (pathIn == "-") and "-" or pathIn:gsub("%.%w+$", "").."."..outputExtension
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not pathsIn[1] then
|
||||||
|
errorLine("No path(s) specified.")
|
||||||
|
elseif #pathsIn ~= #pathsOut then
|
||||||
|
errorLine(F("Number of input and output paths differ. (%d in, %d out)", #pathsIn, #pathsOut))
|
||||||
|
end
|
||||||
|
|
||||||
|
local pathsSetIn = {}
|
||||||
|
local pathsSetOut = {}
|
||||||
|
|
||||||
|
for i = 1, #pathsIn do
|
||||||
|
if pathsSetIn [pathsIn [i]] then errorLine("Duplicate input path: " ..pathsIn [i]) end
|
||||||
|
if pathsSetOut[pathsOut[i]] then errorLine("Duplicate output path: "..pathsOut[i]) end
|
||||||
|
|
||||||
|
pathsSetIn [pathsIn [i]] = true
|
||||||
|
pathsSetOut[pathsOut[i]] = true
|
||||||
|
|
||||||
|
if pathsIn [i] ~= "-" and pathsSetOut[pathsIn [i]] then errorLine("Path is both input and output: "..pathsIn [i]) end
|
||||||
|
if pathsOut[i] ~= "-" and pathsSetIn [pathsOut[i]] then errorLine("Path is both input and output: "..pathsOut[i]) end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Process files.
|
||||||
|
|
||||||
|
-- :SavedInfo
|
||||||
|
local processingInfo = {
|
||||||
|
date = os.date("%Y-%m-%d %H:%M:%S", startTime),
|
||||||
|
files = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
local byteCount = 0
|
||||||
|
local lineCount = 0
|
||||||
|
local lineCountCode = 0
|
||||||
|
local tokenCount = 0
|
||||||
|
|
||||||
|
for i, pathIn in ipairs(pathsIn) do
|
||||||
|
local startClockForPath = os.clock()
|
||||||
|
printfNoise("Processing '%s'...", pathIn)
|
||||||
|
|
||||||
|
local pathOut = pathsOut[i]
|
||||||
|
local pathMeta = (type(outputMeta) == "string") and outputMeta or pathOut:gsub("%.%w+$", "")..".meta.lua"
|
||||||
|
|
||||||
|
if not outputMeta or pathOut == "-" then
|
||||||
|
pathMeta = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local info, err = pp.processFile{
|
||||||
|
pathIn = pathIn,
|
||||||
|
pathMeta = pathMeta,
|
||||||
|
pathOut = pathOut,
|
||||||
|
|
||||||
|
debug = isDebug,
|
||||||
|
addLineNumbers = addLineNumbers,
|
||||||
|
|
||||||
|
backtickStrings = allowBacktickStrings,
|
||||||
|
jitSyntax = allowJitSyntax,
|
||||||
|
canOutputNil = canOutputNil,
|
||||||
|
fastStrings = fastStrings,
|
||||||
|
validate = validate,
|
||||||
|
strictMacroArguments = strictMacroArguments,
|
||||||
|
|
||||||
|
macroPrefix = macroPrefix,
|
||||||
|
macroSuffix = macroSuffix,
|
||||||
|
|
||||||
|
release = releaseMode,
|
||||||
|
logLevel = maxLogLevel,
|
||||||
|
|
||||||
|
onInsert = (hasMessageHandler("insert") or nil) and function(name)
|
||||||
|
local lua = sendMessage("insert", pathIn, name)
|
||||||
|
|
||||||
|
-- onInsert() is expected to return a Lua code string and so is the message
|
||||||
|
-- handler. However, if the handler is a single catch-all function we allow
|
||||||
|
-- the message to not be handled and we fall back to the default behavior of
|
||||||
|
-- treating 'name' as a path to a file to be inserted. If we didn't allow this
|
||||||
|
-- then it would be required for the "insert" message to be handled. I think
|
||||||
|
-- it's better if the user can choose whether to handle a message or not!
|
||||||
|
--
|
||||||
|
if lua == nil and type(messageHandler) == "function" then
|
||||||
|
return assert(pp.readFile(name))
|
||||||
|
end
|
||||||
|
|
||||||
|
return lua
|
||||||
|
end,
|
||||||
|
|
||||||
|
onBeforeMeta = messageHandler and function(lua)
|
||||||
|
sendMessage("beforemeta", pathIn, lua)
|
||||||
|
end,
|
||||||
|
|
||||||
|
onAfterMeta = messageHandler and function(lua)
|
||||||
|
local luaModified = sendMessage("aftermeta", pathIn, lua)
|
||||||
|
|
||||||
|
if type(luaModified) == "string" then
|
||||||
|
lua = luaModified
|
||||||
|
|
||||||
|
elseif luaModified ~= nil then
|
||||||
|
error(F(
|
||||||
|
"%s: Message handler did not return a string for 'aftermeta'. (Got %s)",
|
||||||
|
messageHandlerPath, type(luaModified)
|
||||||
|
))
|
||||||
|
end
|
||||||
|
|
||||||
|
return lua
|
||||||
|
end,
|
||||||
|
|
||||||
|
onDone = messageHandler and function(info)
|
||||||
|
sendMessage("filedone", pathIn, pathOut, info)
|
||||||
|
end,
|
||||||
|
|
||||||
|
onError = function(err)
|
||||||
|
xpcall(function()
|
||||||
|
sendMessage("fileerror", pathIn, err)
|
||||||
|
end, function(err)
|
||||||
|
printfError("Additional error in 'fileerror' message handler...\n%s", pp.tryToFormatError(err))
|
||||||
|
end)
|
||||||
|
os.exit(1)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
assert(info, err) -- The onError() handler above should have been called and we should have exited already.
|
||||||
|
|
||||||
|
byteCount = byteCount + info.processedByteCount
|
||||||
|
lineCount = lineCount + info.lineCount
|
||||||
|
lineCountCode = lineCountCode + info.linesOfCode
|
||||||
|
tokenCount = tokenCount + info.tokenCount
|
||||||
|
|
||||||
|
if processingInfoPath ~= "" then
|
||||||
|
|
||||||
|
-- :SavedInfo
|
||||||
|
table.insert(processingInfo.files, info) -- See 'ProcessInfo' in preprocess.lua for what more 'info' contains.
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
printfNoise("Processing '%s' successful! (%.3fs)", pathIn, os.clock()-startClockForPath)
|
||||||
|
printfNoise(("-"):rep(#header))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Finalize stuff.
|
||||||
|
if processingInfoPath ~= "" then
|
||||||
|
printfNoise("Saving processing info to '%s'.", processingInfoPath)
|
||||||
|
|
||||||
|
local luaParts = {"return"}
|
||||||
|
assert(pp.serialize(luaParts, processingInfo))
|
||||||
|
local lua = table.concat(luaParts)
|
||||||
|
|
||||||
|
local file = assert(io.open(processingInfoPath, "wb"))
|
||||||
|
file:write(lua)
|
||||||
|
file:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
printfNoise(
|
||||||
|
"All done! (%.3fs, %.0f file%s, %.0f LOC, %.0f line%s, %.0f token%s, %s)",
|
||||||
|
os.clock()-startClock,
|
||||||
|
#pathsIn, (#pathsIn == 1) and "" or "s",
|
||||||
|
lineCountCode,
|
||||||
|
lineCount, (lineCount == 1) and "" or "s",
|
||||||
|
tokenCount, (tokenCount == 1) and "" or "s",
|
||||||
|
formatBytes(byteCount)
|
||||||
|
)
|
||||||
|
|
||||||
|
sendMessage("alldone") -- @Incomplete: Use pcall and format error message better?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--[[!===========================================================
|
||||||
|
|
||||||
|
Copyright © 2018-2022 Marcus 'ReFreezed' Thunström
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
==============================================================]]
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
-- GENERATED FILE - DO NOT EDIT
|
||||||
|
-- Instead, edit the source file directly: assets.lua2p.
|
||||||
|
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
Glove = playdate.graphics.image.new("images/game/Glove.png")
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
PlayerFrown = playdate.graphics.image.new("images/game/PlayerFrown.png")
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
PlayerBack = playdate.graphics.image.new("images/game/PlayerBack.png")
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
PlayerLowHat = playdate.graphics.image.new("images/game/PlayerLowHat.png")
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
GloveHoldingBall = playdate.graphics.image.new("images/game/GloveHoldingBall.png")
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
MenuImage = playdate.graphics.image.new("images/game/MenuImage.png")
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
Player = playdate.graphics.image.new("images/game/Player.png")
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
Minimap = playdate.graphics.image.new("images/game/Minimap.png")
|
||||||
|
--selene: allow(unused_variable)
|
||||||
|
--selene: allow(unscoped_variables)
|
||||||
|
GrassBackground = playdate.graphics.image.new("images/game/GrassBackground.png")
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
!(function dirLookup(dir, extension, newFunc)
|
||||||
|
--Open directory look for files, save data in p. By giving '-type f' as parameter, it returns all files.
|
||||||
|
local p = io.popen('find src/' .. dir .. ' -type f')
|
||||||
|
|
||||||
|
local assetCode = ""
|
||||||
|
--Loop through all files
|
||||||
|
for file in p:lines() do
|
||||||
|
if file:find(extension) then
|
||||||
|
local varName = file:gsub(".*/(.*)." .. extension, "%1")
|
||||||
|
file = file:gsub("src/", "")
|
||||||
|
assetCode = assetCode .. '--selene: allow(unused_variable)\n'
|
||||||
|
assetCode = assetCode .. '--selene: allow(unscoped_variables)\n'
|
||||||
|
assetCode = assetCode .. varName .. ' = ' .. newFunc .. '("' .. file .. '")\n'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return assetCode
|
||||||
|
end
|
||||||
|
function generatedFileWarning()
|
||||||
|
return "-- GENERATED FILE - DO NOT EDIT\n-- Instead, edit the source file directly: assets.lua2p."
|
||||||
|
end) !!(generatedFileWarning())
|
||||||
|
|
||||||
|
!!(dirLookup('images/game', 'png', 'playdate.graphics.image.new'))
|
|
@ -1,10 +1,7 @@
|
||||||
-- selene: allow(shadowing)
|
-- selene: allow(shadowing)
|
||||||
local gfx = playdate.graphics
|
local gfx = playdate.graphics
|
||||||
|
|
||||||
local Glove <const> = playdate.graphics.image.new("images/game/glove.png") --[[@as pd_image]]
|
|
||||||
local GloveSizeX, GloveSizeY <const> = Glove:getSize()
|
local GloveSizeX, GloveSizeY <const> = Glove:getSize()
|
||||||
|
|
||||||
local GloveHoldingBall <const> = playdate.graphics.image.new("images/game/glove-holding-ball.png") --[[@as pd_image]]
|
|
||||||
local GloveOffX, GloveOffY <const> = GloveSizeX / 2, GloveSizeY / 2
|
local GloveOffX, GloveOffY <const> = GloveSizeX / 2, GloveSizeY / 2
|
||||||
|
|
||||||
---@param fielderX number
|
---@param fielderX number
|
||||||
|
|
|
@ -3,9 +3,7 @@ local gfx = playdate.graphics
|
||||||
|
|
||||||
local ScoreFont <const> = playdate.graphics.font.new("fonts/font-full-circle.pft")
|
local ScoreFont <const> = playdate.graphics.font.new("fonts/font-full-circle.pft")
|
||||||
|
|
||||||
local MinimapBackground <const> = gfx.image.new("images/game/minimap.png") --[[@as pd_image]]
|
local MinimapSizeX, MinimapSizeY <const> = Minimap:getSize()
|
||||||
|
|
||||||
local MinimapSizeX, MinimapSizeY <const> = MinimapBackground:getSize()
|
|
||||||
local MinimapPosX, MinimapPosY = C.Screen.W - MinimapSizeX, C.Screen.H - MinimapSizeY
|
local MinimapPosX, MinimapPosY = C.Screen.W - MinimapSizeX, C.Screen.H - MinimapSizeY
|
||||||
|
|
||||||
local MinimapMultX <const> = 0.75 * MinimapSizeX / C.Screen.W
|
local MinimapMultX <const> = 0.75 * MinimapSizeX / C.Screen.W
|
||||||
|
@ -14,7 +12,7 @@ local MinimapMultY <const> = 0.70 * MinimapSizeY / C.FieldHeight
|
||||||
local MinimapOffsetY <const> = MinimapPosY - 15
|
local MinimapOffsetY <const> = MinimapPosY - 15
|
||||||
|
|
||||||
function drawMinimap(runners)
|
function drawMinimap(runners)
|
||||||
MinimapBackground:draw(MinimapPosX, MinimapPosY)
|
Minimap:draw(MinimapPosX, MinimapPosY)
|
||||||
gfx.setColor(gfx.kColorBlack)
|
gfx.setColor(gfx.kColorBlack)
|
||||||
for _, runner in pairs(runners) do
|
for _, runner in pairs(runners) do
|
||||||
local x = (MinimapMultX * runner.x) + MinimapOffsetX
|
local x = (MinimapMultX * runner.x) + MinimapOffsetX
|
||||||
|
|
|
@ -25,13 +25,13 @@ blipper = {}
|
||||||
|
|
||||||
--- Build an object that simply "blips" between the given images at the given interval.
|
--- Build an object that simply "blips" between the given images at the given interval.
|
||||||
--- Expects `playdate.graphics.animation.blinker.updateAll()` to be called on every update.
|
--- Expects `playdate.graphics.animation.blinker.updateAll()` to be called on every update.
|
||||||
function blipper.new(msInterval, imagePath1, imagePath2)
|
function blipper.new(msInterval, image1, image2)
|
||||||
local blinker = playdate.graphics.animation.blinker.new(msInterval, msInterval, true)
|
local blinker = playdate.graphics.animation.blinker.new(msInterval, msInterval, true)
|
||||||
blinker:start()
|
blinker:start()
|
||||||
return {
|
return {
|
||||||
blinker = blinker,
|
blinker = blinker,
|
||||||
image1 = playdate.graphics.image.new(imagePath1),
|
image1 = image1,
|
||||||
image2 = playdate.graphics.image.new(imagePath2),
|
image2 = image2,
|
||||||
draw = function(self, disableBlipping, x, y)
|
draw = function(self, disableBlipping, x, y)
|
||||||
local currentImage = (disableBlipping or self.blinker.on) and self.image2 or self.image1
|
local currentImage = (disableBlipping or self.blinker.on) and self.image2 or self.image1
|
||||||
currentImage:draw(x, y)
|
currentImage:draw(x, y)
|
||||||
|
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 720 B After Width: | Height: | Size: 720 B |
Before Width: | Height: | Size: 681 B After Width: | Height: | Size: 681 B |
Before Width: | Height: | Size: 712 B After Width: | Height: | Size: 712 B |
Before Width: | Height: | Size: 711 B After Width: | Height: | Size: 711 B |
14
src/main.lua
|
@ -26,6 +26,7 @@ import 'CoreLibs/ui.lua'
|
||||||
|
|
||||||
import 'utils.lua'
|
import 'utils.lua'
|
||||||
import 'constants.lua'
|
import 'constants.lua'
|
||||||
|
import 'assets.lua'
|
||||||
|
|
||||||
import 'announcer.lua'
|
import 'announcer.lua'
|
||||||
import 'dbg.lua'
|
import 'dbg.lua'
|
||||||
|
@ -36,21 +37,14 @@ import 'draw/fielder'
|
||||||
-- stylua: ignore end
|
-- stylua: ignore end
|
||||||
|
|
||||||
-- selene: allow(shadowing)
|
-- selene: allow(shadowing)
|
||||||
local gfx <const> = playdate.graphics
|
local gfx <const>, C <const> = playdate.graphics, C
|
||||||
|
|
||||||
-- selene: allow(shadowing)
|
|
||||||
local C <const> = C
|
|
||||||
|
|
||||||
local BootTune <const> = playdate.sound.sampleplayer.new("sounds/boot-tune.wav")
|
local BootTune <const> = playdate.sound.sampleplayer.new("sounds/boot-tune.wav")
|
||||||
-- local BootTune <const> = playdate.sound.sampleplayer.new("sounds/boot-tune-organy.wav")
|
-- local BootTune <const> = playdate.sound.sampleplayer.new("sounds/boot-tune-organy.wav")
|
||||||
local TinnyBackground <const> = playdate.sound.sampleplayer.new("sounds/tinny-background.wav")
|
local TinnyBackground <const> = playdate.sound.sampleplayer.new("sounds/tinny-background.wav")
|
||||||
local BatCrackSound <const> = playdate.sound.sampleplayer.new("sounds/bat-crack-reverb.wav")
|
local BatCrackSound <const> = playdate.sound.sampleplayer.new("sounds/bat-crack-reverb.wav")
|
||||||
local GrassBackground <const> = gfx.image.new("images/game/grass.png") --[[@as pd_image]]
|
|
||||||
local PlayerFrown <const> = gfx.image.new("images/game/player-frown.png") --[[@as pd_image]]
|
|
||||||
local PlayerSmile <const> = gfx.image.new("images/game/player.png") --[[@as pd_image]]
|
|
||||||
local PlayerBack <const> = gfx.image.new("images/game/player-back.png") --[[@as pd_image]]
|
|
||||||
|
|
||||||
local PlayerImageBlipper <const> = blipper.new(100, "images/game/player.png", "images/game/player-lowhat.png")
|
local PlayerImageBlipper <const> = blipper.new(100, Player, PlayerLowHat)
|
||||||
|
|
||||||
local FielderDanceAnimator <const> = gfx.animator.new(1, 10, 0, utils.easingHill)
|
local FielderDanceAnimator <const> = gfx.animator.new(1, 10, 0, utils.easingHill)
|
||||||
FielderDanceAnimator.repeatCount = C.DanceBounceCount - 1
|
FielderDanceAnimator.repeatCount = C.DanceBounceCount - 1
|
||||||
|
@ -858,7 +852,7 @@ function playdate.update()
|
||||||
if batAngleDeg > 50 and batAngleDeg < 200 then
|
if batAngleDeg > 50 and batAngleDeg < 200 then
|
||||||
PlayerBack:draw(runner.x, runner.y)
|
PlayerBack:draw(runner.x, runner.y)
|
||||||
else
|
else
|
||||||
PlayerSmile:draw(runner.x, runner.y)
|
Player:draw(runner.x, runner.y)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- TODO? Change blip speed depending on runner speed?
|
-- TODO? Change blip speed depending on runner speed?
|
||||||
|
|