magical machine of death

This commit is contained in:
Burgerballs 2024-05-09 17:51:03 +01:00
parent 34a6e16385
commit edfde606a1
5 changed files with 227 additions and 11 deletions

View file

@ -236,6 +236,11 @@ class PlayState extends MusicBeatSubState
*/ */
public var cameraZoomTween:FlxTween; public var cameraZoomTween:FlxTween;
/**
* An FlxTween that changes the additive speed to the desired amount.
*/
public var additiveScrollSpeedTween:FlxTween;
/** /**
* The camera follow point from the last stage. * The camera follow point from the last stage.
* Used to persist the position of the `cameraFollowPosition` between levels. * Used to persist the position of the `cameraFollowPosition` between levels.
@ -1179,6 +1184,11 @@ class PlayState extends MusicBeatSubState
cameraZoomTween.active = false; cameraZoomTween.active = false;
cameraTweensPausedBySubState.add(cameraZoomTween); cameraTweensPausedBySubState.add(cameraZoomTween);
} }
if (additiveScrollSpeedTween != null && additiveScrollSpeedTween.active)
{
additiveScrollSpeedTween.active = false;
cameraTweensPausedBySubState.add(additiveScrollSpeedTween);
}
// Pause the countdown. // Pause the countdown.
Countdown.pauseCountdown(); Countdown.pauseCountdown();
@ -3023,8 +3033,9 @@ class PlayState extends MusicBeatSubState
// Stop camera zooming on beat. // Stop camera zooming on beat.
cameraZoomRate = 0; cameraZoomRate = 0;
// Cancel camera tweening if it's active. // Cancel camera and scroll tweening if it's active.
cancelAllCameraTweens(); cancelAllCameraTweens();
cancelAdditiveScrollSpeedTween();
// If the opponent is GF, zoom in on the opponent. // If the opponent is GF, zoom in on the opponent.
// Else, if there is no GF, zoom in on BF. // Else, if there is no GF, zoom in on BF.
@ -3244,6 +3255,41 @@ class PlayState extends MusicBeatSubState
cancelCameraZoomTween(); cancelCameraZoomTween();
} }
/**
* The magical function that shall tween the additive scroll speed.
*/
public function tweenAdditiveScrollSpeed(?speed:Float, ?duration:Float, ?ease:Null<Float->Float>):Void
{
// Cancel the current tween if it's active.
cancelAdditiveScrollSpeedTween();
var strumLineTargets:Array<Float> = [
playerStrumline.scrollSpeedAdditive + speed,
opponentStrumline.scrollSpeedAdditive + speed
];
if (duration == 0)
{
playerStrumline.scrollSpeedAdditive = strumLineTargets[0];
opponentStrumline.scrollSpeedAdditive = strumLineTargets[1];
}
else
{
additiveScrollSpeedTween = FlxTween.tween(this,
{
"playerStrumline.scrollSpeedAdditive": strumLineTargets[0],
"opponentStrumline.scrollSpeedAdditive": strumLineTargets[1]
}, duration, {ease: ease});
}
}
public function cancelAdditiveScrollSpeedTween()
{
if (additiveScrollSpeedTween != null)
{
additiveScrollSpeedTween.cancel();
}
}
#if (debug || FORCE_DEBUG_VERSION) #if (debug || FORCE_DEBUG_VERSION)
/** /**
* Jumps forward or backward a number of sections in the song. * Jumps forward or backward a number of sections in the song.

View file

@ -0,0 +1,138 @@
package funkin.play.event;
import flixel.tweens.FlxTween;
import flixel.FlxCamera;
import flixel.tweens.FlxEase;
// Data from the chart
import funkin.data.song.SongData;
import funkin.data.song.SongData.SongEventData;
// Data from the event schema
import funkin.play.event.SongEvent;
import funkin.data.event.SongEventSchema;
import funkin.data.event.SongEventSchema.SongEventFieldType;
/**
* This class represents a handler for scroll speed events.
*
* Example: Scroll speed change of both strums from 1x to 1.3x:
* ```
* {
* 'e': 'AdditiveScrollSpeed',
* "v": {
* "scroll": "0.3",
* "duration": "4",
* "ease": "linear"
* }
* }
* ```
*/
class AdditiveScrollSpeedEvent extends SongEvent
{
public function new()
{
super('AdditiveScrollSpeed');
}
static final DEFAULT_SCROLL:Float = 0;
static final DEFAULT_DURATION:Float = 4.0;
static final DEFAULT_EASE:String = 'linear';
public override function handleEvent(data:SongEventData):Void
{
// Does nothing if there is no PlayState camera or stage.
if (PlayState.instance == null || PlayState.instance.currentStage == null) return;
var scroll:Float = data.getFloat('scroll') ?? DEFAULT_SCROLL;
var duration:Float = data.getFloat('duration') ?? DEFAULT_DURATION;
var ease:String = data.getString('ease') ?? DEFAULT_EASE;
// If it's a string, check the value.
switch (ease)
{
case 'INSTANT':
PlayState.instance.tweenAdditiveScrollSpeed(scroll, 0);
default:
var durSeconds = Conductor.instance.stepLengthMs * duration / 1000;
var easeFunction:Null<Float->Float> = Reflect.field(FlxEase, ease);
if (easeFunction == null)
{
trace('Invalid ease function: $ease');
return;
}
PlayState.instance.tweenAdditiveScrollSpeed(scroll, durSeconds, easeFunction);
}
}
public override function getTitle():String
{
return 'Additive Scroll Speed';
}
/**
* ```
* {
* 'scroll': FLOAT, // Target additive scroll level.
* 'duration': FLOAT, // Duration in steps.
* 'ease': ENUM, // Easing function.
* }
* @return SongEventSchema
*/
public override function getEventSchema():SongEventSchema
{
return new SongEventSchema([
{
name: 'scroll',
title: 'Additive Scroll Amount',
defaultValue: 0.0,
step: 0.1,
type: SongEventFieldType.FLOAT,
units: 'x'
},
{
name: 'duration',
title: 'Duration',
defaultValue: 4.0,
step: 0.5,
type: SongEventFieldType.FLOAT,
units: 'steps'
},
{
name: 'ease',
title: 'Easing Type',
defaultValue: 'linear',
type: SongEventFieldType.ENUM,
keys: [
'Linear' => 'linear',
'Instant' => 'INSTANT',
'Sine In' => 'sineIn',
'Sine Out' => 'sineOut',
'Sine In/Out' => 'sineInOut',
'Quad In' => 'quadIn',
'Quad Out' => 'quadOut',
'Quad In/Out' => 'quadInOut',
'Cube In' => 'cubeIn',
'Cube Out' => 'cubeOut',
'Cube In/Out' => 'cubeInOut',
'Quart In' => 'quartIn',
'Quart Out' => 'quartOut',
'Quart In/Out' => 'quartInOut',
'Quint In' => 'quintIn',
'Quint Out' => 'quintOut',
'Quint In/Out' => 'quintInOut',
'Expo In' => 'expoIn',
'Expo Out' => 'expoOut',
'Expo In/Out' => 'expoInOut',
'Smooth Step In' => 'smoothStepIn',
'Smooth Step Out' => 'smoothStepOut',
'Smooth Step In/Out' => 'smoothStepInOut',
'Elastic In' => 'elasticIn',
'Elastic Out' => 'elasticOut',
'Elastic In/Out' => 'elasticInOut'
]
}
]);
}
}

