Compare commits

..

15 Commits

7 changed files with 79 additions and 4625 deletions

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
.DS_Store
.vscode/settings.json

View File

@ -1,244 +0,0 @@
pico-8 cartridge // http://www.pico-8.com
version 41
__lua__
-- vacuum gambit automatic brake test
-- by kistaro windrider
function usplit(str)
return unpack(split(str))
end
function csv(s)
local ret = split(s, "\n")
for i, v in ipairs(ret) do
ret[i] = type(v) == "string" and split(v) or { v }
end
return ret
end
-- generate standard "overlay"
-- constructor for type tt.
-- if more is defined, generated
-- new calls more(ret) after
-- 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, 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
function _init()
pal(1,129,1)
the_ship = ship.new()
constraints:setup()
slomo = 1
sloc = 0
reroll()
end
function reroll()
frames=0
sloc=0
the_ship:reroll()
end
function _update60()
if (btnp(4)) reroll()
if (btnp(5)) constraints:cycle()
if (btnp(3)) slomo <<= 1
if (btnp(2)) slomo >>= 1
slomo = (slomo < 1) and 1 or (slomo > 8192) and 8192 or slomo
sloc += 1
if sloc >= slomo then
frames += 1
the_ship:update()
sloc=0
end
end
function _draw()
cls(1)
constraints:draw()
the_ship:draw()
print("frames: " .. frames, 4, 64, 7)
print("speed: 1/" .. slomo, 8, 70, 7)
print("thrust: ".. actual_t, 4, 80, 7)
meter(80, 80, 128, 84, actual_t/the_ship.thrust/2)
print("dx: ".. the_ship.dx, 20, 86, 7)
meter(80, 86, 128, 90, the_ship.dx/the_ship.maxspd/2)
print("x: "..the_ship.x, 24, 92, 7)
print("bx: "..gbx, 20, 98, 7)
print("xmin:"..tostr(constraints.xmin), 12, 108, 7)
print("xmax:"..tostr(constraints.xmax), 12, 114, 7)
end
function meter(x0, y0, x1, y1, frac)
local c = 11
if frac < 0 then
frac = -frac
c = 8
end
local range = x1-x0
local midpoint = x0 + (range/2)
rectfill(x0, y0-1, x0, y1+1, 13)
rectfill(midpoint, y0-1, midpoint, y1 + 1, 13)
local width = range * frac
if (width ~= 0) rectfill(x0, y0, x0 + width, y1, c)
end
-->8
-- ship
ship = {
maxspd=4,
thrust=0.25,
drag=0.0625,
y=32,
}
mknew(ship)
function ship:reroll()
self.x=rnd(128)
self.dx=rnd(2*self.maxspd)-self.maxspd
end
function ship:draw()
if self.x < -7 then
spr(2, 0, self.y-7)
spr(2, 0, self.y+8)
elseif self.x > 127 then
spr(2, 120, self.y-7, 1, 1, true)
spr(2, 120, self.y+8, 1, 1, true)
else
spr(1,self.x,self.y)
end
--if (self.dx == 0) return
local bd, f = brake_dist(self.dx, self.thrust + self.drag)
gbx = self.x+bd
spr(3, gbx-2,self.y-2)
print(tostr(f), gbx-2, self.y - 8, 14)
end
function calc_velocity(v0, t, vmax, drag)
v0 = mid(v0 + t, vmax, -vmax)
return v0 - mid(drag, -drag, v0)
end
function ship:update()
local t = btn(0) and -1 or btn(1) and 1 or 0
t *= self.thrust
t = constraints:constrain(self, t)
-- t = constraints:constrain(self, t)
-- t = constraints:constrain(self, t)
local s = calc_velocity(self.dx, t, self.maxspd, self.drag)
self.x += s
self.dx = s
actual_t = t
end
-->8
-- constraints
constraints = {
ymin=20,
ymax=52,
color=10
}
function constraints:constrain(s, want)
self.color=10
if (not self.xmin) return want
-- bmx: brake max
local v1, bmx = calc_velocity(s.dx, want, s.maxspd, s.drag), s.thrust + s.drag
local bd, bf = brake_dist(v1, bmx)
local bx, txm = s.x + bd + v1, self.xmax
if bx < self.xmin then
-- predicted brake point left
-- of xmin; apply max reverse
-- thrust, treat xmin as our
-- max target, and handle
-- overbraking by coalescing
-- with past +xmax case
self.color = 9
want = s.thrust
txm = self.xmin
v1 = calc_velocity(s.dx, want, s.maxspd, s.drag)
bd, bf = brake_dist(v1, bmx)
bx = bd + s.x + v1
end
if (bx <= txm) return want
self.color = 8
local overage = bx - txm
want -= overage/max(bf,1)
if (want < -s.thrust) want = -s.thrust
return want
end
function brake_dist(v0, brake_max)
local tri_frames = abs(v0\brake_max)
local chunks = tri_frames * (tri_frames - 1) >> 1
local chunk_zone = chunks * brake_max
local overage = abs(v0) - tri_frames * brake_max
return (chunk_zone + overage * (tri_frames + 1)) * sgn(v0), (overage > 0) and tri_frames + 1 or tri_frames
end
function constraints:cycle()
if self.ctype=="bounds" then
self.ctype="point"
elseif self.ctype=="point" then
self.ctype="off"
else
self.ctype="bounds"
end
self:setup()
end
function constraints:setup()
if self.ctype=="point" then
self.xmin = 64
self.xmax = 64
elseif self.ctype=="bounds" then
self.xmin = 32
self.xmax = 96
else
self.xmin = nil
self.xmax = nil
end
end
function constraints:draw()
if (not self.xmin) return
rect(self.xmin, self.ymin, self.xmax, self.ymax, self.color)
end
-->8
-- fx
-- todo: spark ring buffer
__gfx__
000000008000000000080000a000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000006666000080000009090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000067777600800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000675555758008888009090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000006750007508000000a000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000067777500080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000005555000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

