zenno/racelib: allow accel skills to be delayed
This commit is contained in:
@@ -25,7 +25,7 @@ export interface Travel {
|
|||||||
* @param start Motion at the beginning of the segment
|
* @param start Motion at the beginning of the segment
|
||||||
* @param targetSpeed Target speed to accelerate to
|
* @param targetSpeed Target speed to accelerate to
|
||||||
* @param totalAccel Total (positive) acceleration including skill bonuses
|
* @param totalAccel Total (positive) acceleration including skill bonuses
|
||||||
* @param maxDur Max duration of the acceleration, or infinite if not given
|
* @param maxDur Max position of the acceleration, or infinite if not given
|
||||||
* @param maxDist Max distance of the acceleration, or infinite if not given
|
* @param maxDist Max distance of the acceleration, or infinite if not given
|
||||||
* @param decel Negative acceleration value for cases where target speed is below start speed
|
* @param decel Negative acceleration value for cases where target speed is below start speed
|
||||||
* @returns Travel segment after reaching the first of the given limits
|
* @returns Travel segment after reaching the first of the given limits
|
||||||
@@ -40,13 +40,13 @@ export function travelSegment(
|
|||||||
): Travel {
|
): Travel {
|
||||||
const a = start.v < targetSpeed ? totalAccel : (decel ?? -1);
|
const a = start.v < targetSpeed ? totalAccel : (decel ?? -1);
|
||||||
const dvt = (targetSpeed - start.v) / a;
|
const dvt = (targetSpeed - start.v) / a;
|
||||||
const dxt = maxDist != null ? (-start.v + Math.sqrt(start.v * start.v + 4 * a * maxDist)) / (2 * a) : dvt;
|
const dxt = maxDist != null ? (-start.v + Math.sqrt(start.v * start.v + 4 * a * (maxDist - start.x))) / (2 * a) : dvt;
|
||||||
const time = maxDur != null ? Math.min(dvt, dxt, maxDur) : Math.min(dvt, dxt);
|
const time = maxDur != null ? Math.min(dvt, dxt, maxDur) : Math.min(dvt, dxt);
|
||||||
// To address numerical imprecision, if accel time comes from velocity or distance,
|
// To address numerical imprecision, if accel time comes from velocity or distance,
|
||||||
// set the reached values directly.
|
// set the reached values directly.
|
||||||
const v = time === dvt ? targetSpeed : start.v + time * a;
|
const v = time === dvt ? targetSpeed : start.v + time * a;
|
||||||
const dist = maxDist != null && time === dxt ? maxDist : (start.v + 0.5 * a * time) * time;
|
const dist = maxDist != null && time === dxt ? maxDist : start.x + (start.v + 0.5 * a * time) * time;
|
||||||
const end = { t: start.t + time, x: start.x + dist, v };
|
const end = { t: start.t + time, x: dist, v };
|
||||||
return { start, end, a };
|
return { start, end, a };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +54,10 @@ export function travelSegment(
|
|||||||
* Acceleration bonus from skills.
|
* Acceleration bonus from skills.
|
||||||
*/
|
*/
|
||||||
export interface Skill {
|
export interface Skill {
|
||||||
|
/**
|
||||||
|
* Forward position along the course at which the skill activates.
|
||||||
|
*/
|
||||||
|
x?: number;
|
||||||
/**
|
/**
|
||||||
* Acceleration modifier in m/s².
|
* Acceleration modifier in m/s².
|
||||||
*/
|
*/
|
||||||
@@ -74,16 +78,18 @@ export interface Skill {
|
|||||||
*/
|
*/
|
||||||
export function up(start: Instant, targetSpeed: number, baseAccel: number, skills: Skill[]) {
|
export function up(start: Instant, targetSpeed: number, baseAccel: number, skills: Skill[]) {
|
||||||
const segments: Travel[] = [];
|
const segments: Travel[] = [];
|
||||||
const sk = skills.map((s) => ({ ...s })).filter((s) => s.dur > 0);
|
const sk = skills.map((s) => ({ x: 0, ...s })).filter((s) => s.dur > 0);
|
||||||
|
const xs = sk.map((s) => s.x).filter((x) => x > 0).sort((a, b) => a - b);
|
||||||
while (start.v < targetSpeed) {
|
while (start.v < targetSpeed) {
|
||||||
const active = sk.filter((s) => s.dur > 0);
|
const active = sk.filter((s) => s.dur > 0 && s.x <= start.x);
|
||||||
if (active.length === 0) {
|
const dx = xs.find((x) => x > start.x);
|
||||||
|
if (active.length === 0 && dx == null) {
|
||||||
segments.push(travelSegment(start, targetSpeed, baseAccel));
|
segments.push(travelSegment(start, targetSpeed, baseAccel));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const boost = active.reduce((a, s) => a + s.accel, 0);
|
const boost = active.reduce((a, s) => a + s.accel, 0);
|
||||||
const time = Math.min(...active.map((s) => s.dur));
|
const time = Math.min(...active.map((s) => s.dur));
|
||||||
const seg = travelSegment(start, targetSpeed, baseAccel + boost, time);
|
const seg = travelSegment(start, targetSpeed, baseAccel + boost, time, dx);
|
||||||
segments.push(seg);
|
segments.push(seg);
|
||||||
start = seg.end;
|
start = seg.end;
|
||||||
for (const s of active) {
|
for (const s of active) {
|
||||||
|
|||||||
Reference in New Issue
Block a user