View file

@ -52,6 +52,15 @@ class Strumline extends FlxSpriteGroup
*/ */
public var conductorInUse(get, set):Conductor; public var conductorInUse(get, set):Conductor;
// Used in-game to control the scroll speed within a song, for example if a song has an additive scroll speed of 1 and the base scroll speed is 1, it will be 2 - burgerballs
public var scrollSpeedAdditive:Float = 0;
public var scrollSpeed(get, never):Float;
function get_scrollSpeed():Float
{
return (PlayState.instance?.currentChart?.scrollSpeed ?? 1.0) + scrollSpeedAdditive;
}
var _conductorInUse:Null<Conductor>; var _conductorInUse:Null<Conductor>;
function get_conductorInUse():Conductor function get_conductorInUse():Conductor
@ -208,6 +217,11 @@ class Strumline extends FlxSpriteGroup
return null; return null;
} }
public function resetScrollSpeed():Void
{
scrollSpeedAdditive = 0;
}
public function getHoldNoteSprite(noteData:SongNoteData):SustainTrail public function getHoldNoteSprite(noteData:SongNoteData):SustainTrail
{ {
if (noteData == null || ((noteData.length ?? 0.0) <= 0.0)) return null; if (noteData == null || ((noteData.length ?? 0.0) <= 0.0)) return null;
@ -283,7 +297,6 @@ class Strumline extends FlxSpriteGroup
// var vwoosh:Float = (strumTime < Conductor.songPosition) && vwoosh ? 2.0 : 1.0; // var vwoosh:Float = (strumTime < Conductor.songPosition) && vwoosh ? 2.0 : 1.0;
// ^^^ commented this out... do NOT make it move faster as it moves offscreen! // ^^^ commented this out... do NOT make it move faster as it moves offscreen!
var vwoosh:Float = 1.0; var vwoosh:Float = 1.0;
var scrollSpeed:Float = PlayState.instance?.currentChart?.scrollSpeed ?? 1.0;
return return
Constants.PIXELS_PER_MS * (conductorInUse.songPosition - strumTime - Conductor.instance.inputOffset) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1); Constants.PIXELS_PER_MS * (conductorInUse.songPosition - strumTime - Conductor.instance.inputOffset) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1);
@ -539,6 +552,7 @@ class Strumline extends FlxSpriteGroup
{ {
playStatic(dir); playStatic(dir);
} }
scrollSpeedAdditive = 0;
} }
public function applyNoteData(data:Array<SongNoteData>):Void public function applyNoteData(data:Array<SongNoteData>):Void
@ -705,6 +719,7 @@ class Strumline extends FlxSpriteGroup
if (holdNoteSprite != null) if (holdNoteSprite != null)
{ {
holdNoteSprite.parentStrumline = this;
holdNoteSprite.noteData = note; holdNoteSprite.noteData = note;
holdNoteSprite.strumTime = note.time; holdNoteSprite.strumTime = note.time;
holdNoteSprite.noteDirection = note.getDirection(); holdNoteSprite.noteDirection = note.getDirection();

View file

@ -32,6 +32,7 @@ class SustainTrail extends FlxSprite
public var sustainLength(default, set):Float = 0; // millis public var sustainLength(default, set):Float = 0; // millis
public var fullSustainLength:Float = 0; public var fullSustainLength:Float = 0;
public var noteData:Null<SongNoteData>; public var noteData:Null<SongNoteData>;
public var parentStrumline:Strumline;
public var cover:NoteHoldCover = null; public var cover:NoteHoldCover = null;
@ -119,7 +120,7 @@ class SustainTrail extends FlxSprite
// CALCULATE SIZE // CALCULATE SIZE
graphicWidth = graphic.width / 8 * zoom; // amount of notes * 2 graphicWidth = graphic.width / 8 * zoom; // amount of notes * 2
graphicHeight = sustainHeight(sustainLength, getScrollSpeed()); graphicHeight = sustainHeight(sustainLength, parentStrumline?.scrollSpeed ?? 1.0);
// instead of scrollSpeed, PlayState.SONG.speed // instead of scrollSpeed, PlayState.SONG.speed
flipY = Preferences.downscroll; flipY = Preferences.downscroll;
@ -135,9 +136,21 @@ class SustainTrail extends FlxSprite
this.active = true; // This NEEDS to be true for the note to be drawn! this.active = true; // This NEEDS to be true for the note to be drawn!
} }
function getScrollSpeed():Float function getBaseScrollSpeed()
{ {
return PlayState?.instance?.currentChart?.scrollSpeed ?? 1.0; return (PlayState.instance?.currentChart?.scrollSpeed ?? 1.0);
}
var previousScrollSpeed:Float = 1;
override function update(elapsed)
{
super.update(elapsed);
if (previousScrollSpeed != (parentStrumline?.scrollSpeed ?? 1.0))
{
triggerRedraw();
}
previousScrollSpeed = parentStrumline?.scrollSpeed ?? 1.0;
} }
/** /**
@ -155,12 +168,16 @@ class SustainTrail extends FlxSprite
if (s < 0.0) s = 0.0; if (s < 0.0) s = 0.0;
if (sustainLength == s) return s; if (sustainLength == s) return s;
graphicHeight = sustainHeight(s, getScrollSpeed());
this.sustainLength = s; this.sustainLength = s;
triggerRedraw();
return this.sustainLength;
}
function triggerRedraw()
{
graphicHeight = sustainHeight(sustainLength, parentStrumline?.scrollSpeed ?? 1.0);
updateClipping(); updateClipping();
updateHitbox(); updateHitbox();
return this.sustainLength;
} }
public override function updateHitbox():Void public override function updateHitbox():Void
@ -178,7 +195,7 @@ class SustainTrail extends FlxSprite
*/ */
public function updateClipping(songTime:Float = 0):Void public function updateClipping(songTime:Float = 0):Void
{ {
var clipHeight:Float = FlxMath.bound(sustainHeight(sustainLength - (songTime - strumTime), getScrollSpeed()), 0, graphicHeight); var clipHeight:Float = FlxMath.bound(sustainHeight(sustainLength - (songTime - strumTime), parentStrumline?.scrollSpeed ?? 1.0), 0, graphicHeight);
if (clipHeight <= 0.1) if (clipHeight <= 0.1)
{ {
visible = false; visible = false;

View file

@ -58,11 +58,11 @@ class ChartEditorHoldNoteSprite extends SustainTrail
{ {
if (lerp) if (lerp)
{ {
sustainLength = FlxMath.lerp(sustainLength, h / (getScrollSpeed() * Constants.PIXELS_PER_MS), 0.25); sustainLength = FlxMath.lerp(sustainLength, h / (getBaseScrollSpeed() * Constants.PIXELS_PER_MS), 0.25);
} }
else else
{ {
sustainLength = h / (getScrollSpeed() * Constants.PIXELS_PER_MS); sustainLength = h / (getBaseScrollSpeed() * Constants.PIXELS_PER_MS);
} }
fullSustainLength = sustainLength; fullSustainLength = sustainLength;