diff --git a/the_parser.p8 b/the_parser.p8 new file mode 100644 index 0000000..8c0a0e2 --- /dev/null +++ b/the_parser.p8 @@ -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 diff --git a/updatedshmup.p8 b/updatedshmup.p8 index f43382e..190d776 100644 --- a/updatedshmup.p8 +++ b/updatedshmup.p8 @@ -26,22 +26,20 @@ end -- ret is definitely not nil -- before calling setmetatable. -- use to initialize mutables. +-- +-- if there was a previous new, +-- it is invoked on the new +-- object *after* more, because +-- this works better with the +-- `more` impls i use. function mknew(tt, more) - local mt = {__index=tt} - -- check "more" only once ever - if more then - tt.new = function(ret) - if (not ret) ret = {} - more(ret) - setmetatable(ret, mt) - return ret - end - else - tt.new=function(ret) - if (not ret) ret = {} - setmetatable(ret, mt) - return ret - end + local mt,oldnew = {__index=tt},tt.new + tt.new=function(ret) + if(not ret) ret = {} + if(more) more(ret) + if(oldnew) oldnew(ret) + setmetatable(ret, mt) + return ret end end @@ -121,7 +119,7 @@ function _init() init_blip_pals() wipe_level() primary_ship.main_gun = zap_gun.new() - load_level(example_level) + load_level(example_level_csv) state = game pal(2,129) pal() @@ -416,59 +414,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 - -->8 --ship behavior @@ -603,520 +548,6 @@ function ship_m:refresh_shield() self.shield_refresh_ready = lframe + self.shieldcooldown end --->8 ---ships, including player - -firespark = split"9, 8, 2, 5, 1" -smokespark = split"13, 13, 5, 5" - -player = ship_m.new{ - --shape - sprite = 1, --index of ship sprite - size = 1, --all ships are square; how many 8x8 sprites? - hurt = { -- hurtbox - where this ship can be hit - x_off = 3, -- upper left corner - y_off = 2, -- relative to ship ulc - width = 1, - height = 3 - }, - sparks = firespark, -- see tab 9 - sparkodds = 2, - boss = true, -- dramatic special effects - - -- health and power - hp = 3, -- current health, non-regenerating - maxhp = 3, -- player only; other ships never heal - shield = 2, -- regenerates, using power - maxshield = 2, - shieldcost = 300, -- power cost to refill shield - generator = 1.5, -- 1 feels too slow - - -- gun - main_gun = nil, -- assign at spawn time - special_gun = nil, - fire_off_x = 4, -- offset where bullets come from - fire_off_y = 0, - - -- position - x=52, -- x and y are for upper left corner - y=96, - xmomentum = 0, - ymomentum = 0, - maxspd = 2.5, -- momentum cap - thrust = 0.25, -- momentum added from button - drag = 0.125, -- momentum lost per frame - slip = false, -- does not slide down screen - grab_butts = function(self) -- fetch buttons - local butts = grab_p1_butts() - if butts[0] == butts[1] then - self.sprite = 1 - elseif butts[0] > 0 then - self.sprite = 17 - else - self.sprite = 18 - end - return butts - end -} -mknew(player, - function(p) - p.main_gun = zap_gun.new() - end -) - -frownie = ship_m.new{ - --shape - sprite = 3, --index of ship sprite - size = 1, --all ships are square; how many 8x8 sprites? - hurt = { -- hurtbox - where this ship can be hit - x_off = 0, -- upper left corner - y_off = 1, -- relative to ship ulc - width = 8, - height = 6 - }, - sparks = smokespark, - sparkodds = 8, - - -- health and power - hp = 1, -- enemy ships need no max hp - - -- position - x=60, -- x and y are for upper left corner - y=8, - xmomentum = 0, - ymomentum = 0, - maxspd = 2, -- momentum cap - thrust = 0.12, -- momentum added from button - drag = 0.07, -- momentum lost per frame - slip = true, - grab_butts = function(discard_self) - -- buttons are effectively analog - -- and negative buttons work just fine! - local butts = {} - local tstate = (1 + flr(4*t() + 0.5)) % 6 - butts[0] = ((tstate==1 or tstate==2) and 1) or 0 - butts[1] = ((tstate==4 or tstate==5) and 1) or 0 - for b=2, 5 do - butts[b]=0 - end - return butts - end, -- button fetch algorithm -} -mknew(frownie) - -blocky = frownie.new{ - sprite = 10, - hp = 2, - hurt = { - x_off = 0, - y_off = 0, - width = 8, - height = 7 - }, - - ow = function(self) - if self.hp <= 1 then - self.sprite = 11 - else - self.sprite = 10 - end - ship_m.ow(self) - end -} -mknew(blocky) - -function spawn_spewy_at(x, y) - local spewy = frownie.new{ - x = x, - y = y, - sprite = 26, - power = -20, - hurt = { - x_off = 0, - y_off = 1, - width = 8, - height = 5 - }, - - hp = 1, - maxpower = 70, - generator = 0.5, - main_gun = protron_gun.new{enemy=true}, - fire_off_x = 4, - fire_off_y = 7, - grab_butts = function() - local butts = frownie.grab_butts() - butts[5] = 1 - return butts - end, - } - eships:push_back(spewy) - return spewy -end - -chasey = ship_m.new{ - sprite = 5, - size = 1, - hurt = { - x_off = 1, - y_off = 2, - width = 6, - height = 5, - }, - sparks = smokespark, - sparkodds = 8, - hp = 2, - shield = 1, - maxshield = 1, - shieldcost = 180, - - fire_off_x = 4, - fire_off_y = 7, - - maxspd = 2, - thrust = 0.2, - drag = 0.075, - slip = true, - - grab_butts = function(self) - local butts = {0,0,0,0,0} - butts[0] = 0 - if (self.x < primary_ship.x) butts[1] = 1 - if (self.x > primary_ship.x) butts[0] = 1 - if (self.x - 16 < primary_ship.x and self.x + 16 > primary_ship.x) butts[5] = 1 - return butts - end, -} -mknew(chasey) - -function spawn_chasey_at(x, y) - local c = chasey.new{ - x = x, - y = y, - main_gun = zap_gun.new{enemy=true}, - } - eships:push_back(c) - return c -end - -function spawn_xl_chasey_at(x, y) - local c = chasey.new{ - x = x, - y = y, - size = 2, - maxspd = 1.25, - hurt = { - x_off = 2, - y_off = 4, - width = 12, - height = 10 - }, - hp = 20, - shield = 5, - boss = true, - slip = false, - main_gun = zap_gun.new{enemy=true}, - grab_butts = function(self) - local butts = chasey.grab_butts(self) - if (self.y < 4) butts[3] = 1 - return butts - end, - draw = function(self) - if(self.fx_pal) pal(self.fx_pal) - sspr(40, 0, 8, 8, self.x, self.y, 16, 16) - pal() - end, - } - eships:push_back(c) - return c -end --->8 --- collisions - --- box: x, y, width, height - -function collides(box1, box2) - return not ( - box1.x>box2.x+box2.width - or box1.y>box2.y+box2.height - or box1.x+box1.width8 --- level and event system - --- a level is a map from --- effective frame number to --- callback for that frame. - --- effective frame number stops --- when freeze count is nonzero - --- a level is won when it hits --- the end-of-level sentinel --- and there are no more --- tracked enemies. --- lost when there are no --- player ships left. - --- effective frame -distance = 0 --- actual frame count since --- start of level times 0x0.0001 -lframe = 0 - --- do not advance distance when --- nonzero -freeze = 0 - -eol = {} - -function load_level(lvltbl) - 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 - end - leveldone = false -end - -function level_frame() - lframe += 0x0.0001 - 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 - current_level = nil - return true - else - cb() - end - end - end - return false -end --->8 --- example level - -function spawn_rnd_x(typ) - s = typ.new{ - x = rnd(104), - y = -(typ.size * 8 - 1) - } - eships:push_back(s) - return s -end - -function spawn_blocking_rnd_x(typ) - freeze += 1 - s = typ.new{ - x = rnd(104), - y = -7, - ice = 1, - orig_die = typ.die, - die = function(self) - freeze -= self.ice - self.ice = 0 - self:orig_die() - end - } - eships:push_back(s) - return s -end - -function spawn_frownie() - return spawn_rnd_x(frownie) -end - -function spawn_blocking_frownie() - spawn_blocking_rnd_x(frownie) -end - -function spawn_blocky() - spawn_rnd_x(blocky) -end - -function spawn_blocking_blocky() - spawn_blocking_rnd_x(blocky) -end - -function spawn_spewy() - return spawn_spewy_at(rnd(104), -7) -end - -function spawn_chasey() - return spawn_chasey_at(rnd(104), -7) -end - -function spawn_blocking_spewy() - freeze += 1 - local s = spawn_spewy() - s.ice = 1 - s.die = function(self) - freeze -= self.ice - self.ice = 0 - frownie.die(self) - end -end - -function spawn_bonus_frownie() - local f = spawn_frownie() - f.sprite = 7 - f.die = function(self) - spawn_repair_at(self.x+4, self.y+4) - frownie.die(self) - end -end - -function spawn_bonus_vulcan_chasey() - local c = spawn_chasey() - c.main_gun=vulcan_gun.new{enemy=true} - c.die = function(self) - spawn_main_gun_at(self.x-1, self.y-1, vulcan_gun) - chasey.die(self) - end - c.sprite=4 - return c -end - -helpers = { - spawn_frownie, - spawn_frownie, - spawn_frownie, - spawn_blocky, - spawn_blocky, - spawn_chasey, - spawn_spewy, -} - -function spawn_blocking_boss_chasey() - freeze += 1 - local c = spawn_xl_chasey_at(44, -15) - c.ice = 1 - c.die = function(self) - freeze -= self.ice - self.ice = 0 - chasey.die(self) - end - - local nextspawn = lframe + 0x0.0080 - events:push_back{move=function() - if lframe >= nextspawn then - helpers[flr(rnd(#helpers))+1]() - nextspawn += 0x0.0040 - end - return c.dead - end} - - return c -end - -example_level = { - [1]=spawn_frownie, - [60]=spawn_bonus_vulcan_chasey, - [61]=spawn_blocky, - [85]=spawn_spewy, - [100]=spawn_spewy, - [115]=spawn_spewy, - [130]=spawn_bonus_frownie, - [145]=spawn_spewy, - [200]=spawn_chasey, - [250]=spawn_blocking_blocky, - [285]=function() - spawn_spec_gun_at(35, -11, blast_gun) - end, - [310]=function() - spawn_blocking_blocky() - spawn_blocking_blocky() - spawn_blocking_blocky() - end, - [311]=spawn_frownie, - [350]=function() - spawn_main_gun_at(70, -11, protron_gun) - end, - [401]=spawn_frownie, - [420]=spawn_blocking_frownie, - [430]=spawn_bonus_vulcan_chasey, - [450]=spawn_frownie, - [465]=spawn_bonus_frownie, - [480]=spawn_chasey, - [500]=function() - local tnext = lframe - local remain = 20 - events:push_back{move=function() - if (lframe < tnext) return false - spawn_blocking_blocky() - tnext = lframe + 0x0.000c - remain -= 1 - return (remain <= 0) - end} - end, - [501]=spawn_bonus_frownie, - [620]=spawn_blocking_blocky, - [700]=spawn_blocking_boss_chasey, - [701]=eol -} - -->8 -- bullet and gun behaviors @@ -1395,6 +826,540 @@ vulcan_gun = gun_base.new{ } mknew(vulcan_gun) +-->8 +--ships, including player + +firespark = split"9, 8, 2, 5, 1" +smokespark = split"13, 13, 5, 5" + +player = ship_m.new{ + --shape + sprite = 1, --index of ship sprite + size = 1, --all ships are square; how many 8x8 sprites? + hurt = { -- hurtbox - where this ship can be hit + x_off = 3, -- upper left corner + y_off = 2, -- relative to ship ulc + width = 1, + height = 3 + }, + sparks = firespark, -- see tab 9 + sparkodds = 2, + boss = true, -- dramatic special effects + + -- health and power + hp = 3, -- current health, non-regenerating + maxhp = 3, -- player only; other ships never heal + shield = 2, -- regenerates, using power + maxshield = 2, + shieldcost = 300, -- power cost to refill shield + generator = 1.5, -- 1 feels too slow + + -- gun + main_gun = nil, -- assign at spawn time + special_gun = nil, + fire_off_x = 4, -- offset where bullets come from + fire_off_y = 0, + + -- position + x=52, -- x and y are for upper left corner + y=96, + xmomentum = 0, + ymomentum = 0, + maxspd = 2.5, -- momentum cap + thrust = 0.25, -- momentum added from button + drag = 0.125, -- momentum lost per frame + slip = false, -- does not slide down screen + grab_butts = function(self) -- fetch buttons + local butts = grab_p1_butts() + if butts[0] == butts[1] then + self.sprite = 1 + elseif butts[0] > 0 then + self.sprite = 17 + else + self.sprite = 18 + end + return butts + end +} +mknew(player, + function(p) + p.main_gun = zap_gun.new() + end +) + +frownie = ship_m.new{ + --shape + sprite = 3, --index of ship sprite + size = 1, --all ships are square; how many 8x8 sprites? + hurt = { -- hurtbox - where this ship can be hit + x_off = 0, -- upper left corner + y_off = 1, -- relative to ship ulc + width = 8, + height = 6 + }, + sparks = smokespark, + sparkodds = 8, + + -- health and power + hp = 1, -- enemy ships need no max hp + + -- position + x=60, -- x and y are for upper left corner + y=8, + xmomentum = 0, + ymomentum = 0, + maxspd = 2, -- momentum cap + thrust = 0.12, -- momentum added from button + drag = 0.07, -- momentum lost per frame + slip = true, + grab_butts = function(discard_self) + -- buttons are effectively analog + -- and negative buttons work just fine! + local butts = {} + local tstate = (1 + flr(4*t() + 0.5)) % 6 + butts[0] = ((tstate==1 or tstate==2) and 1) or 0 + butts[1] = ((tstate==4 or tstate==5) and 1) or 0 + for b=2, 5 do + butts[b]=0 + end + return butts + end, -- button fetch algorithm +} +mknew(frownie) + +blocky = frownie.new{ + sprite = 10, + hp = 2, + hurt = { + x_off = 0, + y_off = 0, + width = 8, + height = 7 + }, + + ow = function(self) + if self.hp <= 1 then + self.sprite = 11 + else + self.sprite = 10 + end + ship_m.ow(self) + end +} +mknew(blocky) + +spewy = frownie.new{ + sprite=26, + power=-20, + hurt = { + x_off=0, + y_off=1, + width=8, + height=5 + }, + hp=1, + maxpower=70, + generator=0.5, + fire_off_x=4, + fire_off_y = 7, + grab_butts=function() + local butts=frownie.grab_butts() + butts[5]=1 + return butts + end +} +mknew(spewy, function(ship) + ship.main_gun=ship.main_gun or protron_gun.new{enemy=true} +end) + +chasey = ship_m.new{ + sprite = 5, + size = 1, + hurt = { + x_off = 1, + y_off = 2, + width = 6, + height = 5, + }, + sparks = smokespark, + sparkodds = 8, + hp = 2, + shield = 1, + maxshield = 1, + shieldcost = 180, + + fire_off_x = 4, + fire_off_y = 7, + + maxspd = 2, + thrust = 0.2, + drag = 0.075, + slip = true, +} +mknew(chasey, function(ship) + ship.main_gun=ship.main_gun or zap_gun.new{enemy=true} +end) + +function chasey:grab_butts() + local butts = {[0]=0,0,0,0,0,0} + if (self.x < primary_ship.x) butts[1] = 1 + if (self.x > primary_ship.x) butts[0] = 1 + if (self.x - 16 < primary_ship.x and self.x + 16 > primary_ship.x) butts[5] = 1 + return butts +end + +xl_chasey=chasey.new{ + size=2, + maxspd=1.25, + hurt = { + x_off = 2, + y_off = 4, + width = 12, + height = 10 + }, + hp = 20, + shield = 5, + boss = true, + slip = false, + grab_butts = function(self) + local butts = chasey.grab_butts(self) + if (self.y < 4) butts[3] = 1 + return butts + end, + draw = function(self) + if(self.fx_pal) pal(self.fx_pal) + sspr(40, 0, 8, 8, self.x, self.y, 16, 16) + pal() + end, +} +mknew(xl_chasey, function(ship) + ship.main_gun=ship.main_gun or zap_gun.new{enemy=true} +end) +-->8 +-- collisions + +-- box: x, y, width, height + +function collides(box1, box2) + return not ( + box1.x>box2.x+box2.width + or box1.y>box2.y+box2.height + or box1.x+box1.width8 +-- level and event system + +-- a level is a map from +-- effective frame number to +-- 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 + +-- a level is won when it hits +-- the end-of-level sentinel +-- and there are no more +-- tracked enemies. +-- lost when there are no +-- player ships left. + +-- effective frame +distance = 0 +-- actual frame count since +-- start of level times 0x0.0001 +lframe = 0 + +-- do not advance distance when +-- nonzero +freeze = 0 + +eol = {} + +function load_level(levelfile) + distance = 0 + lframe = 0 + freeze = 0 + leveldone = false + current_level = {} + local found_eol = false + if (type(levelfile)=="string") levelfile = csv(levelfile) + for row in all(levelfile) do + local x = current_level[row[1]] + if row[2] == "eol" then + found_eol = true + assert(x==nil, "events on eol frame") + current_level[row[1]] = eol + else + row.next = x + current_level[row[1]]=row + end + end + assert(found_eol) +end + +function level_frame() + lframe += 0x0.0001 + if (current_level == nil) return true + if freeze == 0 then + distance += 1 + local cbs = current_level[distance] + if cbs ~= nil then + if cbs == eol then + current_level = nil + return true + else + while cbs do + assert(cbs[1] == distance) + local f = _ENV[cbs[2]] + assert(type(f) == "function", cbs[2].." at "..distance.." is not a function") + f(unpack(cbs, 3)) + cbs=cbs.next + end + end + end + end + return false +end +-->8 +-- example level + +function spawn_blocking_rnd_x(typ) + freeze += 1 + s = typ.new{ + x = rnd(104), + y = -7, + ice = 1, + orig_die = typ.die, + die = function(self) + freeze -= self.ice + self.ice = 0 + self:orig_die() + end, + } + eships:push_back(s) + return s +end + +function spawn_frownie() + return spawn_rnd(frownie) +end + +function spawn_blocking_frownie() + spawn_blocking_rnd_x(frownie) +end + +function spawn_blocky() + spawn_rnd(blocky) +end + +function spawn_blocking_blocky() + spawn_rnd(blocky, 1) +end + +function spawn_spewy() + return spawn_rnd(spewy) +end + +function spawn_chasey() + return spawn_rnd(chasey) +end + +function spawn_blocking_spewy() + freeze += 1 + local s = spawn_spewy() + s.ice = 1 + s.die = function(self) + freeze -= self.ice + self.ice = 0 + frownie.die(self) + end +end + +function spawn_bonus_frownie() + local f = spawn_frownie() + f.sprite = 7 + f.die = function(self) + spawn_repair_at(self.x+4, self.y+4) + frownie.die(self) + end +end + +function spawn_bonus_vulcan_chasey() + local c = spawn_chasey() + c.main_gun=vulcan_gun.new{enemy=true} + c.die = function(self) + spawn_main_gun_at(self.x-1, self.y-1, vulcan_gun) + chasey.die(self) + end + c.sprite=4 + return c +end + +helpers = { + spawn_frownie, + spawn_frownie, + spawn_frownie, + spawn_blocky, + spawn_blocky, + spawn_chasey, + spawn_spewy, +} + +function spawn_blocking_boss_chasey() + local c = spawn_rnd(xl_chasey, 1) + local nextspawn = lframe + 0x0.0080 + events:push_back{move=function() + if lframe >= nextspawn then + helpers[flr(rnd(#helpers))+1]() + nextspawn += 0x0.0040 + end + return c.dead + end} + + return c +end + +function std_spawn(tnm, n, blocking, goodie,altspr) + local typ = _ENV[tnm] + assert(typ and typ.new, tostr(tnm).." not a class") + for i=1,(n or 1) do + spawn_rnd(typ, blocking, goodie,altspr) + end +end + +-- blocking: 1 or 0 +function spawn_rnd(typ, blocking, goodie,altspr) + blocking = blocking or 0 + freeze += blocking + s = typ.new{ + x = rnd(104), + y = -(typ.size * 8 - 1), + ice=blocking, + die=function(self) + freeze -= self.ice + self.ice=0 + typ.die(self) + spawn_goodie(goodie, self.x, self.y, self.size) + end, + } + if (altspr) s.spr = altspr + eships:push_back(s) + return s +end + +-- TODO: spawn_goodie compatible versions of gun drops +-- TODO: goodie table +function spawn_goodie(goodie_name, x, y, sz) + if (not goodie_name or #goodie_name == 0) return + local sh = sz and sz/2 or 0 + goodies[goodie_name].new{}:spawn_at(x+sh,y+sh) +end + +function multi(times, interval, fnm, ...) + local f,irm,vargs = _ENV[fnm],interval,pack(...) + assert(type(f) == "function", fnm.." not a function") + f(...) + events:push_back{move=function() + irm-=1 + if irm <= 0 then + irm=interval + times-=1 + f(unpack(vargs)) + return times <= 1 + end + end} +end + +-- 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. + +example_level_csv=[[1,spawn_frownie +60,spawn_bonus_vulcan_chasey +61,spawn_blocky +85,spawn_spewy +100,spawn_spewy +115,spawn_spewy +130,spawn_bonus_frownie +145,spawn_spewy +200,spawn_chasey +250,spawn_blocking_blocky +285,spawn_spec_gun_at,35,-11,blast_gun +310,spawn_blocking_blocky +310,spawn_blocking_blocky +310,spawn_blocking_blocky +311,spawn_frownie +350,spawn_main_gun_at,70,-11,protron_gun +401,spawn_frownie +420,spawn_blocking_frownie +430,spawn_bonus_vulcan_chasey +450,spawn_frownie +465,spawn_bonus_frownie +480,spawn_chasey +500,multi,20,12,spawn_blocking_blocky +501,spawn_bonus_frownie +620,spawn_blocking_blocky +700,spawn_blocking_boss_chasey +701,eol]] + -->8 -- readme.md @@ -1969,6 +1934,7 @@ gun_swap = powerup.new{ mknew(gun_swap) function spawn_main_gun_at(x, y, gunt) + if (type(gunt)=="string") gunt=_ENV[gunt] local gun_p = gun_swap.new{ gun = gunt.new() } @@ -1982,6 +1948,7 @@ spec_gun_pl = { } function spawn_spec_gun_at(x, y, gunt) + if (type(gunt)=="string") gunt=_ENV[gunt] local gun_p = gun_swap.new{ gun = gunt.new(), hitship = function(self, ship)