1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2024-10-03 15:59:04 +00:00

Standardized camera zoom tweening to match camera follow tweening. Implemented methods to cancel tweens in necessary places. Start of pausing tweens when pausing the game (WIP). (CHANGES NOT TESTED EXPECT SOMETHING TO BREAK)

This commit is contained in:
Jenny Crowe 2024-03-10 16:35:41 -07:00
parent f9291d6458
commit 6b8fb7dc77
5 changed files with 136 additions and 38 deletions

View file

@ -119,6 +119,8 @@ class GameOverSubState extends MusicBeatSubState
// Set up the visuals
//
var playState = PlayState.instance;
// Add a black background to the screen.
var bg = new FunkinSprite().makeSolidColor(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK);
// We make this transparent so that we can see the stage underneath during debugging,
@ -130,13 +132,16 @@ class GameOverSubState extends MusicBeatSubState
// Pluck Boyfriend from the PlayState and place him (in the same position) in the GameOverSubState.
// We can then play the character's `firstDeath` animation.
boyfriend = PlayState.instance.currentStage.getBoyfriend(true);
boyfriend = playState.currentStage.getBoyfriend(true);
boyfriend.isDead = true;
add(boyfriend);
boyfriend.resetCharacter();
// Cancel camera tweening if it's currently active.
playState.cancelAllCameraTweens();
// Assign a camera follow point to the boyfriend's position.
cameraFollowPoint = new FlxObject(PlayState.instance.cameraFollowPoint.x, PlayState.instance.cameraFollowPoint.y, 1, 1);
cameraFollowPoint = new FlxObject(playState.cameraFollowPoint.x, playState.cameraFollowPoint.y, 1, 1);
cameraFollowPoint.x = boyfriend.getGraphicMidpoint().x;
cameraFollowPoint.y = boyfriend.getGraphicMidpoint().y;
var offsets:Array<Float> = boyfriend.getDeathCameraOffsets();

View file

