Compare commits

...

8 Commits

2 changed files with 87 additions and 30 deletions

View File

@ -81,9 +81,10 @@ function _draw()
print("dx: ".. the_ship.dx, 20, 86, 7) print("dx: ".. the_ship.dx, 20, 86, 7)
meter(80, 86, 128, 90, the_ship.dx/the_ship.maxspd/2) meter(80, 86, 128, 90, the_ship.dx/the_ship.maxspd/2)
print("x: "..the_ship.x, 24, 92, 7) print("x: "..the_ship.x, 24, 92, 7)
print("bx: "..gbx, 20, 98, 7)
print("xmin:"..tostr(constraints.xmin), 12, 102, 7) print("xmin:"..tostr(constraints.xmin), 12, 108, 7)
print("xmax:"..tostr(constraints.xmax), 12, 108, 7) print("xmax:"..tostr(constraints.xmax), 12, 114, 7)
end end
function meter(x0, y0, x1, y1, frac) function meter(x0, y0, x1, y1, frac)
@ -127,26 +128,24 @@ function ship:draw()
spr(1,self.x,self.y) spr(1,self.x,self.y)
end end
if (self.dx == 0) return --if (self.dx == 0) return
local bd, f = brake_dist(self.dx, self.thrust + self.drag) local bd, f = brake_dist(self.dx, self.thrust + self.drag)
local bdx = self.x+bd-2 gbx = self.x+bd
spr(3, bdx,self.y-2) spr(3, gbx-2,self.y-2)
print(tostr(f), bdx, self.y - 8, 14) print(tostr(f), gbx-2, self.y - 8, 14)
end end
function calc_velocity(v0, t, vmax, drag) function calc_velocity(v0, t, vmax, drag)
local v1 = v0 + t v0 = mid(v0 + t, vmax, -vmax)
local sg = sgn(v1) return v0 - mid(drag, -drag, v0)
v1 -= sg*drag
if (sgn(v1) != sg) return 0
if (abs(v1) > vmax) return sg*vmax
return v1
end end
function ship:update() function ship:update()
local t = btn(0) and -1 or btn(1) and 1 or 0 local t = btn(0) and -1 or btn(1) and 1 or 0
t *= self.thrust t *= self.thrust
t = constraints:constrain(self, t) 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) local s = calc_velocity(self.dx, t, self.maxspd, self.drag)
self.x += s self.x += s
@ -165,10 +164,31 @@ constraints = {
function constraints:constrain(s, want) function constraints:constrain(s, want)
self.color=10 self.color=10
if (not self.xmin) return want
local v1 = calc_velocity(s.dx, want, s.maxspd, s.drag) -- bmx: brake max
local bd, bf = brake_dist(v1, s.thrust + s.drag) 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 return want
end end

View File

@ -420,6 +420,13 @@ ship_m = {
xmomentum = 0, xmomentum = 0,
ymomentum = 0, ymomentum = 0,
-- xmin, xmax, ymin, ymax:
-- movement constraints
-- enforced by `constrain`.
xmin = 0, xmax = 104,
-- ymin, ymax default to nil
-- pship needs more constraint
} }
mknew(ship_m) mknew(ship_m)
@ -428,31 +435,60 @@ function ship_m:die()
if (self.hp <= 0) boom(self.x+self.size*4, self.y+self.size*4,12*self.size, self.boss) if (self.hp <= 0) boom(self.x+self.size*4, self.y+self.size*4,12*self.size, self.boss)
end end
function ship_m:calc_velocity(v0, t)
v0 = mid(v0 + t, self.maxspd, -self.maxspd)
return v0 - mid(self.drag, -self.drag, v0)
end
function ship_m:brake_dist(v0)
local brake_max = self.thrust + self.drag
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 ship_m:constrain(p, dp, pmin, pmax, want)
if (not pmin) return want
local v1, bd, bf, bp
function calc_targets()
-- velocity after move
v1 = self:calc_velocity(dp, want)
-- brake distance and frames
bd, bf = self:brake_dist(v1)
-- brake point
bp = p + bd + v1
end
calc_targets()
if bp < pmin then
-- undershoot. max thrust,
-- then treat as overshoot
-- targeting minimum bound
want, pmax = self.thrust, pmin
calc_targets()
end
if (bp <= pmax) return want
-- spread overshoot across frames
want -= (bp - pmax)/max(bf,1)
return max(want, -self.thrust)
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() local dx, dy, shoot_spec, shoot_main = self:act()
dx = self:constrain(self.x, self.xmomentum, self.xmin, self.xmax, dx)
dy = self:constrain(self.y, self.ymomentum, self.ymin, self.ymax, dy)
if (shoot_main) self:maybe_shoot(self.main_gun) if (shoot_main) self:maybe_shoot(self.main_gun)
if (shoot_spec) self:maybe_shoot(self.special_gun) if (shoot_spec) 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 (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)
self.xmomentum += dx self.xmomentum = self:calc_velocity(self.xmomentum, dx)
self.ymomentum += dy self.ymomentum = self:calc_velocity(self.ymomentum, dy)
self.xmomentum = mid(-self.maxspd, self.maxspd, self.xmomentum)
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
self.x = mid(0, 112 - 8 * self.size, self.x)
self.y = mid(0, 128 - 8 * self.size, self.y)
end
--friction
local d = self.drag
self.xmomentum -= mid(d, -d, self.xmomentum)
self.ymomentum -= mid(d, -d, self.ymomentum)
-- "scrolling" behavior -- "scrolling" behavior
if self.slip then if self.slip then
self.y += scrollrate self.y += scrollrate
@ -850,6 +886,7 @@ player = ship_m.new{
ymomentum = 0, ymomentum = 0,
maxspd = 2.5, -- momentum cap maxspd = 2.5, -- momentum cap
thrust = 0.25, -- momentum added from button thrust = 0.25, -- momentum added from button
ymin = 0, ymax = 120, -- stay on screen
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 act = function(self) -- fetch buttons