algorithm to make the charter faster

This commit is contained in:
Yoshman29
2023-04-19 13:50:45 +02:00
parent d45dbc9d7a
commit 4b4c2f10e9
3 changed files with 88 additions and 10 deletions
@@ -0,0 +1,49 @@
package funkin.backend.utils;
/**
* All types of utils only usable in a sorted array.
*/
class SortedArrayUtil {
/**
* Gets the index of a possible new element of an Array of T using an efficient algorithm.
* @param array Array of T to check in
* @param getVal Function that returns the position value of T
* @return Index
*/
public static inline function binarySearch<T>(array:Array<T>, val:Float, getVal:T->Float):Int {
if (array.length <= 0) return 0; // if the array is empty, it should be equal to zero (the beginning)
if (getVal(array[0]) > val) return 0; // in case its the minimum
if (getVal(array[array.length-1]) < val) return array.length; // in case its the maximum
// binary search
var iMin:Int = 0;
var iMax:Int = array.length-1;
var i:Int = 0;
var mid:Float;
while(iMin <= iMax) {
i = Math.floor((iMin + iMax) / 2);
mid = getVal(array[i]);
if (mid < val)
iMin = i+1
else if (mid > val)
iMax = i-1;
else {
iMin = i;
break;
}
}
return iMin;
}
/**
* Adds to a sorted array, using binary search.
* @param array Array to add to
* @param val Value to add
* @param getVal Function that returns the value that needs to be sorted
*/
public static inline function addSorted<T>(array:Array<T>, val:T, getVal:T->Float) {
if (val != null)
array.insert(binarySearch(array, getVal(val), getVal), val);
}
}
+17 -2
View File
@@ -399,6 +399,7 @@ class Charter extends UIState {
vocals = FlxG.sound.load(Paths.voices(__song, __diff));
vocals.group = FlxG.sound.defaultMusicGroup;
trace("generating notes...");
for(strID=>strL in PlayState.SONG.strumLines) {
for(note in strL.notes) {
var n = new CharterNote();
@@ -409,6 +410,12 @@ class Charter extends UIState {
strumLines.add(new CharterStrumline(strL));
}
trace("sorting notes...");
notesGroup.sort(function(i, n1, n2) {
if (n1.step == n2.step)
return FlxSort.byValues(FlxSort.ASCENDING, n1.id, n2.id);
return FlxSort.byValues(FlxSort.ASCENDING, n1.step, n2.step);
});
refreshBPMSensitive();
}
@@ -522,6 +529,8 @@ class Charter extends UIState {
deletes.push(s);
} else {
s.updatePos(newStep, newID, s.susLength, s.type);
notesGroup.remove(s);
notesGroup.add(s);
drags.push({
note: s,
@@ -785,8 +794,11 @@ class Charter extends UIState {
for(n in changes)
n.note.updatePos(n.note.step, n.note.id, n.before, n.note.type);
case CNoteDrag(notes, deletes):
for(n in notes)
for(n in notes) {
n.note.updatePos(n.oldStep, n.oldID, n.note.susLength, n.note.type);
notesGroup.remove(n.note);
notesGroup.add(n.note);
}
for(d in deletes) {
notesGroup.add(d);
d.revive();
@@ -832,8 +844,11 @@ class Charter extends UIState {
for(n in changes)
n.note.updatePos(n.note.step, n.note.id, n.after, n.note.type);
case CNoteDrag(notes, deletes):
for(n in notes)
for(n in notes) {
n.note.updatePos(n.newStep, n.newID, n.note.susLength, n.note.type);
notesGroup.remove(n.note);
notesGroup.add(n.note);
}
deleteNotes(deletes, false);
selection = [for(n in notes) n.note];
}
@@ -9,7 +9,6 @@ class CharterNoteGroup extends FlxTypedGroup<CharterNote> {
var __currentlyLooping:Bool = false;
public override function forEach(noteFunc:CharterNote->Void, recursive:Bool = false) {
i = 0;
__loopSprite = null;
max = FlxG.height / 70 / camera.zoom;
@@ -21,19 +20,34 @@ class CharterNoteGroup extends FlxTypedGroup<CharterNote> {
if (FlxG.state is Charter && !FlxG.sound.music.playing)
curStep = cast(FlxG.state, Charter).conductorFollowerSpr.y / 40;
while(i < length) {
var begin = SortedArrayUtil.binarySearch(members, curStep - max, getVarForEach);
var end = SortedArrayUtil.binarySearch(members, curStep + max, getVarForEach);
for(i in begin...end) {
__loopSprite = members[i];
if (__loopSprite == null || !__loopSprite.exists) {
i++;
continue;
}
if (Math.abs(__loopSprite.step - curStep) - __loopSprite.susLength < max)
if (!cast(FlxG.state, Charter).selection.contains(__loopSprite))
noteFunc(__loopSprite);
i++;
}
for(c in cast(FlxG.state, Charter).selection)
noteFunc(c);
__currentlyLooping = oldCur;
}
public override function add(v:CharterNote):CharterNote {
SortedArrayUtil.addSorted(members, v, getVar);
return v;
}
public override function remove(v:CharterNote, force:Bool = true):CharterNote
return super.remove(v, true);
private static function getVar(n:CharterNote)
return n.step;
private static function getVarForEach(n:CharterNote)
return n.step + n.susLength;
public override function draw() {
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
@:privateAccess if (cameras != null) FlxCamera._defaultCameras = cameras;