okay honestly this all can and should just be CSVs
This commit is contained in:
parent
b536d2c987
commit
4ccbe1dc35
61
the_parser.p8
Normal file
61
the_parser.p8
Normal file
@ -0,0 +1,61 @@
|
||||
pico-8 cartridge // http://www.pico-8.com
|
||||
version 41
|
||||
__lua__
|
||||
-- the parser
|
||||
|
||||
parser = {}
|
||||
mknew(parser)
|
||||
|
||||
-- calls parse_into with a nop
|
||||
-- emit function.
|
||||
function parser:parse(str)
|
||||
self:parse_into(str, function() end)
|
||||
end
|
||||
|
||||
-- read a file of commands and
|
||||
-- execute them, emitting the
|
||||
-- results from each call into
|
||||
-- `emit` as a table per row.
|
||||
--
|
||||
-- a "command" is a method on
|
||||
-- self. a row alternates
|
||||
-- commands with args. when
|
||||
-- calling a command, it also
|
||||
-- gets a table of previous
|
||||
-- results as the first arg.
|
||||
-- args are split on ','.
|
||||
function parser:parse_into(str, emit)
|
||||
for row in all(split(str, "\n")) do
|
||||
local prev = {}
|
||||
local sectors = split(row, ":")
|
||||
for i=1,#sectors,2 do
|
||||
local x = self[sectors[i]](self, prev, usplit(sectors[i+1]))
|
||||
if (x) add(prev, x)
|
||||
end
|
||||
emit(prev)
|
||||
end
|
||||
end
|
||||
|
||||
-- saves prev[sel] as self.name.
|
||||
-- if sel is unspecified, saves
|
||||
-- all of prev (as a table).
|
||||
function parser:saveas(prev, name, sel)
|
||||
self[name] = sel and prev[sel] or prev
|
||||
end
|
||||
|
||||
-- returns its args, ignoring
|
||||
-- prev. Used to stuff things
|
||||
-- into prev. args are packed
|
||||
-- if there's multiple.
|
||||
function parser:val(_, ...)
|
||||
local ret := pack(...)
|
||||
if (#ret == 1) return ret[1]
|
||||
return ret
|
||||
end
|
||||
|
||||
function parser:bind(_, fn, ...)
|
||||
local f = self[fn]
|
||||
return function()
|
||||
f(...)
|
||||
end
|
||||
end
|
126
updatedshmup.p8
126
updatedshmup.p8
@ -416,66 +416,6 @@ function grab_p1_butts()
|
||||
}
|
||||
end
|
||||
|
||||
-->8
|
||||
-- the parser
|
||||
|
||||
parser = {}
|
||||
mknew(parser)
|
||||
|
||||
-- calls parse_into with a nop
|
||||
-- emit function.
|
||||
function parser:parse(str)
|
||||
self:parse_into(str, function() end)
|
||||
end
|
||||
|
||||
-- read a file of commands and
|
||||
-- execute them, emitting the
|
||||
-- results from each call into
|
||||
-- `emit` as a table per row.
|
||||
--
|
||||
-- a "command" is a method on
|
||||
-- self. a row alternates
|
||||
-- commands with args. when
|
||||
-- calling a command, it also
|
||||
-- gets a table of previous
|
||||
-- results as the first arg.
|
||||
-- args are split on ','.
|
||||
function parser:parse_into(str, emit)
|
||||
for row in all(split(str, "\n")) do
|
||||
local prev = {}
|
||||
local sectors = split(row, ":")
|
||||
for i=1,#sectors,2 do
|
||||
local x = self[sectors[i]](self, prev, usplit(sectors[i+1]))
|
||||
if (x) add(prev, x)
|
||||
end
|
||||
emit(prev)
|
||||
end
|
||||
end
|
||||
|
||||
-- saves prev[sel] as self.name.
|
||||
-- if sel is unspecified, saves
|
||||
-- all of prev (as a table).
|
||||
function parser:saveas(prev, name, sel)
|
||||
self[name] = sel and prev[sel] or prev
|
||||
end
|
||||
|
||||
-- returns its args, ignoring
|
||||
-- prev. Used to stuff things
|
||||
-- into prev. args are packed
|
||||
-- if there's multiple.
|
||||
function parser:val(_, ...)
|
||||
local ret := pack(...)
|
||||
if (#ret == 1) return ret[1]
|
||||
return ret
|
||||
end
|
||||
|
||||
function parser:bind(_, fn, ...)
|
||||
local f = self[fn]
|
||||
return function()
|
||||
f(...)
|
||||
end
|
||||
end
|
||||
|
||||
-->8
|
||||
--ship behavior
|
||||
|
||||
@ -907,7 +847,9 @@ end
|
||||
|
||||
-- a level is a map from
|
||||
-- effective frame number to
|
||||
-- callback for that frame.
|
||||
-- a list of actions for that
|
||||
-- frame. an action is a
|
||||
-- method name and its args.
|
||||
|
||||
-- effective frame number stops
|
||||
-- when freeze count is nonzero
|
||||
@ -931,16 +873,20 @@ freeze = 0
|
||||
|
||||
eol = {}
|
||||
|
||||
function load_level(lvltbl)
|
||||
function load_level(levelfile)
|
||||
distance = 0
|
||||
lframe = 0
|
||||
freeze = 0
|
||||
current_level = {}
|
||||
-- copy the level so we can
|
||||
-- modify it dynamically
|
||||
-- without losing the original
|
||||
for frame, cb in pairs(lvltbl) do
|
||||
current_level[frame] = cb
|
||||
for row in all(csv(levelfile)) do
|
||||
local x = current_level[row[1]]
|
||||
if row[2] == "eol" then
|
||||
assert(x==nil, "events on eol frame")
|
||||
row[1] = eol
|
||||
else
|
||||
add(x, row)
|
||||
end
|
||||
row[1]=x
|
||||
end
|
||||
leveldone = false
|
||||
end
|
||||
@ -950,13 +896,16 @@ function level_frame()
|
||||
if (current_level == nil) return true
|
||||
if freeze == 0 then
|
||||
distance += 1
|
||||
local cb = current_level[distance]
|
||||
if cb ~= nil then
|
||||
if cb == eol then
|
||||
local cbs = current_level[distance]
|
||||
if cbs ~= nil then
|
||||
if cbs == eol then
|
||||
current_level = nil
|
||||
return true
|
||||
else
|
||||
cb()
|
||||
for c in all(cbs) do
|
||||
assert(c[1] == distance)
|
||||
level_events[c[2]](unpack(c.params, 3))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -965,23 +914,26 @@ end
|
||||
-->8
|
||||
-- example level
|
||||
|
||||
level_parser = parser.new{}
|
||||
mknew(level_parser)
|
||||
function std_spawn(tnm, n, blocking, goodie)
|
||||
-- TODO: implement
|
||||
-- look up enemy type from tnm
|
||||
-- spawn n of them at random positions,
|
||||
-- see spawn_rnd_x.
|
||||
-- if blocking, patch the blocking logic in.
|
||||
-- if they drop a goodie, find the goodie,
|
||||
-- then patch the bonus logic in.
|
||||
end
|
||||
|
||||
function level_parser:parse_level(lvl)
|
||||
local ret = {}
|
||||
self:parse_into(lvl,
|
||||
function(row)
|
||||
if (#row < 2 or type(row[1] ~= "number")) return
|
||||
local idx = row[1]
|
||||
local x = ret[idx] or {}
|
||||
for j=2,#row do
|
||||
add(x, row[j])
|
||||
end
|
||||
ret[idx]=x
|
||||
end)
|
||||
return ret
|
||||
end
|
||||
-- to implement: repeat(times, interval, f, ...)
|
||||
-- once on this frame, then times-1 times after that spaced interval
|
||||
-- frames apart, f(...). schedule this like the one-off written in
|
||||
-- example_level.
|
||||
|
||||
-- then convert sample_level to csv.
|
||||
-- spawn_spec_gun_at and spawn_main_gun_at will need parsed forms.
|
||||
-- the boss also needs to be reachable, but one-off is fine.
|
||||
-- each row of level csv is offset,event,event-args...
|
||||
-- where offset,eol is a special case.
|
||||
|
||||
function spawn_rnd_x(typ)
|
||||
s = typ.new{
|
||||
|
Loading…
Reference in New Issue
Block a user