BG Parallax Configurable

Background
Configurable

Moves the background in the opposite direction of player cursor. As seen in Chata - enn. Configureable version.

Creates a pretty sharp screen move effect. The background moves opposite to the direction of the next hitobjects, so in gameplay it looks like the background is parallax with the cursor. Script includes a parameter for start/end fade for smooth transitions. Fade out opacity can also be configured.

Script
using StorybrewCommon.Scripting;
using StorybrewCommon.Storyboarding;
using StorybrewCommon.Mapset;
using System.Linq;
using OpenTK;

namespace StorybrewScripts
{
    public class BGParallax : StoryboardObjectGenerator
    {
        [Configurable]
        public string BackgroundPath = "";

        [Configurable]
        public int StartTime = 0;

        [Configurable]
        public int EndTime = 0;

        [Configurable]
        public double StartFadeDuration = 200;

        [Configurable]
        public double EndFadeDuration = 200;

        [Configurable]
        public double Opacity = 0.2;

        [Configurable]
        public float Shake = 0.015f;

        public override void Generate()
        {
            if (BackgroundPath == "") BackgroundPath = Beatmap.BackgroundPath ?? string.Empty;
            if (StartTime == EndTime) EndTime = (int)(Beatmap.HitObjects.LastOrDefault()?.EndTime ?? AudioDuration);
            Parallaxer(BackgroundPath, StartFadeDuration, StartTime, EndTime, EndFadeDuration, Opacity, Shake);
        }

        public void Parallaxer(string BackgroundPath, double StartFade, int StartTime, int EndTime, double EndFade, double Opacity, float Shake)
        {
            var bitmap = GetMapsetBitmap(BackgroundPath);
            var bg = GetLayer("blur").CreateSprite(BackgroundPath);
            var beat = Beatmap.GetTimingPointAt(StartTime).BeatDuration;
            Vector2 screenCenter = new Vector2(320, 240);
            Vector2 position;
            Vector2 oldPosition = screenCenter;
            Vector2 direction;
            double lastTime = StartTime;

            bg.Scale(StartTime, (480.0f / bitmap.Height));
            bg.Fade(StartTime-StartFadeDuration, StartTime, 0, Opacity);
            bg.Fade(EndTime-EndFadeDuration, EndTime , Opacity , 0);

            foreach (var hitobject in Beatmap.HitObjects)
            {
                if (hitobject.StartTime >= StartTime && hitobject.StartTime <= EndTime)
                {
                    direction = (screenCenter + hitobject.Position) * Shake;
                    position = screenCenter + direction;
                    bg.Move(OsbEasing.InOutQuad, lastTime, hitobject.StartTime, oldPosition, position);
                    oldPosition = position;
                    lastTime = hitobject.StartTime;
                }
            }
        }
    }
}
Example Usage
Configurable