diff --git a/vacuum_gambit.p8 b/vacuum_gambit.p8 index 6d75805..ddb1cd8 100644 --- a/vacuum_gambit.p8 +++ b/vacuum_gambit.p8 @@ -420,6 +420,13 @@ ship_m = { xmomentum = 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) @@ -428,31 +435,59 @@ function ship_m:die() if (self.hp <= 0) boom(self.x+self.size*4, self.y+self.size*4,12*self.size, self.boss) 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 + 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)/(bf+1) + return max(want, -self.thrust) +end + function ship_m:move() self:refresh_shield() self.power = min(self.max_power, self.power + self.generator) 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_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) - self.xmomentum += dx - self.ymomentum += dy - self.xmomentum = mid(-self.maxspd, self.maxspd, self.xmomentum) - self.ymomentum = mid(-self.maxspd, self.maxspd, self.ymomentum) - + self.xmomentum = self:calc_velocity(self.xmomentum, dx) + self.ymomentum = self:calc_velocity(self.ymomentum, dy) + self.x += self.xmomentum 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 if self.slip then self.y += scrollrate