replace demo level with infinite copies of flotilla 0

This commit is contained in:
Kistaro Windrider 2025-05-31 21:29:54 -07:00
parent 267f8a3667
commit 0bd1463416
Signed by: kistaro
SSH Key Fingerprint: SHA256:TBE2ynfmJqsAf0CP6gsflA0q5X5wD5fVKWPsZ7eVUg8

View File

@ -171,6 +171,10 @@ function wipe_game()
new_events = linked_list.new() new_events = linked_list.new()
primary_ship.main_gun = zap_gun_p.new() primary_ship.main_gun = zap_gun_p.new()
primary_ship.main_gun:peel() primary_ship.main_gun:peel()
gframe = 0
interlude = 0
waves_complete = 0
current_wave = nil
end end
function _update60() function _update60()
@ -185,12 +189,42 @@ function call_move(x)
return x:move() return x:move()
end end
function ones(n)
local ret = 0
while n != 0 do
ret +=
end
end
function updategame() function updategame()
if (primary_ship.xp >= primary_ship.xptarget) and (lframe - primary_ship.last_xp_frame > 0x0.000f) and (not primary_ship.dead) then if (primary_ship.xp >= primary_ship.xptarget) and (gframe - primary_ship.last_xp_frame > 0x0.000f) and (not primary_ship.dead) then
mode = rearm_mode.new() mode = rearm_mode.new()
return _update60() return _update60()
end end
leveldone = level_frame() gframe += 1
if current_wave then
if current_wave:update() then
-- end of stage
waves_complete += 1
current_wave = nil
if waves_complete < 32767 then
interlude = 59 -- plus one dead frame with load_level but no update
else
-- you maxed out the level
-- counter. what the fuck
-- is wrong with you?
-- go outside.
--
-- do not spawn more levels.
interlude = 32767
end
end
elseif interlude > 0 then
interlude -= 1
else
current_wave = flotilla.new()
current_wave:load_level(0, 0, min(ones(waves_complete)\2, 4))
end
events:vore(new_events) events:vore(new_events)
events:strip(call_move) events:strip(call_move)
for _, lst in ipairs{intangibles_bg, pships, eships, pbullets, ebullets} do for _, lst in ipairs{intangibles_bg, pships, eships, pbullets, ebullets} do
@ -254,7 +288,7 @@ function updategame()
intangibles_fg:strip(call_move) intangibles_fg:strip(call_move)
if leveldone and not eships.next and not ebullets.next and not events.next then if waves_complete == 32767 and not eships.next and not ebullets.next and not events.next then
game_state = win game_state = win
end end
if (not pships.next) game_state = lose if (not pships.next) game_state = lose
@ -619,7 +653,7 @@ end
function ship_m:hitsomething(dmg) function ship_m:hitsomething(dmg)
if (dmg <= 0) return false if (dmg <= 0) return false
self.shield_refresh_ready = lframe + self.shieldpenalty self.shield_refresh_ready = gframe + self.shieldpenalty
if self.shield > 0 then if self.shield > 0 then
self.shield -= dmg self.shield -= dmg
if self.shield > 0 then if self.shield > 0 then
@ -641,10 +675,10 @@ end
function ship_m:refresh_shield() function ship_m:refresh_shield()
if (self.shield >= self.maxshield) return if (self.shield >= self.maxshield) return
if (lframe < self.shield_refresh_ready) return if (gframe < self.shield_refresh_ready) return
self.shield += 1 self.shield += 1
self.shield = min(self.shield, self.maxshield) self.shield = min(self.shield, self.maxshield)
self.shield_refresh_ready = lframe + self.shieldcooldown self.shield_refresh_ready = gframe + self.shieldcooldown
end end
-->8 -->8
@ -813,12 +847,12 @@ function bullet_base:spawn_at(x, y)
end end
function gun_base:shoot(x, y) function gun_base:shoot(x, y)
if (lframe < self.shoot_ready) return false if (gframe < self.shoot_ready) return false
if self.ammo then if self.ammo then
if (self.ammo <= 0) return false if (self.ammo <= 0) return false
self.ammo -= 1 self.ammo -= 1
end end
self.shoot_ready = lframe + self.cooldown self.shoot_ready = gframe + self.cooldown
self:actually_shoot(x, y) self:actually_shoot(x, y)
return true return true
end end
@ -1251,81 +1285,10 @@ shield will
return ret return ret
end end
frownie = mknew(ship_m.new{ -- original prototype leftover;
--shape -- likely to be the basis of a
sprite = 3, --index of ship sprite -- standard raider type, so
size = 1, --all ships are square; how many 8x8 sprites? -- i am keeping it around
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,
hp = 0.5, -- enemy ships need no max hp
xp = 0x0.0001,
-- 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,
act = function(self)
local tstate,dx = (1 + flr(4*t() + 0.5)) % 6,0
if (tstate==1 or tstate==2) dx=-self.thrust
if (tstate>=4) dx=self.thrust
return dx,0,false,false
end,
})
blocky = mknew(frownie.new{
sprite = 10,
hp = 1.5,
xp = 0x0.0002,
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
})
spewy = mknew(frownie.new{
sprite=26,
xp = 0x0.0003,
hurt = {
x_off=0,
y_off=1,
width=8,
height=5
},
hp=0.5,
fire_off_x=4,
fire_off_y=7,
act=function(self)
local dx,dy,shoot_spec=frownie.act(self)
return dx, dy, shoot_spec, self.y > 10
end,
init = function(ship)
ship.main_gun=ship.main_gun or protron_gun_e.new{}
end
})
chasey = mknew(ship_m.new{ chasey = mknew(ship_m.new{
sprite = 5, sprite = 5,
xp = 0x0.0004, xp = 0x0.0004,
@ -1658,259 +1621,6 @@ function flotilla:update()
return false -- some ships remain return false -- some ships remain
end end
-->8
-- 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_vulcan_chasey()
local c = spawn_chasey()
c.main_gun=vulcan_gun_e.new{enemy=true}
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)
end,
}
if (altspr) s.spr = altspr
eships:push_back(s)
return s
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
function demo_spawn_f(ttn)
local spx,spy=rnd_spawn_loc()
local s = _ENV[ttn].new{
x = spx,
y = spy,
want_x = 8 + rnd(96),
want_y = 8 + rnd(64)
}
eships:push_back(s)
return s
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
20,demo_spawn_f,ship_mook
25,demo_spawn_f,ship_defender
30,demo_spawn_f,ship_turret
35,demo_spawn_f,ship_skirmisher
80,spawn_vulcan_chasey
81,spawn_blocky
100,spawn_spewy
125,spawn_spewy
130,spawn_frownie
145,spawn_frownie
180,spawn_spewy
230,spawn_chasey
250,spawn_blocking_blocky
310,spawn_blocking_blocky
310,spawn_blocking_blocky
310,spawn_blocking_blocky
311,spawn_frownie
401,spawn_frownie
420,spawn_blocking_frownie
430,spawn_vulcan_chasey
450,spawn_frownie
465,spawn_frownie
480,spawn_chasey
500,multi,20,12,spawn_blocking_blocky
501,spawn_frownie
620,spawn_blocking_blocky
630,spawn_vulcan_chasey
720,spawn_blocking_boss_chasey
721,eol]]
-->8 -->8
-- standard events -- standard events
@ -2017,10 +1727,10 @@ function xp_gem:draw()
-- sprite map position: -- sprite map position:
-- sprite id to x and y, -- sprite id to x and y,
-- offset shifts specific low -- offset shifts specific low
-- bits of lframe up to the the -- bits of gframe up to the the
-- bit with value 4 as a cheap -- bit with value 4 as a cheap
-- way to pick an anim frame -- way to pick an anim frame
if (lframe&0x0.003 == 0) qx, qy = (lframe&0x0.0004)<<16, (lframe&0x0.0008)<<15 if (gframe&0x0.003 == 0) qx, qy = (gframe&0x0.0004)<<16, (gframe&0x0.0008)<<15
sspr( sspr(
(s%16<<3)+qx, (s%16<<3)+qx,
(s\16<<3)+qy, (s\16<<3)+qy,
@ -2046,7 +1756,7 @@ end
function xp_gem:hitship(ship) function xp_gem:hitship(ship)
if (ship ~= primary_ship or primary_ship.dead) return false if (ship ~= primary_ship or primary_ship.dead) return false
primary_ship.xp += self.val primary_ship.xp += self.val
primary_ship.last_xp_frame = lframe primary_ship.last_xp_frame = gframe
return true return true
end end