View File

@ -1 +0,0 @@
Trans rights.

View File

@ -75,7 +75,7 @@ function updategame()
edeaths = {} edeaths = {}
for ip, ps in ipairs(pships) do for ip, ps in ipairs(pships) do
for ie, eb in ipairs(ebullets) do for ie, eb in ipairs(ebullets) do
if collides(hurtbox(ps), hurtbox(eb)) then if collides(hurtobx(ps), hurtbox(eb)) then
if (eb:hitship(ps)) add(edeaths, ie) if (eb:hitship(ps)) add(edeaths, ie)
if ps:hitbullet(eb) then if ps:hitbullet(eb) then
add(pdeaths, ip) add(pdeaths, ip)

File diff suppressed because it is too large Load Diff

View File

@ -397,6 +397,23 @@ function dropshadow(str, x, y, col)
print(str, x, y, col) print(str, x, y, col)
end end
function grab_p1_butts()
if state ~= game then
local r = {0,0,0,0,0}
r[0] = 0
return r
end
local b = btn()
return {
[0]=b&0x1,
[1]=(b&0x2)>>1,
[2]=(b&0x4)>>2,
[3]=(b&0x8)>>3,
[4]=(b&0x10)>>4,
[5]=(b&0x20)>>5
}
end
-->8 -->8
--ship behavior --ship behavior
@ -431,19 +448,19 @@ end
function ship_m:move() function ship_m:move()
self:refresh_shield() self:refresh_shield()
self.power = min(self.max_power, self.power + self.generator) self.power = min(self.max_power, self.power + self.generator)
local dx, dy, shoot_spec, shoot_main = self:act() butt = self:grab_butts()
if (shoot_main) self:maybe_shoot(self.main_gun) if (butt[5] > 0) self:maybe_shoot(self.main_gun)
if (shoot_spec) self:maybe_shoot(self.special_gun) if (butt[4] > 0) self:maybe_shoot(self.special_gun)
if (dx ~= 0 or dy ~= 0) spark(self.sparks, self.x + 4*self.size, self.y + 4*self.size, dx*2.5, dy*2.5, self.sparkodds) if (butt[0]-butt[1] ~= 0 or butt[2]-butt[3] ~= 0) spark(self.sparks, self.x + 4*self.size, self.y + 4*self.size, butt, self.thrust, self.sparkodds)
self.xmomentum += dx self.xmomentum += (self.thrust * butt[1]) - (self.thrust * butt[0])
self.ymomentum += dy self.ymomentum += (self.thrust * butt[3]) - (self.thrust * butt[2])
self.xmomentum = mid(-self.maxspd, self.maxspd, self.xmomentum) self.xmomentum = mid(-self.maxspd, self.maxspd, self.xmomentum)
self.ymomentum = mid(-self.maxspd, self.maxspd, self.ymomentum) self.ymomentum = mid(-self.maxspd, self.maxspd, self.ymomentum)
self.x += self.xmomentum self.x += self.xmomentum
self.y += self.ymomentum self.y += self.ymomentum
if self == primary_ship then if self == primary_self then
self.x = mid(0, 112 - 8 * self.size, self.x) self.x = mid(0, 112 - 8 * self.size, self.x)
self.y = mid(0, 128 - 8 * self.size, self.y) self.y = mid(0, 128 - 8 * self.size, self.y)
end end
@ -852,18 +869,16 @@ player = ship_m.new{
thrust = 0.25, -- momentum added from button thrust = 0.25, -- momentum added from button
drag = 0.125, -- momentum lost per frame drag = 0.125, -- momentum lost per frame
slip = false, -- does not slide down screen slip = false, -- does not slide down screen
act = function(self) -- fetch buttons grab_butts = function(self) -- fetch buttons
local b,th = btn(),self.thrust local butts = grab_p1_butts()
local blr = b&0x3 if butts[0] == butts[1] then
if blr == 1 then
self.sprite=17
elseif blr==2 then
self.sprite=18
else
self.sprite = 1 self.sprite = 1
elseif butts[0] > 0 then
self.sprite = 17
else
self.sprite = 18
end end
--dx, dy, shoot_spec, shoot_main return butts
return (((b&0x2)>>1) - (b&0x1)) * th, (((b&0x8)>>3) - ((b&0x4)>>2)) * th, (b&0x10) > 0, (b&0x20) > 0
end end
} }
mknew(player, mknew(player,
@ -897,12 +912,18 @@ frownie = ship_m.new{
thrust = 0.12, -- momentum added from button thrust = 0.12, -- momentum added from button
drag = 0.07, -- momentum lost per frame drag = 0.07, -- momentum lost per frame
slip = true, slip = true,
act = function(self) grab_butts = function(discard_self)
local tstate,dx = (1 + flr(4*t() + 0.5)) % 6,0 -- buttons are effectively analog
if (tstate==1 or tstate==2) dx=-self.thrust -- and negative buttons work just fine!
if (tstate>=4) dx=self.thrust local butts = {}
return dx,0,false,false local tstate = (1 + flr(4*t() + 0.5)) % 6
end, 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) mknew(frownie)
@ -941,9 +962,10 @@ spewy = frownie.new{
generator=0.5, generator=0.5,
fire_off_x=4, fire_off_x=4,
fire_off_y = 7, fire_off_y = 7,
act=function(self) grab_butts=function()
local dx,dy,shoot_spec=frownie.act(self) local butts=frownie.grab_butts()
return dx, dy, shoot_spec, true butts[5]=1
return butts
end end
} }
mknew(spewy, function(ship) mknew(spewy, function(ship)
@ -978,11 +1000,12 @@ mknew(chasey, function(ship)
ship.main_gun=ship.main_gun or zap_gun.new{enemy=true} ship.main_gun=ship.main_gun or zap_gun.new{enemy=true}
end) end)
function chasey:act() function chasey:grab_butts()
local dx = 0 local butts = {[0]=0,0,0,0,0,0}
if (self.x < primary_ship.x) dx=self.thrust if (self.x < primary_ship.x) butts[1] = 1
if (self.x > primary_ship.x) dx=-self.thrust if (self.x > primary_ship.x) butts[0] = 1
return dx, 0, false, self.x - 16 < primary_ship.x and self.x + 16 > primary_ship.x if (self.x - 16 < primary_ship.x and self.x + 16 > primary_ship.x) butts[5] = 1
return butts
end end
xl_chasey=chasey.new{ xl_chasey=chasey.new{
@ -998,10 +1021,10 @@ xl_chasey=chasey.new{
shield = 5, shield = 5,
boss = true, boss = true,
slip = false, slip = false,
act = function(self) grab_butts = function(self)
local dx,dy,shoot_spec,shoot_main = chasey.act(self) local butts = chasey.grab_butts(self)
if (self.y < 4) dy=self.thrust if (self.y < 4) butts[3] = 1
return dx,dy,shoot_spec,shoot_main return butts
end, end,
draw = function(self) draw = function(self)
if(self.fx_pal) pal(self.fx_pal) if(self.fx_pal) pal(self.fx_pal)
@ -1285,7 +1308,7 @@ end
function spawn_goodie(goodie_name, x, y, sz) function spawn_goodie(goodie_name, x, y, sz)
if (not goodie_name or #goodie_name == 0) return if (not goodie_name or #goodie_name == 0) return
local sh = sz and sz/2 or 0 local sh = sz and sz/2 or 0
_ENV[goodie_name].new{}:spawn_at(x+sh,y+sh) goodies[goodie_name].new{}:spawn_at(x+sh,y+sh)
end end
function multi(times, interval, fnm, ...) function multi(times, interval, fnm, ...)
@ -1487,12 +1510,18 @@ like a player pushing buttons.
the player ship actually reads the player ship actually reads
buttons for this. buttons for this.
act -- returns new acceleration: grab_butts - ship thrust control
dx, dy, shoot_spec, shoot_main. based on btn() api. returns a
dx and dy are change in momentum table indexed from 0..5 with
in px/frame. this is controls 0 to not push this button and 1
only -- friction is handled in to push it. ships can use
ship:move (`drag` value). fractional or out-of-range
numbers to get varying amounts
of thrust, including using
negative numbers for thrust in
the opposite direction. 4 and 5
just check for nonzeroness to
attempt to fire.
ships hitting another ship take ships hitting another ship take
1 damage per frame of overlap. 1 damage per frame of overlap.
@ -1771,7 +1800,9 @@ function boom(x,y,boominess,is_boss)
local boombonus = min(0.05 * boominess, 1.25) local boombonus = min(0.05 * boominess, 1.25)
for _=1,boominess do for _=1,boominess do
local angle = rnd(1) local angle = rnd(1)
spark(sp,x+4,y+4,cos(angle), sin(angle),boombase+rnd(boombonus),1, true) local butts = {0, sin(angle), 0}
butts[0] = cos(angle)
spark(sp,x+4,y+4,butts,boombase+rnd(boombonus),1, true)
end end
return return
end end
@ -1791,16 +1822,17 @@ function spark_particle:draw()
pset(self.x,self.y,self.sprs[self.sidx]) pset(self.x,self.y,self.sprs[self.sidx])
end end
function spark(sprs, x, y, dx, dy, odds, fg) function spark(sprs, x, y, butts, thrust, odds, fg)
if (sprs==nil or flr(rnd(odds)) ~= 0) return if (sprs==nil or flr(rnd(odds)) ~= 0) return
thrust *= 2.5
local target = fg and intangibles_fg or intangibles_bg local target = fg and intangibles_fg or intangibles_bg
target:push_back(spark_particle.new{ target:push_back(spark_particle.new{
x = x + rnd(4) - 2, x = x + rnd(4) - 2,
y = y + rnd(4) - 2, y = y + rnd(4) - 2,
sprs = sprs, sprs = sprs,
sidx = 1, sidx = 1,
dx = dx + rnd(2) - 1, dx = (butts[0] - butts[1]) * thrust + rnd(2) - 1,
dy = dy + rnd(2) - 1, dy = (butts[2] - butts[3]) * thrust + rnd(2) - 1,
}) })
end end
-->8 -->8

File diff suppressed because it is too large Load Diff