@ -242,6 +242,11 @@ class PlayState extends MusicBeatSubState
*/
public var cameraFollowTween:FlxTween;
/**
* An FlxTween that zooms the camera to the desired amount.
*/
public var cameraZoomTween:FlxTween;
/**
* The camera follow point from the last stage.
* Used to persist the position of the `cameraFollowPosition` between levels.
@ -402,10 +407,12 @@ class PlayState extends MusicBeatSubState
var startingSong:Bool = false;
/**
* False if `FlxG.sound.music`
* Track if we currently have the music paused for a Pause substate, so we can unpause it when we return.
*/
var musicPausedBySubState:Bool = false;
var cameraFollowTweenPausedBySubState:Bool = false; // Idea FOR LATER: Store paused tweens in an array, so we know which ones to unpause when leaving the Pause substate.
/**
* False until `create()` has completed.
*/
@ -1126,14 +1133,24 @@ class PlayState extends MusicBeatSubState
// Pause the music.
if (FlxG.sound.music != null)
{
musicPausedBySubState = FlxG.sound.music.playing;
if (musicPausedBySubState)
if (FlxG.sound.music.playing)
{
FlxG.sound.music.pause();
musicPausedBySubState = true;
}
// Pause vocals.
// Not tracking that we've done this via a bool because vocal re-syncing involves pausing the vocals anyway.
if (vocals != null) vocals.pause();
}
// Pause camera tweening.
if (cameraFollowTween != null && cameraFollowTween.active)
{
cameraFollowTween.active = false;
cameraFollowTweenPausedBySubState = true;
}
// Pause the countdown.
Countdown.pauseCountdown();
}
@ -1155,10 +1172,18 @@ class PlayState extends MusicBeatSubState
if (event.eventCanceled) return;
// Resume
// Resume music if we paused it.
if (musicPausedBySubState)
{
FlxG.sound.music.play();
musicPausedBySubState = false;
}
// Resume camera tweening if we paused it.
if (cameraFollowTweenPausedBySubState)
{
cameraFollowTween.active = true;
cameraFollowTweenPausedBySubState = false;
}
if (currentConversation != null)
@ -1166,6 +1191,7 @@ class PlayState extends MusicBeatSubState
currentConversation.resumeMusic();
}
// Re-sync vocals.
if (FlxG.sound.music != null && !startingSong && !isInCutscene) resyncVocals();
// Resume the countdown.
@ -2852,6 +2878,9 @@ class PlayState extends MusicBeatSubState
*/
function performCleanup():Void
{
// If the camera is being tweened, stop it.
cancelAllCameraTweens();
if (currentConversation != null)
{
remove(currentConversation);
@ -2910,6 +2939,9 @@ class PlayState extends MusicBeatSubState
// Stop camera zooming on beat.
cameraZoomRate = 0;
// Cancel camera tweening if it's active.
cancelAllCameraTweens();
// If the opponent is GF, zoom in on the opponent.
// Else, if there is no GF, zoom in on BF.
// Else, zoom in on GF.
@ -2996,12 +3028,12 @@ class PlayState extends MusicBeatSubState
/**
* Resets the camera's zoom level and focus point.
*/
public function resetCamera(?resetZoom:Bool = true, ?cancelFollowTween:Bool = true):Void
public function resetCamera(?resetZoom:Bool = true, ?cancelTweens:Bool = true):Void
{
// Cancel the follow tween if it's active.
if (cancelFollowTween && cameraFollowTween != null)
// Cancel camera tweens if any are active.
if (cancelTweens)
{
cameraFollowTween.cancel();
cancelAllCameraTweens();
}
FlxG.camera.follow(cameraFollowPoint, LOCKON, 0.04);
@ -3019,26 +3051,78 @@ class PlayState extends MusicBeatSubState
/**
* Disables camera following and tweens the camera to the follow point manually.
*/
public function tweenCamera(?duration:Float, ?ease:Null<Float->Float>):Void
public function tweenCameraToFollowPoint(?duration:Float, ?ease:Null<Float->Float>):Void
{
// Cancel the current tween if it's active.
cancelCameraFollowTween();
if (duration == 0)
{
// Instant movement. Just reset the camera to force it to the follow point.
resetCamera(false, false);
}
else
{
// Disable camera following for the duration of the tween.
FlxG.camera.target = null;
// Follow tween! Caching it so we can cancel/pause it later if needed.
var followPos:FlxPoint = cameraFollowPoint.getPosition() - FlxPoint.weak(FlxG.camera.width * 0.5, FlxG.camera.height * 0.5);
cameraFollowTween = FlxTween.tween(FlxG.camera.scroll, {x: followPos.x, y: followPos.y}, duration,
{
ease: ease,
onComplete: function(_) {
resetCamera(false, false); // Re-enable camera following when the tween is complete.
}
});
}
}
public function cancelCameraFollowTween()
{
if (cameraFollowTween != null)
{
cameraFollowTween.cancel();
}
}
// Disable camera following for the duration of the tween.
FlxG.camera.target = null;
/**
* Tweens the camera zoom to the desired amount. Tweens defaultCameraZoom to avoid breaking camera bops.
*/
public function tweenCameraZoom(?zoom:Float, ?duration:Float, ?ease:Null<Float->Float>):Void
{
// Cancel the current tween if it's active.
cancelCameraZoomTween();
// Follow tween! Caching it so we can cancel it later if needed.
var followPos:FlxPoint = cameraFollowPoint.getPosition() - FlxPoint.weak(FlxG.camera.width * 0.5, FlxG.camera.height * 0.5);
cameraFollowTween = FlxTween.tween(FlxG.camera.scroll, {x: followPos.x, y: followPos.y}, duration,
{
ease: ease,
onComplete: function(_) {
resetCamera(false, false); // Re-enable camera following when the tween is complete.
}
});
var targetZoom = zoom * FlxCamera.defaultZoom;
if (duration == 0)
{
// Instant zoom. No tween needed.
defaultCameraZoom = targetZoom;
}
else
{
// Zoom tween! Caching it so we can cancel/pause it later if needed.
cameraZoomTween = FlxTween.tween(this, {defaultCameraZoom: targetZoom}, duration, {ease: ease});
}
}
public function cancelCameraZoomTween()
{
if (cameraZoomTween != null)
{
cameraZoomTween.cancel();
}
}
/**
* Cancel all active camera tweens simultaneously.
*/
public function cancelAllCameraTweens()
{
cancelCameraFollowTween();
cancelCameraZoomTween();
}
#if (debug || FORCE_DEBUG_VERSION)

View file

@ -125,16 +125,22 @@ class FocusCameraSongEvent extends SongEvent
if (useTween)
{
var durSeconds = Conductor.instance.stepLengthMs * duration / 1000;
var easeFunction:Null<Float->Float> = Reflect.field(FlxEase, ease);
if (easeFunction == null)
switch (ease)
{
trace('Invalid ease function: $ease');
return;
}
case 'INSTANT':
PlayState.instance.tweenCameraToFollowPoint(0);
default:
var durSeconds = Conductor.instance.stepLengthMs * duration / 1000;
PlayState.instance.tweenCamera(durSeconds, easeFunction);
var easeFunction:Null<Float->Float> = Reflect.field(FlxEase, ease);
if (easeFunction == null)
{
trace('Invalid ease function: $ease');
return;
}
PlayState.instance.tweenCameraToFollowPoint(durSeconds, easeFunction);
}
}
}

View file

@ -69,9 +69,10 @@ class ZoomCameraSongEvent extends SongEvent
switch (ease)
{
case 'INSTANT':
// Set the zoom. Use defaultCameraZoom to prevent breaking camera bops.
PlayState.instance.defaultCameraZoom = zoom * FlxCamera.defaultZoom;
PlayState.instance.tweenCameraZoom(zoom, 0);
default:
var durSeconds = Conductor.instance.stepLengthMs * duration / 1000;
var easeFunction:Null<Float->Float> = Reflect.field(FlxEase, ease);
if (easeFunction == null)
{
@ -79,8 +80,7 @@ class ZoomCameraSongEvent extends SongEvent
return;
}
FlxTween.tween(PlayState.instance, {defaultCameraZoom: zoom * FlxCamera.defaultZoom}, (Conductor.instance.stepLengthMs * duration / 1000),
{ease: easeFunction});
PlayState.instance.tweenCameraZoom(zoom, durSeconds, easeFunction);
}
}

View file

@ -49,8 +49,11 @@ class StageOffsetSubState extends HaxeUISubState
{
super.create();
var playState = PlayState.instance;
FlxG.mouse.visible = true;
PlayState.instance.pauseMusic();
playState.pauseMusic();
playState.cancelAllCameraTweens();
FlxG.camera.target = null;
setupUIListeners();
@ -63,8 +66,8 @@ class StageOffsetSubState extends HaxeUISubState
// add(uiStuff);
PlayState.instance.persistentUpdate = true;
component.cameras = [PlayState.instance.camHUD];
playState.persistentUpdate = true;
component.cameras = [playState.camHUD];
// uiStuff.cameras = [PlayState.instance.camHUD];
// btn.cameras = [PlayState.instance.camHUD];
@ -72,7 +75,7 @@ class StageOffsetSubState extends HaxeUISubState
var layerList:ListView = findComponent("prop-layers");
for (thing in PlayState.instance.currentStage)
for (thing in playState.currentStage)
{
var prop:StageProp = cast thing;
if (prop != null && prop.name != null)