Compare commits
32 Commits
288b7f64c8
...
flotillas
Author | SHA1 | Date | |
---|---|---|---|
3151db5430
|
|||
2964159858
|
|||
95d4b6eb37
|
|||
96312e3adf
|
|||
bf9a45d87e
|
|||
36f7c6572f
|
|||
45b70d3aca
|
|||
35980d801a
|
|||
734811bd62
|
|||
4fddbea82c
|
|||
f675e31967
|
|||
0bd1463416
|
|||
267f8a3667
|
|||
fa206c37c5
|
|||
928e7f7418
|
|||
2439fda068
|
|||
d13290f438
|
|||
e3a2810f0a
|
|||
3764063b20
|
|||
90f6df2922
|
|||
b7c3e6ee92
|
|||
c91e5f4bd1
|
|||
ea2ddadb15
|
|||
9333c03bf3
|
|||
1b45bd3dc3
|
|||
71a7351d77
|
|||
80bb848468
|
|||
b227844d12
|
|||
ce14d03669
|
|||
ccd2c64103
|
|||
e5b8a30cb6
|
|||
7ed305d2d9
|
769
vacuum_gambit.p8
769
vacuum_gambit.p8
@ -127,7 +127,6 @@ function _init()
|
||||
mode = game_mode
|
||||
init_blip_pals()
|
||||
wipe_game() -- redundant?
|
||||
load_level(example_level_csv)
|
||||
game_state = game
|
||||
pal(2,129)
|
||||
pal()
|
||||
@ -171,6 +170,10 @@ function wipe_game()
|
||||
new_events = linked_list.new()
|
||||
primary_ship.main_gun = zap_gun_p.new()
|
||||
primary_ship.main_gun:peel()
|
||||
gframe = 0
|
||||
interlude = 0
|
||||
waves_complete = 0
|
||||
current_wave = nil
|
||||
end
|
||||
|
||||
function _update60()
|
||||
@ -185,12 +188,44 @@ function call_move(x)
|
||||
return x:move()
|
||||
end
|
||||
|
||||
function ones(n)
|
||||
local ret = 0
|
||||
while n != 0 do
|
||||
if (n&0x0.0001) ret += 1
|
||||
n >>= 1
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
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()
|
||||
return _update60()
|
||||
end
|
||||
leveldone = level_frame()
|
||||
gframe += 0x0.0001
|
||||
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(0, 0, min(ones(waves_complete)\2, 4))
|
||||
end
|
||||
events:vore(new_events)
|
||||
events:strip(call_move)
|
||||
for _, lst in ipairs{intangibles_bg, pships, eships, pbullets, ebullets} do
|
||||
@ -254,7 +289,7 @@ function updategame()
|
||||
|
||||
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
|
||||
end
|
||||
if (not pships.next) game_state = lose
|
||||
@ -466,6 +501,14 @@ end
|
||||
-->8
|
||||
--ship behavior
|
||||
|
||||
-- generic full sprite hurtbox
|
||||
box8 = {
|
||||
x_off = 0,
|
||||
y_off = 1,
|
||||
width = 8,
|
||||
height = 8
|
||||
}
|
||||
|
||||
scrollrate = 0.25 --in px/frame
|
||||
|
||||
ship_m = mknew{
|
||||
@ -611,7 +654,7 @@ end
|
||||
|
||||
function ship_m:hitsomething(dmg)
|
||||
if (dmg <= 0) return false
|
||||
self.shield_refresh_ready = lframe + self.shieldpenalty
|
||||
self.shield_refresh_ready = gframe + self.shieldpenalty
|
||||
if self.shield > 0 then
|
||||
self.shield -= dmg
|
||||
if self.shield > 0 then
|
||||
@ -633,10 +676,10 @@ end
|
||||
|
||||
function ship_m:refresh_shield()
|
||||
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 = min(self.shield, self.maxshield)
|
||||
self.shield_refresh_ready = lframe + self.shieldcooldown
|
||||
self.shield_refresh_ready = gframe + self.shieldcooldown
|
||||
end
|
||||
|
||||
-->8
|
||||
@ -676,7 +719,13 @@ bullet_base = mknew{ }
|
||||
|
||||
gun_base = mknew{
|
||||
shoot_ready = -32768,
|
||||
icon = 20
|
||||
icon = 20,
|
||||
ammobonus = 1,
|
||||
|
||||
-- fractional frames of
|
||||
-- cooldown reduction from
|
||||
-- upgrades, not yet applied
|
||||
cd_remainder = 0,
|
||||
}
|
||||
|
||||
-- gun_base subtypes are
|
||||
@ -707,6 +756,68 @@ function gun_base:actually_shoot(x, y)
|
||||
self.munition.new{}:spawn_at(x, y)
|
||||
end
|
||||
|
||||
-- upgrade
|
||||
function gun_base:small_upgrade_opts()
|
||||
local ret = {
|
||||
self:ammo_upgrade_opt(),
|
||||
self:rate_upgrade_opt(),
|
||||
}
|
||||
local s = self.special_upgrade_opt
|
||||
if (s) add(ret, s(self))
|
||||
return ret
|
||||
end
|
||||
|
||||
function gun_base:ammo_upgrade_opt()
|
||||
local a=self.maxammo
|
||||
local x=a\10+self.ammobonus
|
||||
return {
|
||||
icon=self.icon,
|
||||
hdr=self.hdr,
|
||||
body=[[--------AMMO
|
||||
|
||||
more shots
|
||||
before you
|
||||
run out.
|
||||
|
||||
is: ]]..tostr(a)..[[
|
||||
add: ]]..tostr(x)..[[
|
||||
----------
|
||||
total: ]]..tostr(a+x),
|
||||
action=function()
|
||||
self.maxammo+=x
|
||||
self.ammo+=x
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
function gun_base:rate_upgrade_opt()
|
||||
local c=self.cooldown<<16
|
||||
local rawnewc=0.85*(c-self.cd_remainder)
|
||||
local newc=ceil(rawnewc)
|
||||
return {
|
||||
icon=self.icon,
|
||||
hdr=self.hdr,
|
||||
body=[[--------RATE
|
||||
|
||||
reduce delay
|
||||
between each
|
||||
shot when
|
||||
firing.
|
||||
|
||||
is: ]]..tostr(c)..[[f
|
||||
minus: ]]..tostr(c-newc)..[[f
|
||||
----------
|
||||
total: ]]..tostr(newc)..[[f
|
||||
|
||||
remainder:
|
||||
]]..sub(tostr(newc-rawnewc),0,5),
|
||||
action=function()
|
||||
self.cooldown=newc>>16
|
||||
self.cd_remainder=newc-rawnewc
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
function bullet_base:hitship(_)
|
||||
self:die()
|
||||
return true
|
||||
@ -737,12 +848,12 @@ function bullet_base:spawn_at(x, y)
|
||||
end
|
||||
|
||||
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 <= 0) return false
|
||||
self.ammo -= 1
|
||||
end
|
||||
self.shoot_ready = lframe + self.cooldown
|
||||
self.shoot_ready = gframe + self.cooldown
|
||||
self:actually_shoot(x, y)
|
||||
return true
|
||||
end
|
||||
@ -848,10 +959,12 @@ blast_gun = mknew(gun_base.new{
|
||||
maxammo = 5,
|
||||
munition = blast,
|
||||
hdr = "bLASTER",
|
||||
body= [[plasma orb
|
||||
body= [[---------GUN
|
||||
|
||||
plasma orb
|
||||
cuts through
|
||||
enemies.
|
||||
slow.
|
||||
enemies.
|
||||
slow.
|
||||
|
||||
ammo: 5
|
||||
rate: 1/2sec
|
||||
@ -920,9 +1033,11 @@ protron_gun_p = mknew(protron_gun_e.new{
|
||||
maxammo = 20,
|
||||
cooldown = 0x0.0018,
|
||||
hdr = "pROTRON",
|
||||
body = [[spray shots
|
||||
in a dense
|
||||
arc.
|
||||
body = [[---------GUN
|
||||
|
||||
spray shots
|
||||
in a dense
|
||||
arc.
|
||||
|
||||
ammo: 20
|
||||
rate: 2/sec
|
||||
@ -981,9 +1096,10 @@ vulcan_gun_p = mknew(vulcan_gun_e.new{
|
||||
munition=vulcan_p,
|
||||
maxammo = 100,
|
||||
hdr = "vULCAN",
|
||||
body = [[rapid fire
|
||||
in a v
|
||||
shape.
|
||||
body = [[---------GUN
|
||||
|
||||
rapidly fire
|
||||
in a v.
|
||||
|
||||
ammo: 100
|
||||
rate: 20/sec
|
||||
@ -1074,7 +1190,11 @@ function player:small_upgrade_opts()
|
||||
local ret = {{
|
||||
icon=53,
|
||||
hdr="hull",
|
||||
body=[[ armor
|
||||
body=[[--------SHIP
|
||||
|
||||
survive more
|
||||
unshielded
|
||||
hits.
|
||||
|
||||
+2 hp]],
|
||||
action=function()
|
||||
@ -1083,8 +1203,13 @@ function player:small_upgrade_opts()
|
||||
end,
|
||||
},{
|
||||
icon=52,
|
||||
hdr="shield",
|
||||
body=[[ capacity
|
||||
hdr="capacity",
|
||||
body=[[------SHIELD
|
||||
|
||||
shield can
|
||||
absorb more
|
||||
hits before
|
||||
recharging.
|
||||
|
||||
+1 hp]],
|
||||
action=function()
|
||||
@ -1094,10 +1219,11 @@ function player:small_upgrade_opts()
|
||||
},{
|
||||
icon=1,
|
||||
hdr="thrusters",
|
||||
body=[[performance
|
||||
|
||||
body=[[--------SHIP
|
||||
|
||||
move faster,
|
||||
steer faster]],
|
||||
steer more
|
||||
sharply.]],
|
||||
action=function()
|
||||
--maxspd thrust drag
|
||||
self.maxspd += 0.5
|
||||
@ -1106,22 +1232,29 @@ steer faster]],
|
||||
end,
|
||||
},{
|
||||
icon=20,
|
||||
hdr="hull",
|
||||
body=[[ magnet
|
||||
|
||||
hdr="magnet",
|
||||
body=[[--------SHIP
|
||||
|
||||
pick up xp
|
||||
from further
|
||||
away]],
|
||||
away.]],
|
||||
action=function ()
|
||||
self.magnet += 2
|
||||
end,
|
||||
}}
|
||||
},
|
||||
self.main_gun:rate_upgrade_opt(),
|
||||
}
|
||||
|
||||
if cdr > 0 then
|
||||
add(ret, {
|
||||
icon = 6,
|
||||
hdr = "shield",
|
||||
body=[[charge rate
|
||||
hdr = "recharge",
|
||||
body=[[------SHIELD
|
||||
|
||||
shield will
|
||||
recharge at
|
||||
a faster
|
||||
pace.
|
||||
|
||||
]] .. tostr(ceil(100 * cdr / self.shieldcooldown)) .. "% faster",
|
||||
action = function()
|
||||
@ -1133,8 +1266,15 @@ from further
|
||||
if pr > 0 then
|
||||
add(ret, {
|
||||
icon = 6,
|
||||
hdr = "shield",
|
||||
body=[[disruption
|
||||
hdr = "recovery",
|
||||
body=[[------SHIELD
|
||||
|
||||
reduce the
|
||||
delay after
|
||||
a hit before
|
||||
shield will
|
||||
start to
|
||||
recharge.
|
||||
|
||||
]] .. tostr(ceil(100 * pr / self.shieldpenalty)) .. "% shorter",
|
||||
action = function()
|
||||
@ -1146,81 +1286,10 @@ from further
|
||||
return ret
|
||||
end
|
||||
|
||||
frownie = mknew(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,
|
||||
|
||||
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
|
||||
})
|
||||
|
||||
-- original prototype leftover;
|
||||
-- likely to be the basis of a
|
||||
-- standard raider type, so
|
||||
-- i am keeping it around
|
||||
chasey = mknew(ship_m.new{
|
||||
sprite = 5,
|
||||
xp = 0x0.0004,
|
||||
@ -1250,7 +1319,6 @@ chasey = mknew(ship_m.new{
|
||||
end
|
||||
})
|
||||
|
||||
-- todo: use constraints
|
||||
function chasey:act()
|
||||
self.xmin = max(primary_ship.x-8, 0)
|
||||
self.xmax = min(primary_ship.x + 8, 112 - 8*self.size)
|
||||
@ -1288,6 +1356,53 @@ xl_chasey=mknew(chasey.new{
|
||||
end,
|
||||
})
|
||||
|
||||
-- flotilla ships
|
||||
|
||||
ship_f = mknew(ship_m.new{
|
||||
-- sprite required
|
||||
size = 1,
|
||||
hurt = box8,
|
||||
-- no sparks
|
||||
hp = 0.5,
|
||||
xp = 0x0.0001,
|
||||
|
||||
maxspd = 3,
|
||||
thrust = 0.1,
|
||||
drag = 0.05,
|
||||
slip = false,
|
||||
act = function(self)
|
||||
local wx,wy=self.want_x,self.want_y
|
||||
self.xmin,self.xmax,self.ymin,self.ymax = wx,wx,wy,wy
|
||||
return 0,0,false,false
|
||||
end,
|
||||
})
|
||||
|
||||
ship_mook = mknew(ship_f.new{
|
||||
sprite=103
|
||||
})
|
||||
ship_defender = mknew(ship_f.new{
|
||||
sprite=105,
|
||||
hp = 2.5,
|
||||
xp = 0x0.0003,
|
||||
})
|
||||
ship_turret = mknew(ship_f.new{
|
||||
sprite=106,
|
||||
xp = 0x0.0002,
|
||||
})
|
||||
ship_skirmisher = mknew(ship_f.new{
|
||||
sprite=107,
|
||||
xp = 0x0.0004,
|
||||
spark = smokespark,
|
||||
sparkodds = 4,
|
||||
})
|
||||
|
||||
function rnd_spawn_loc()
|
||||
local x,y = flr(rnd(304)), flr(rnd(32))
|
||||
if (x<184) return x-40,-y-8
|
||||
if (x<244) return -y-8,x-184
|
||||
return 112+y, x-244
|
||||
end
|
||||
|
||||
-->8
|
||||
-- collisions
|
||||
|
||||
@ -1352,242 +1467,163 @@ function collider:get_collisions(item)
|
||||
end
|
||||
return found
|
||||
end
|
||||
|
||||
-->8
|
||||
-- level and event system
|
||||
-- flotillas
|
||||
|
||||
-- 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.
|
||||
-- a template for a wave, read
|
||||
-- from the map. each ship can
|
||||
-- alternate between "attack"
|
||||
-- and "formation" modes, like
|
||||
-- galaxian or galaga. ships
|
||||
-- with different roles have
|
||||
-- different rules for becoming
|
||||
-- aggressive, but aggression
|
||||
-- ramps up during the wave.
|
||||
|
||||
-- effective frame number stops
|
||||
-- when freeze count is nonzero
|
||||
-- flotilla placeholders are
|
||||
-- defined by sprite flags.
|
||||
-- see obsidian vault for
|
||||
-- full docs.
|
||||
|
||||
-- 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,
|
||||
flotilla = mknew{
|
||||
use_var = 0x1111,
|
||||
opt_odds = split"0.5,0.5,0.5,0.5",
|
||||
init=function(this)
|
||||
this.ship_bases={
|
||||
[0]=mknew(ship_mook.new{ship_t=0}),
|
||||
[1]=mknew(ship_mook.new{ship_t=1, sprite=104}),
|
||||
[4]=mknew(ship_defender.new{ship_t=4}),
|
||||
[5]=mknew(ship_defender.new{ship_t=5, sprite=10}),
|
||||
[8]=mknew(ship_turret.new{ship_t=8}),
|
||||
[9]=mknew(ship_turret.new{ship_t=9, sprite=4}),
|
||||
[12]=mknew(ship_skirmisher.new{ship_t=12}),
|
||||
[13]=mknew(ship_skirmisher.new{ship_t=13, sprite=26}),
|
||||
}
|
||||
end,
|
||||
}
|
||||
|
||||
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,
|
||||
function flotilla:load(ulc_cx, ulc_cy, lvl)
|
||||
local rows,cy,uv,counts={},ulc_cy,self.use_var,{
|
||||
[0]=0,
|
||||
[1]=0,
|
||||
[4]=0,
|
||||
[5]=0,
|
||||
[8]=0,
|
||||
[9]=0,
|
||||
[12]=0,
|
||||
[13]=0,
|
||||
}
|
||||
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
|
||||
repeat
|
||||
local row,cx,opt,f,mode= {},ulc_cx,{},0,0
|
||||
for i,v in ipairs(self.opt_odds) do
|
||||
opt[i*4-4]=rnd()<v
|
||||
end
|
||||
end}
|
||||
repeat
|
||||
f=fget(mget(cx, cy))
|
||||
-- bits 0x03: control mark or ship?
|
||||
mode = f&0x03
|
||||
if mode==2 then
|
||||
-- bits 0x0c: ship class
|
||||
local ship_t = f&0x0c
|
||||
-- bit 0x20: optional?
|
||||
if f&0x20 == 0 or opt[ship_t] then
|
||||
-- bit 0x10: alternate ship?
|
||||
-- increment ship id if
|
||||
-- alternate is requested
|
||||
-- and we allow alternates
|
||||
-- for this type of ship
|
||||
ship_t+=(uv>>ship_t&0x1)&((f&0x10)>>4)
|
||||
add(row, self.ship_bases[ship_t].new{col=cx-ulc_cx})
|
||||
end
|
||||
end
|
||||
cx += 1
|
||||
until mode==1
|
||||
-- mode 1: end of line control mark
|
||||
-- bits 0x18: what size flotilla is this row used for?
|
||||
if (f&0x18)>>3 <= lvl then
|
||||
-- keep the row; count it
|
||||
for s in all(row) do
|
||||
counts[s.ship_t] += 1
|
||||
s.x,s.y=rnd_spawn_loc()
|
||||
eships:push_back(s)
|
||||
end
|
||||
add(rows, row)
|
||||
end
|
||||
cy += 1
|
||||
-- control mark bit 0x04: end of flotilla
|
||||
until f&0x04 > 0
|
||||
self.rows=rows
|
||||
self:statisfy(counts)
|
||||
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.
|
||||
function flotilla:statisfy(counts)
|
||||
-- TODO: now that we know how
|
||||
-- many ships of each kind
|
||||
-- exist, build ships to match
|
||||
-- difficulty target
|
||||
--
|
||||
-- no difficulty model is yet
|
||||
-- implemented, though, so
|
||||
-- just use base ships only
|
||||
-- for this prototype
|
||||
end
|
||||
|
||||
example_level_csv=[[1,spawn_frownie
|
||||
60,spawn_vulcan_chasey
|
||||
61,spawn_blocky
|
||||
85,spawn_spewy
|
||||
115,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]]
|
||||
function flotilla:update()
|
||||
-- algorithm: redistribute
|
||||
-- TODO: alternate flotilla movement algorithms
|
||||
|
||||
-- find effective width and height
|
||||
local min_col,max_col,live_rows=999,0,0
|
||||
for row in all(self.rows) do
|
||||
local row_alive=false
|
||||
for ship in all(row) do
|
||||
if not ship.dead then
|
||||
row_alive=true
|
||||
local col=ship.col
|
||||
if (col < min_col) min_col = col
|
||||
if (col > max_col) max_col = col
|
||||
end
|
||||
end -- scanned row
|
||||
if (row_alive) live_rows += 1
|
||||
end -- extent search
|
||||
|
||||
if (live_rows == 0) return true -- done
|
||||
|
||||
-- distribute across box:
|
||||
-- x = [4, 100)
|
||||
-- y = [4, 60)
|
||||
|
||||
local x_interval,x_offset = 0,52
|
||||
if min_col < max_col then
|
||||
x_interval=96/(max_col-min_col)
|
||||
x_offset = 4-min_col*x_interval
|
||||
end
|
||||
|
||||
local y_interval,y_offset=0,40
|
||||
if live_rows > 1 then
|
||||
y_interval=52/(live_rows-1)
|
||||
y_offset=4-y_interval
|
||||
end
|
||||
|
||||
-- now assign target locations
|
||||
local real_row=0
|
||||
for row in all(self.rows) do
|
||||
local row_alive = false
|
||||
for ship in all(row) do
|
||||
if not ship.dead then
|
||||
if not row_alive then
|
||||
real_row += 1
|
||||
row_alive = true
|
||||
end
|
||||
ship.want_x = ship.col * x_interval + x_offset
|
||||
ship.want_y = real_row * y_interval + y_offset
|
||||
end -- ship updated
|
||||
end -- row updated
|
||||
end -- table updated
|
||||
|
||||
return false -- some ships remain
|
||||
end
|
||||
|
||||
-->8
|
||||
-- standard events
|
||||
@ -1695,10 +1731,10 @@ function xp_gem:draw()
|
||||
-- sprite map position:
|
||||
-- sprite id to x and y,
|
||||
-- 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
|
||||
-- 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(
|
||||
(s%16<<3)+qx,
|
||||
(s\16<<3)+qy,
|
||||
@ -1724,7 +1760,7 @@ end
|
||||
function xp_gem:hitship(ship)
|
||||
if (ship ~= primary_ship or primary_ship.dead) return false
|
||||
primary_ship.xp += self.val
|
||||
primary_ship.last_xp_frame = lframe
|
||||
primary_ship.last_xp_frame = gframe
|
||||
return true
|
||||
end
|
||||
|
||||
@ -1795,7 +1831,12 @@ end
|
||||
-- ordinary upgrades
|
||||
function small_opts()
|
||||
-- todo: include gun opts
|
||||
return pick(primary_ship:small_upgrade_opts(), 2)
|
||||
if(not primary_ship.special_guns) return pick(primary_ship:small_upgrade_opts(), 2)
|
||||
local opts = {rnd(primary_ship:small_upgrade_opts())}
|
||||
for g in all(primary_ship.special_guns) do
|
||||
add(opts, rnd(g:small_upgrade_opts()))
|
||||
end
|
||||
return pick(opts, 2)
|
||||
end
|
||||
|
||||
-->8
|
||||
@ -1804,7 +1845,7 @@ end
|
||||
rearm_mode = mknew{
|
||||
sel=1,
|
||||
bfm=1,
|
||||
crt_frm = 1,
|
||||
crt_frm = 0,
|
||||
pos=-1,
|
||||
init=function(this)
|
||||
poke(0x5f5c, 255) --no btnp repeat
|
||||
@ -1819,7 +1860,7 @@ function rearm_mode:glow_box(x0, y0, x1, y1, c, cf)
|
||||
i -= 1
|
||||
rect(x0+i,y0+i,x1-i,y1-i,v)
|
||||
end
|
||||
fillp(crt[self.crt_frm&0xff])
|
||||
fillp(crt[1+(self.crt_frm&7)])
|
||||
rectfill(x0+4, y0+4, x1-4, y1-4, cf)
|
||||
fillp()
|
||||
end
|
||||
@ -1851,7 +1892,7 @@ end
|
||||
|
||||
function rearm_mode:draw_option(id)
|
||||
local rec = self.options[id]
|
||||
self:glow_box(0,0,55,100,self:frame_col(self.sel == id),1)
|
||||
self:glow_box(0,0,55,101,self:frame_col(self.sel == id),1)
|
||||
spr(rec.icon,5, 5)
|
||||
print(rec.hdr, 13, 8, 7)
|
||||
print(rec.body, 5, 15, 6)
|
||||
@ -1887,9 +1928,9 @@ function rearm_mode:draw()
|
||||
camera(frac * -128 + (1-frac) * -56, 0)
|
||||
self:draw_option(2)
|
||||
camera(0, -28 * frac)
|
||||
self:glow_box(0,101,111,127,self:frame_col(self.sel < 0),1)
|
||||
self:glow_box(0,102,111,127,self:frame_col(self.sel < 0),1)
|
||||
spr(96,15,107,4,2)
|
||||
print("full ammo\nfull shield\n+50% health",54, 106, 6)
|
||||
print("full ammo\nfull shield\n+50% health",54, 107, 6)
|
||||
end
|
||||
|
||||
function rearm_mode:update_pos()
|
||||
@ -1909,6 +1950,7 @@ function rearm_mode:update_pos()
|
||||
end
|
||||
|
||||
function rearm_mode:update()
|
||||
self.crt_frm+=0.25
|
||||
self:update_pos()
|
||||
if self.pos > 1 then
|
||||
mode = game_mode
|
||||
@ -2003,21 +2045,21 @@ cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
04444400044444440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
447777700477777a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
477aaa7a0477aaaa0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
47a0047a047a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
47a0447a047a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
47a4477a047a44400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
477777a00477777a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
477770000422aaaa2222000200000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
47a77700022ee0002eeee002e00022e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
47a4777002ea2e002e002e02ee022ee0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
47a0477a22ea2e002e002e02e2e2e2e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
47a0047a2e2222e02e222e02e02e02e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
47a0047a2eeeeeea2eeee002e02e02e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0aa000aa2e7aa2ea2e00e002e02e02e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000002e0002e02e002e02e02e02e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
044444000444444400000000000000000000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
|
||||
447777700477777a0000000000000000000000000000000000000000000666000077700008888800000ab00006000060000bb000000aa0000009900000088000
|
||||
477aaa7a0477aaaa0000000000000000000000000000000000000000006ddd5007fff70008eeee20000ab00006c006d0000bb000000aa0000009900000088000
|
||||
47a0047a047a0000000000000000000000000000000000000000000006dd7d5007ffff4008eeee200aaabbb006ccccd0000bb000000aa0000009900000088000
|
||||
47a0447a047a0000000000000000000000000000000000000000000006d7dd5007ffff4008eeee200bbb333006ccccd0000bb000000aa0000009900000088000
|
||||
47a4477a047a4440000000000000000000000000000000000000000006ddd500004fff4008eeee20000b300006d00cd0000bb000000aa0000009900000088000
|
||||
477777a00477777a0000000000000000000000000000000000000000005550000004440002222200000b30000d0000d0000bb000000aa0000009900000088000
|
||||
477770000422aaaa22220002000002000000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
|
||||
47a77700022ee0002eeee002e00022e00000000000000000000000000000000000000000000000000000000000000000000bb000000aa0000009900000088000
|
||||
47a4777002ea2e002e002e02ee022ee00000000000000000000000000005600000474000028282000004b000060000000bbbbbb00aaaaaa00999999008888880
|
||||
47a0477a22ea2e002e002e02e2e2e2e0000000000000000000000000005d0d0004f0f400080e0e00000a000000c000d00b0000b00a0000a00900009008000080
|
||||
47a0047a2e2222e02e222e02e02e02e000000000000000000000000005d07050070f0f2002e0e02004a0b0b0060c0c000b0bb0b00a0aa0a00909909008088080
|
||||
47a0047a2eeeeeea2eeee002e02e02e000000000000000000000000006070d1004f0f040080e0e000b0b035000c0c0d00b0bb0b00a0aa0a00909909008088080
|
||||
0aa000aa2e7aa2ea2e00e002e02e02e000000000000000000000000000d0d100002f0f2002e0e0200000300006000c000b0000b00a0000a00900009008000080
|
||||
000000002e0002e02e002e02e02e02e0000000000000000000000000000510000002420002020200000b5000000000d00bbbbbb00aaaaaa00999999008888880
|
||||
000000000e0000e00e000e00e00e00e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
__label__
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007777777777777777
|
||||
@ -2149,3 +2191,12 @@ __label__
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007555555555555555
|
||||
|
||||
__gff__
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000212060a0e01091119000000000000002232363a3e050d151d
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
__map__
|
||||
00006b6b00006f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
7b6a00006a7b6e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
7778686878776c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
6767777767676c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
7877676777787d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
|
Reference in New Issue
Block a user