mirror of
https://gitlab.com/skysthelimit.dev/selenite.git
synced 2025-06-21 04:46:45 -05:00
86 lines
3.5 KiB
JavaScript
86 lines
3.5 KiB
JavaScript
var CURVE_POINTS_SEPERATION = 5;
|
|
|
|
define(["curves/Curve"], function (Curve) {
|
|
// Adapted from EqualDistanceMultiCurve.java from github://itdelatrisu/opsu
|
|
function EqualDistanceMultiCurve(hit) {
|
|
Curve.call(this, hit);
|
|
this.ncurve = 0;
|
|
this.startAngle = 0;
|
|
this.endAngle = 0;
|
|
}
|
|
EqualDistanceMultiCurve.prototype.init = function init(curves) {
|
|
this.ncurve = Math.floor(this.hitObject.pixelLength / CURVE_POINTS_SEPERATION) + 1;
|
|
// number of segments, which have approximately same length
|
|
this.curve = [];
|
|
|
|
|
|
var distanceAt = 0; // accumulated length of new curve
|
|
var curPoint = 0;
|
|
var curCurveIndex = 0;
|
|
var curCurve = curves[0]; // current pointer of raw curve array
|
|
var lastCurve = curCurve.curve[0];
|
|
var lastDistanceAt = 0;
|
|
|
|
var pixelLength = this.hitObject.pixelLength; // This is the expected value of length
|
|
if (pixelLength < 0) console.error("osu curve: negative slider length");
|
|
for (var i = 0; i <= this.ncurve; i++) {
|
|
var prefDistance = i * pixelLength / this.ncurve; // expected current accumulated length
|
|
while (distanceAt < prefDistance) {
|
|
lastDistanceAt = distanceAt;
|
|
lastCurve = curCurve.curve[curPoint];
|
|
curPoint++;
|
|
|
|
if (curPoint >= curCurve.ncurve) {
|
|
if (curCurveIndex < curves.length - 1) {
|
|
curCurveIndex++;
|
|
curCurve = curves[curCurveIndex];
|
|
curPoint = 0;
|
|
} else {
|
|
curPoint = curCurve.ncurve - 1;
|
|
if (lastDistanceAt === distanceAt) {
|
|
if (distanceAt < pixelLength * 0.97) {
|
|
console.warn("[curve] L/B shorter than given", distanceAt / pixelLength);
|
|
}
|
|
// out of points even though the preferred distance hasn't been reached
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
distanceAt += curCurve.curveDistance[curPoint];
|
|
}
|
|
var thisCurve = curCurve.curve[curPoint];
|
|
|
|
// linear interpolate between lastCurve & thisCurve
|
|
// this can always be done when lastCurve != thisCurve, since lastCurve is always available
|
|
// lastDistanceAt <= prefDistance <= distanceAt
|
|
if (lastCurve == thisCurve) {
|
|
this.curve[i] = thisCurve;
|
|
} else {
|
|
let t = (prefDistance - lastDistanceAt) / (distanceAt - lastDistanceAt);
|
|
this.curve[i] = {
|
|
x: Curve.lerp(lastCurve.x, thisCurve.x, t),
|
|
y: Curve.lerp(lastCurve.y, thisCurve.y, t),
|
|
};
|
|
}
|
|
this.curve[i].t = i / this.ncurve;
|
|
}
|
|
}
|
|
EqualDistanceMultiCurve.prototype.pointAt = function pointAt(t) {
|
|
|
|
var indexF = t * this.ncurve;
|
|
var index = Math.floor(indexF);
|
|
if (index >= this.ncurve) { // overflowing or at exact endpoint
|
|
return this.curve[this.ncurve];
|
|
} else {
|
|
// linear interpolation between two points
|
|
let poi = this.curve[index];
|
|
let poi2 = this.curve[index + 1];
|
|
let t = indexF - index;
|
|
return {
|
|
x: Curve.lerp(poi.x, poi2.x, t),
|
|
y: Curve.lerp(poi.y, poi2.y, t)
|
|
};
|
|
}
|
|
}
|
|
return EqualDistanceMultiCurve;
|
|
}); |