Skip to content

Commit

Permalink
Merge pull request #8 from kionell/master
Browse files Browse the repository at this point in the history
Another slider patch
  • Loading branch information
Itsyuka authored Feb 22, 2021
2 parents 8f29c5c + 43feb93 commit b312825
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 66 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "osu-bpdpc",
"version": "0.2.4",
"version": "0.3.0",
"description": "Osu beatmap parser, difficulty and performance calculator",
"main": "index.js",
"engines": {
Expand Down
17 changes: 13 additions & 4 deletions src/Beatmap.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import HitSound from "./Enum/HitSound";
import Colour from "./Colour";

export default class Beatmap {
public Version: number;

public General: {
AudioFilename: string;
AudioLeadin: number;
Expand Down Expand Up @@ -65,14 +67,21 @@ export default class Beatmap {
public static fromOsu(data: string): Beatmap;

/**
* Takes a JSON string and returns a new Beatmap instance
* Returns a string for an .osu file
*/
public static fromJSON(data: string): Beatmap;
public toOsu(): string;

/**
* Returns a string for an .osu file
* Takes a JSON string and returns a new Beatmap instance
*/
public toOsu(): string;
public static fromJSON(data: string): Beatmap;

public get countNormal(): number;
public get countSlider(): number;
public get countSpinner(): number;
public get countObjects(): number;
public get maxCombo(): number;
public get length(): number;
}

export interface Break {
Expand Down
91 changes: 74 additions & 17 deletions src/Beatmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,24 +282,29 @@ class Beatmap {
hitObject.pathPoints.push(point);
});

let sliderPath = new SliderPath(
let path = new SliderPath(
hitObject.pathPoints, hitObject.pixelLength
);

let endPoint = sliderPath.positionAt(1);
let endPoint = path.positionAt(path.progressAt(hitObject, 1));

if (endPoint && endPoint.x && endPoint.y) {
hitObject.path = path;

if (Number.isFinite(endPoint.x) && Number.isFinite(endPoint.y)) {
hitObject.endPos = hitObject.pos.add(endPoint);
} else {
// If endPosition could not be calculated, approximate it by setting it to the last point
hitObject.endPos = hitObject.curvePoints[hitObject.curvePoints.length - 1];
// If endPosition could not be calculated,
// approximate it by setting it to the last point
hitObject.endPos =
hitObject.curvePoints[hitObject.curvePoints.length - 1];
}

if (edgeHitSounds) {
hitObject.edgeHitSounds = edgeHitSounds
.split("|")
.map(v => parseInt(v, 10));
}

if (edgeAdditions) {
hitObject.edgeAdditions = edgeAdditions
.split("|")
Expand Down Expand Up @@ -363,24 +368,67 @@ class Beatmap {
break;
}
}
let parentPoint = beatmap.TimingPoints.find(tp => !tp.inherited);

for (const tp of beatmap.TimingPoints) {
if (!tp.inherited) parentPoint = tp;
let tpIndex = -1, nextTime = Number.NEGATIVE_INFINITY;
let parentPoint, timingPoint, pixelsPerBeat = 0;

for (const hitObject of beatmap.HitObjects) {
if (!(hitObject.hitType & HitType.Slider)) {
continue;
}

while (hitObject.startTime >= nextTime) {
++tpIndex;

if (beatmap.TimingPoints.length > tpIndex + 1) {
nextTime = beatmap.TimingPoints[tpIndex + 1].time;
}
else {
nextTime = Number.POSITIVE_INFINITY;
}

timingPoint = beatmap.TimingPoints[tpIndex];

if (timingPoint.inherited) {
parentPoint = timingPoint;
}

let bpm = Math.round(60000 / timingPoint.beatLength);

let bpm = Math.round(60000 / tp.beatLength);
if (bpm > 0) {
beatmap.General.MinBPM =
Math.min(beatmap.General.MinBPM, bpm) || bpm;
beatmap.General.MaxBPM =
Math.max(beatmap.General.MaxBPM, bpm) || bpm;
}

if (bpm > 0) {
beatmap.General.MinBPM = Math.min(beatmap.General.MinBPM, bpm) || bpm;
beatmap.General.MaxBPM = Math.max(beatmap.General.MaxBPM, bpm) || bpm;
let velocityMultiplier = 1;

if (!timingPoint.inherited && timingPoint.beatLength < 0) {
velocityMultiplier = -100 / timingPoint.beatLength;
}

pixelsPerBeat = beatmap.Difficulty.SliderMultiplier * 100;

if (beatmap.Version >= 8) {
pixelsPerBeat *= velocityMultiplier;
}
}

let beats = (hitObject.path.distance * hitObject.repeat) / pixelsPerBeat;

let ticks = Math.ceil((beats - 0.01) / hitObject.repeat
* beatmap.Difficulty.SliderTickRate) - 1;

for (let hitObject of beatmap.HitObjects.filter(
ho => ho.startTime >= tp.time
)) {
if (hitObject.finalize) hitObject.finalize(tp, parentPoint, beatmap);
}
ticks *= hitObject.repeat;
ticks += hitObject.repeat + 1;

hitObject.duration = beats * parentPoint.beatLength;
hitObject.endTime = hitObject.startTime + hitObject.duration;

hitObject.combo = Math.max(0, ticks);
}

return beatmap;
}

Expand Down Expand Up @@ -526,6 +574,15 @@ class Beatmap {
get maxCombo() {
return this.HitObjects.reduce((a, c) => a + c.combo, 0);
}

get length() {
let startTime = this.HitObjects[0].startTime;
let endTime = this.HitObjects.reduce((time, ho) => {
return Math.max(time, ho.endTime || ho.startTime);
}, 0);

return endTime - startTime;
}
}

module.exports = Beatmap;
27 changes: 1 addition & 26 deletions src/Rulesets/Osu/Objects/Slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,14 @@ class Slider extends HitObject {
this.curveType = hitObject.curveType;
this.curvePoints = hitObject.curvePoints;
this.repeat = hitObject.repeat;
this.path = hitObject.path;
this.pixelLength = hitObject.pixelLength;
if (hitObject.edgeHitSounds) {
this.edgeHitSounds = hitObject.edgeHitSounds;
this.edgeAdditions = hitObject.edgeAdditions;
}
}

finalize(timingPoint, parentTimingPoint, beatmap) {
let velocityMultiplier = 1;
let difficulty = beatmap.Difficulty;

if (!timingPoint.inherited && timingPoint.beatLength < 0) {
velocityMultiplier = -100 / timingPoint.beatLength;
}

let pixelsPerBeat = difficulty.SliderMultiplier * 100;

if (beatmap.Version >= 8) {
pixelsPerBeat *= velocityMultiplier;
}

let beats = (this.pixelLength * this.repeat) / pixelsPerBeat;
let parentBeatLength = parentTimingPoint ? parentTimingPoint.beatLength : 1;
let duration = Math.ceil(beats * parentBeatLength);

this.endTime = this.startTime + duration;
this.combo =
Math.ceil((beats - 0.1) / this.repeat * difficulty.SliderTickRate) - 1;

this.combo *= this.repeat;
this.combo += this.repeat + 1;
}

toOsu() {
let arrayBuilder = [];
arrayBuilder.push(
Expand Down
2 changes: 1 addition & 1 deletion src/Utils/PathApproximator.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class PathApproximator
static approximateCatmull(controlPoints)
{
let result = [];
let controlPointsLength = controlPoints.Length;
let controlPointsLength = controlPoints.length;

for (let i = 0; i < controlPointsLength - 1; i++) {
let v1 = i > 0 ? controlPoints[i - 1] : controlPoints[i];
Expand Down
21 changes: 17 additions & 4 deletions src/Utils/SliderPath.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ class SliderPath
path.push(this._interpolateVertices(i, d1));
}

/**
* Computes the progress along the curve relative to how much of the hit object has been completed.
* @param obj the curve.
* @param progress where 0 is the start time of the hit object and 1 is the end time of the hit object.
*/
progressAt(obj, progress)
{
let p = progress * obj.repeat % 1;

return Math.trunc(progress * obj.repeat) % 2 ? 1 - p : p;
}

/**
* Computes the position on the slider at a given progress that ranges from 0 (beginning of the path)
* to 1 (end of the path).
Expand Down Expand Up @@ -94,14 +106,14 @@ class SliderPath

_calculatePath()
{
this.calculatedPath = [];

let controlPointsLength = this.controlPoints.length;

if (controlPointsLength === 0) {
return;
}

this.calculatedPath = [];

let vertices = [];

for (let i = 0; i < controlPointsLength; i++) {
Expand All @@ -120,8 +132,9 @@ class SliderPath
let segmentType = this.controlPoints[start].type || 'L';

for (let t of this._calculateSubPath(segmentVertices, segmentType)) {
if (this.calculatedPath.length === 0
|| this.calculatedPath[this.calculatedPath.length - 1] != t) {
let last = this.calculatedPath[this.calculatedPath.length - 1];

if (this.calculatedPath.length === 0 || !last.equals(t)) {
this.calculatedPath.push(t);
}
}
Expand Down
40 changes: 27 additions & 13 deletions src/Utils/Vector2.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,74 @@ export default class Vector2 {
public constructor(x: number, y: number);

/**
* Adds a vector to current and returns a new instance
* Adds a vector to the current and returns a new instance.
* @param vec vector to add.
*/
public add(vec: Vector2): Vector2;

/**
* Adds a vector to current and returns a new instance with single precision
* Adds a vector to the current and returns a new instance with single precision.
* @param vec vector to add.
*/
public fadd(vec: Vector2): Vector2;

/**
* Subtracts a vector to current and returns a new instance
* Subtracts a vector from the current and returns a new instance.
* @param vec vector to substract.
*/
public subtract(vec: Vector2): Vector2;

/**
* Subtracts a vector to current and returns a new instance with single precision
* Subtracts a vector from the current and returns a new instance with single precision.
* @param vec vector to substract.
*/
public fsubtract(vec: Vector2): Vector2;

/**
* Scales the vector and returns a new instance
* Scales the current vector and returns a new instance.
* @param multiplier vector multiplier.
*/
public scale(multiplier: number): Vector2;

/**
* Returns a new instance with a dot product of a vector.
* Divides the current vector and returns a new instance.
* @param multiplier vector divisor.
*/
public dot(vec: Vector2): Vector2;
public divide(divisor: number): Vector2;

/**
* Divides the vector and returns a new instance.
* Returns a new instance with a dot product of two vectors.
* @param vec second vector.
*/
public divide(divisor: number): Vector2;
public dot(vec: Vector2): Vector2;

/**
* Returns the length of the 2 points in the vector
* Returns a length of two points in a vector.
*/
public length(): number;

/**
* Returns the single precision length of the 2 points in the vector
* Returns a single precision length of two points in a vector.
*/
public flength(): number;

/**
* Returns the distance between 2 vectors
* Returns a distance between two vectors.
* @param vec second vector.
*/
public distance(vec: Vector2): number;

/**
* Returns normaliled vector
* Returns a normalized vector.
*/
public normalize(): Vector2;

/**
* Checks if two vectors are equal.
* @param vec second vector.
*/
public equals(vec: Vector2): boolean;

/**
* Clones the current vector and returns it
* Kinda useless but ¯\_(ツ)_/¯
Expand Down
4 changes: 4 additions & 0 deletions src/Utils/Vector2.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ class Vector2 {
this.y = y;
}

equals(vec) {
return this.x === vec.x && this.y === vec.y;
}

add(vec) {
return new Vector2(this.x + vec.x, this.y + vec.y);
}
Expand Down

0 comments on commit b312825

Please sign in to comment.