FunkinCrew / Funkin

A rhythm game made with HaxeFlixel
https://www.newgrounds.com/portal/view/770371
Other
2.97k stars 2.29k forks source link

Enhancement: automatic video caching for mid-song and onCountdownEnd cutscenes #2658

Open Johferson opened 5 months ago

Johferson commented 5 months ago

What is your suggestion, and why should it be implemented?

Dear Funkin' Crew, Inc, Please implement a system where videos, specifically those that are activated mid-song and after the countdown ends (NOT BEFORE COUNTDOWN) are automatically cached before a song starts playing. This is in order to fix sync issues related to cutscenes being called once the countdown ends and in order for modders to save time from coding in one out of the many possible methods of "caching" videos.

Thank you.

AbnormalPoof commented 1 month ago

Alternatively, you can also have the game re-sync the video for you!

Example:

    function onStepHit(event) {
        super.onStepHit(event);
        if (vidEvent != null && recentTime != null) {
            if (resyncVideo && vidEvent.bitmap.isPlaying) {

                var correctTime:Int = Conductor.instance.songPosition - recentTime - Conductor.instance.instrumentalOffset;

                if (Math.abs(vidEvent.bitmap.time - correctTime) > 700) {
                    trace('VIDEO NEEDS RESYNC!');
                    vidEvent.bitmap.time = correctTime;
                }
            }
        }
    }

vidEvent is the FlxVideoSprite object, recentTime is the timestamp of the most recent video created.

I use a custom function to make an FlxVideoSprite manually instead of using VideoCutscene:

    /**
     * Handles video creation
     * @param filePath The path to the video file to be played.
     * @param isCutscene Wether to hide the HUD or not, takes in an Int as an input.
     * @param disableControl Wether to disable controls during the video, Boolean.
     * @param duration The duration of the HUD fade (used in combination with isCutscene!).
     * @param resync Wether to automatically resync the video if it becomes desynced.
     * @param zIndex The zIndex of the video.
     * @param mute Wether to mute the video or not.
     */
    public function createVid(filePath:String, ?isCutscene:Int = 1, ?disableControl:Bool = false, ?duration:Float = 1, ?resync:Bool = true, ?zIndex:Int = 300,
            ?mute:Bool = false):Void {

        // Unrelated code.

        // We set recentTime here in the VERY last line! AFTER the video is played.
        recentTime = Conductor.instance.songPosition;
    }

Here, recentTime is set to Conductor's songPosition, which is then used in the re-syncing logic mentioned earlier:

    var correctTime:Int = Conductor.instance.songPosition - recentTime - Conductor.instance.instrumentalOffset;

    if (Math.abs(vidEvent.bitmap.time - correctTime) > 700) {
        trace('VIDEO NEEDS RESYNC!');
        vidEvent.bitmap.time = correctTime;
    }

One drawback this method has is that it needs to be during the song, since it uses Conductor.

I'm sure there's a better way of handling things, but this is the one that's the most effective for me. Video caching would still be the best method, ideally.