From 1d018c9289dbdfd29a3a1b9d2c1a55d6af1fb32e Mon Sep 17 00:00:00 2001 From: Yoshman29 <81191621+YoshiCrafter29@users.noreply.github.com> Date: Thu, 26 Jan 2023 17:40:46 +0100 Subject: [PATCH] time signatures --- buildnumber.txt | 2 +- source/funkin/game/PlayState.hx | 4 +- source/funkin/game/Stage.hx | 2 + source/funkin/interfaces/IBeatReceiver.hx | 1 + source/funkin/system/Conductor.hx | 42 ++++++++++++++++--- source/funkin/system/FunkinSprite.hx | 1 + source/funkin/system/MusicBeatGroup.hx | 3 ++ source/funkin/system/MusicBeatState.hx | 18 ++++++++ source/funkin/system/MusicBeatSubstate.hx | 42 +++++++++++++------ source/funkin/system/Song.hx | 2 + .../funkin/system/framerate/ConductorInfo.hx | 2 + 11 files changed, 99 insertions(+), 20 deletions(-) diff --git a/buildnumber.txt b/buildnumber.txt index d64b2abb..8e20b01e 100644 --- a/buildnumber.txt +++ b/buildnumber.txt @@ -1 +1 @@ -2199 \ No newline at end of file +2202 \ No newline at end of file diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index 97d42583..077d56ef 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -933,6 +933,8 @@ class PlayState extends MusicBeatState if (songData.maxHealth != null && songData.maxHealth > 0) maxHealth = songData.maxHealth; + camZoomingInterval = cast songData.beatsPerMesure.getDefault(4); + Conductor.changeBPM(songData.bpm); curSong = songData.song.toLowerCase(); @@ -1084,7 +1086,7 @@ class PlayState extends MusicBeatState } public function get_curSection() { - return PlayState.SONG.notes[Std.int(curStep / 16)]; + return PlayState.SONG.notes[curMeasure]; } diff --git a/source/funkin/game/Stage.hx b/source/funkin/game/Stage.hx index e6a34f6d..e16b692f 100644 --- a/source/funkin/game/Stage.hx +++ b/source/funkin/game/Stage.hx @@ -144,4 +144,6 @@ class Stage extends FlxBasic implements IBeatReceiver { public function beatHit(curBeat:Int) {} public function stepHit(curStep:Int) {} + + public function measureHit(curMeasure:Int) {} } \ No newline at end of file diff --git a/source/funkin/interfaces/IBeatReceiver.hx b/source/funkin/interfaces/IBeatReceiver.hx index ca7dfa35..743e41f4 100644 --- a/source/funkin/interfaces/IBeatReceiver.hx +++ b/source/funkin/interfaces/IBeatReceiver.hx @@ -1,6 +1,7 @@ package funkin.interfaces; interface IBeatReceiver { + public function measureHit(curMeasure:Int):Void; public function beatHit(curBeat:Int):Void; public function stepHit(curStep:Int):Void; } \ No newline at end of file diff --git a/source/funkin/system/Conductor.hx b/source/funkin/system/Conductor.hx index 8a514d18..4e021514 100644 --- a/source/funkin/system/Conductor.hx +++ b/source/funkin/system/Conductor.hx @@ -44,6 +44,16 @@ class Conductor */ public static var stepCrochet:Float = crochet / 4; // steps in milliseconds + /** + * Number of beats per mesure (top number in time signature). Defaults to 4. + */ + public static var beatsPerMesure:Float = 4; + + /** + * Number of steps per beat (bottom number in time signature). Defaults to 4. + */ + public static var stepsPerBeat:Float = 4; + /** * Current position of the song, in milliseconds. @@ -60,6 +70,11 @@ class Conductor * Current beat */ public static var curBeat:Int = 0; + + /** + * Current measure + */ + public static var curMeasure:Int = 0; /** @@ -71,6 +86,11 @@ class Conductor * Current beat, as a `Float` (ex: 1.24, instead of 1) */ public static var curBeatFloat:Float = 0; + + /** + * Current measure, as a `Float` (ex: 1.24, instead of 1) + */ + public static var curMeasureFloat:Float = 0; @:dox(hide) public static var lastSongPos:Float = 0; @@ -104,7 +124,7 @@ class Conductor public static function setupSong(SONG:SwagSong) { reset(); mapBPMChanges(SONG); - changeBPM(SONG.bpm); + changeBPM(SONG.bpm, cast SONG.beatsPerMesure.getDefault(4), cast SONG.stepsPerBeat.getDefault(4)); } /** * Maps BPM changes from a song. @@ -191,6 +211,8 @@ class Conductor } private static var __lastChange:BPMChangeEvent; private static var __updateBeat:Bool; + private static var __updateMeasure:Bool; + private static function update() { if (FlxG.state != null && FlxG.state is MusicBeatState && cast(FlxG.state, MusicBeatState).cancelConductorUpdate) return; @@ -214,11 +236,13 @@ class Conductor if (__lastChange.bpm > 0 && bpm != __lastChange.bpm) changeBPM(__lastChange.bpm); curStepFloat = __lastChange.stepTime + ((Conductor.songPosition - __lastChange.songTime) / Conductor.stepCrochet); - curBeatFloat = curStepFloat / 4; + curBeatFloat = curStepFloat / stepsPerBeat; + curMeasureFloat = curBeatFloat / beatsPerMesure; if (curStep != (curStep = Std.int(curStepFloat))) { // updates step - var __updateBeat = curBeat != (curBeat = Std.int(curBeatFloat)); + __updateBeat = curBeat != (curBeat = Std.int(curBeatFloat)); + __updateMeasure = __updateBeat && (curMeasure != (curMeasure = Std.int(curMeasureFloat))); onStepHit.dispatch(curStep); if (__updateBeat) @@ -227,11 +251,13 @@ class Conductor if (FlxG.state is IBeatReceiver) { var state = FlxG.state; while(state != null) { - if (state is IBeatReceiver && (state.subState == null || state.subState.persistentUpdate)) { + if (state is IBeatReceiver && (state.subState == null || state.persistentUpdate)) { var st = cast(state, IBeatReceiver); st.stepHit(curStep); if (__updateBeat) st.beatHit(curBeat); + if (__updateMeasure) + st.measureHit(curMeasure); } state = state.subState; } @@ -241,12 +267,16 @@ class Conductor } } - public static function changeBPM(newBpm:Float) + public static function changeBPM(newBpm:Float, beatsPerMesure:Float = 4, stepsPerBeat:Float = 4) { bpm = newBpm; crochet = ((60 / bpm) * 1000); - stepCrochet = crochet / 4; + stepCrochet = crochet / stepsPerBeat; + + Conductor.beatsPerMesure = beatsPerMesure; + Conductor.stepsPerBeat = stepsPerBeat; + onBPMChange.dispatch(bpm); } diff --git a/source/funkin/system/FunkinSprite.hx b/source/funkin/system/FunkinSprite.hx index 87c99b27..70f8cdfa 100644 --- a/source/funkin/system/FunkinSprite.hx +++ b/source/funkin/system/FunkinSprite.hx @@ -86,6 +86,7 @@ class FunkinSprite extends FlxSprite implements IBeatReceiver implements IOffset } } public function stepHit(curBeat:Int) {} + public function measureHit(curMeasure:Int) {} public override function getScreenBounds(?newRect:FlxRect, ?camera:FlxCamera):FlxRect { __doPreZoomScaleProcedure(camera); diff --git a/source/funkin/system/MusicBeatGroup.hx b/source/funkin/system/MusicBeatGroup.hx index 9e241bb0..700fc8d3 100644 --- a/source/funkin/system/MusicBeatGroup.hx +++ b/source/funkin/system/MusicBeatGroup.hx @@ -11,4 +11,7 @@ class MusicBeatGroup extends FlxTypedSpriteGroup implements IBeatRece public function stepHit(curStep:Int) { for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).stepHit(curStep); } + public function measureHit(curMeasure:Int) { + for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).measureHit(curMeasure); + } } \ No newline at end of file diff --git a/source/funkin/system/MusicBeatState.hx b/source/funkin/system/MusicBeatState.hx index 1bea665f..b19b13bc 100644 --- a/source/funkin/system/MusicBeatState.hx +++ b/source/funkin/system/MusicBeatState.hx @@ -30,6 +30,10 @@ class MusicBeatState extends FlxUIState implements IBeatReceiver * Current beat */ public var curBeat(get, never):Int; + /** + * Current beat + */ + public var curMeasure(get, never):Int; /** * Current step, as a `Float` (ex: 4.94, instead of 4) */ @@ -38,6 +42,10 @@ class MusicBeatState extends FlxUIState implements IBeatReceiver * Current beat, as a `Float` (ex: 1.24, instead of 1) */ public var curBeatFloat(get, never):Float; + /** + * Current beat, as a `Float` (ex: 1.24, instead of 1) + */ + public var curMeasureFloat(get, never):Float; /** * Current song position (in milliseconds). */ @@ -47,10 +55,14 @@ class MusicBeatState extends FlxUIState implements IBeatReceiver return Conductor.curStep; inline function get_curBeat():Int return Conductor.curBeat; + inline function get_curMeasure():Int + return Conductor.curMeasure; inline function get_curStepFloat():Float return Conductor.curStepFloat; inline function get_curBeatFloat():Float return Conductor.curBeatFloat; + inline function get_curMeasureFloat():Float + return Conductor.curMeasureFloat; inline function get_songPos():Float return Conductor.songPosition; @@ -171,6 +183,12 @@ class MusicBeatState extends FlxUIState implements IBeatReceiver call("beatHit", [curBeat]); } + @:dox(hide) public function measureHit(curMeasure:Int):Void + { + for(e in members) if (e != null && e is IBeatReceiver) cast(e, IBeatReceiver).measureHit(curMeasure); + call("measureHit", [curMeasure]); + } + /** * Shortcut to `FlxMath.lerp` or `CoolUtil.lerp`, depending on `fpsSensitive` * @param v1 Value 1 diff --git a/source/funkin/system/MusicBeatSubstate.hx b/source/funkin/system/MusicBeatSubstate.hx index 30450d90..13bd00d4 100644 --- a/source/funkin/system/MusicBeatSubstate.hx +++ b/source/funkin/system/MusicBeatSubstate.hx @@ -26,6 +26,10 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver * Current beat */ public var curBeat(get, never):Int; + /** + * Current beat + */ + public var curMeasure(get, never):Int; /** * Current step, as a `Float` (ex: 4.94, instead of 4) */ @@ -34,21 +38,29 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver * Current beat, as a `Float` (ex: 1.24, instead of 1) */ public var curBeatFloat(get, never):Float; + /** + * Current beat, as a `Float` (ex: 1.24, instead of 1) + */ + public var curMeasureFloat(get, never):Float; /** * Current song position (in milliseconds). */ - public var songPos(get, never):Float; - - inline function get_curStep():Int - return Conductor.curStep; - inline function get_curBeat():Int - return Conductor.curBeat; - inline function get_curStepFloat():Float - return Conductor.curStepFloat; - inline function get_curBeatFloat():Float - return Conductor.curBeatFloat; - inline function get_songPos():Float - return Conductor.songPosition; + public var songPos(get, never):Float; + + inline function get_curStep():Int + return Conductor.curStep; + inline function get_curBeat():Int + return Conductor.curBeat; + inline function get_curMeasure():Int + return Conductor.curMeasure; + inline function get_curStepFloat():Float + return Conductor.curStepFloat; + inline function get_curBeatFloat():Float + return Conductor.curBeatFloat; + inline function get_curMeasureFloat():Float + return Conductor.curMeasureFloat; + inline function get_songPos():Float + return Conductor.songPosition; /** @@ -177,6 +189,12 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver call("beatHit", [curBeat]); } + @:dox(hide) public function measureHit(curMeasure:Int):Void + { + for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).measureHit(curMeasure); + call("measureHit", [curMeasure]); + } + /** * Shortcut to `FlxMath.lerp` or `CoolUtil.lerp`, depending on `fpsSensitive` * @param v1 Value 1 diff --git a/source/funkin/system/Song.hx b/source/funkin/system/Song.hx index 0f06360b..2634fbc2 100644 --- a/source/funkin/system/Song.hx +++ b/source/funkin/system/Song.hx @@ -24,6 +24,8 @@ typedef SwagSong = // ADDITIONAL STUFF THAT MAY NOT BE PRESENT IN CHART var ?maxHealth:Float; + var ?beatsPerMesure:Float; + var ?stepsPerBeat:Float; } class Song diff --git a/source/funkin/system/framerate/ConductorInfo.hx b/source/funkin/system/framerate/ConductorInfo.hx index 6d1d6bca..499474d9 100644 --- a/source/funkin/system/framerate/ConductorInfo.hx +++ b/source/funkin/system/framerate/ConductorInfo.hx @@ -12,8 +12,10 @@ class ConductorInfo extends FramerateCategory { _text = 'Current Song Position: ${Conductor.songPosition}'; _text += '\n - ${Conductor.curBeat} beats'; _text += '\n - ${Conductor.curStep} steps'; + _text += '\n - ${Conductor.curMeasure} measures'; _text += '\nCurrent BPM: ${Conductor.bpm}'; _text += '\nCurrent speed: ${FlxMath.roundDecimal(Conductor.speed, 2)}x'; + _text += '\nTime Signature: ${Conductor.beatsPerMesure}/${Conductor.stepsPerBeat}'; this.text.text = _text; super.__enterFrame(t);