pause button/pause screen rework

This commit is contained in:
fabs
2025-06-08 04:09:40 +01:00
parent a9a4dad511
commit b3ebfd0910
2 changed files with 161 additions and 24 deletions
+114 -14
View File
@@ -17,7 +17,10 @@ import funkin.ui.freeplay.FreeplayState;
import funkin.graphics.FunkinSprite;
import funkin.play.cutscene.VideoCutscene;
import funkin.ui.AtlasText;
import flixel.util.FlxTimer;
import funkin.ui.MusicBeatSubState;
import funkin.util.HapticUtil;
import funkin.ui.FullScreenScaleMode;
import funkin.ui.transition.stickers.StickerSubState;
import funkin.util.SwipeUtil;
import funkin.util.TouchUtil;
@@ -74,7 +77,9 @@ class PauseSubState extends MusicBeatSubState
* Pause menu entries for when the game is paused during a video cutscene.
*/
static final PAUSE_MENU_ENTRIES_VIDEO_CUTSCENE:Array<PauseMenuEntry> = [
#if !mobile
{text: 'Resume', callback: resume},
#end
{text: 'Skip Cutscene', callback: skipVideoCutscene},
{text: 'Restart Cutscene', callback: restartVideoCutscene},
{text: 'Exit to Menu', callback: quitToMenu},
@@ -149,6 +154,18 @@ class PauseSubState extends MusicBeatSubState
// Graphics Variables
// ===============
#if mobile
/**
* The pause button for the game, only appears in Mobile targets. Shows up breifly to finish the pause animation.
*/
var pauseButton:FunkinSprite;
/**
* The pause circle for the game, only appears in Mobile targets. Shows up breifly to finish the pause animation.
*/
var pauseCircle:FunkinSprite;
#end
/**
* The placeholder sprite displayed when an advertisement fails to load or display.
*/
@@ -253,6 +270,10 @@ class PauseSubState extends MusicBeatSubState
super.destroy();
charterFadeTween.cancel();
charterFadeTween = null;
dataFadeTimer.cancel();
dataFadeTimer = null;
hapticTimer.cancel();
hapticTimer = null;
pauseMusic.stop();
}
@@ -321,6 +342,29 @@ class PauseSubState extends MusicBeatSubState
background.scrollFactor.set(0, 0);
background.updateHitbox();
add(background);
#if mobile
pauseButton = FunkinSprite.createSparrow(0, 0, "pauseButton");
pauseButton.animation.addByIndices('idle', 'pause', [0], "", 24, false);
pauseButton.animation.addByIndices('hold', 'pause', [5], "", 24, false);
pauseButton.animation.addByIndices('confirm', 'pause', [
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
], "", 24, false);
pauseButton.scale.set(0.8, 0.8);
pauseButton.updateHitbox();
pauseButton.animation.play("confirm");
pauseButton.setPosition((FlxG.width - pauseButton.width) - 35, 35);
pauseCircle = FunkinSprite.create(0, 0, 'pauseCircle');
pauseCircle.scale.set(0.84, 0.8);
pauseCircle.updateHitbox();
pauseCircle.x = ((pauseButton.x + (pauseButton.width / 2)) - (pauseCircle.width / 2));
pauseCircle.y = ((pauseButton.y + (pauseButton.height / 2)) - (pauseCircle.height / 2));
pauseCircle.alpha = 0.1;
add(pauseCircle);
add(pauseButton);
#end
}
/**
@@ -332,7 +376,7 @@ class PauseSubState extends MusicBeatSubState
metadata.scrollFactor.set(0, 0);
add(metadata);
var metadataSong:FlxText = new FlxText(20, 580, camera.width - Math.max(40, funkin.ui.FullScreenScaleMode.gameNotchSize.x), 'Song Name');
var metadataSong:FlxText = new FlxText(20, 15, camera.width - Math.max(40, funkin.ui.FullScreenScaleMode.gameNotchSize.x), 'Song Name');
metadataSong.setFormat(Paths.font('vcr.ttf'), 32, FlxColor.WHITE, FlxTextAlign.RIGHT);
if (PlayState.instance?.currentChart != null)
{
@@ -373,6 +417,12 @@ class PauseSubState extends MusicBeatSubState
metadataPractice.scrollFactor.set(0, 0);
metadata.add(metadataPractice);
metadataArtist.alpha = 0;
metadataPractice.alpha = 0;
metadataSong.alpha = 0;
metadataDifficulty.alpha = 0;
metadataDeaths.alpha = 0;
updateMetadataText();
}
@@ -432,6 +482,9 @@ class PauseSubState extends MusicBeatSubState
});
}
var dataFadeTimer = new FlxTimer();
var hapticTimer = new FlxTimer();
/**
* Perform additional animations to transition the pause menu in when it is first displayed.
*/
@@ -439,11 +492,35 @@ class PauseSubState extends MusicBeatSubState
{
FlxTween.tween(background, {alpha: 0.6}, 0.8, {ease: FlxEase.quartOut});
#if mobile
HapticUtil.vibrate(0, 0.05, 0.5);
pauseButton.animation.play("confirm");
pauseCircle.scale.set(0.84 * 1.4, 0.8 * 1.4);
pauseCircle.alpha = 0.4;
FlxTween.tween(pauseCircle.scale, {x: 0.84 * 0.8, y: 0.8 * 0.8}, 0.4, {ease: FlxEase.backInOut});
FlxTween.tween(pauseCircle, {alpha: 0}, 0.6, {ease: FlxEase.quartOut});
hapticTimer.start(0.2, function(_) {
HapticUtil.vibrate(0, 0.01, 0.2);
});
dataFadeTimer.start(0.3, function(_) {
transitionMetadataIn();
FlxTween.tween(pauseButton, {alpha: 0}, 0.6, {ease: FlxEase.quartOut});
});
#else
transitionMetadataIn();
#end
}
function transitionMetadataIn():Void
{
// Animate each element a little bit downwards.
var delay:Float = 0.1;
for (child in metadata.members)
{
FlxTween.tween(child, {alpha: 1, y: child.y - 5}, 1.8, {ease: FlxEase.quartOut, startDelay: delay});
FlxTween.tween(child, {alpha: 1, y: child.y + 5}, 1.8, {ease: FlxEase.quartOut, startDelay: delay});
delay += 0.1;
}
}
@@ -460,8 +537,8 @@ class PauseSubState extends MusicBeatSubState
if (!allowInput) return;
// Doing this just so it'd look better i guess.
final upP:Bool = controls.UI_UP_P || SwipeUtil.swipeUp;
final downP:Bool = controls.UI_DOWN_P || SwipeUtil.swipeDown;
final upP:Bool = controls.UI_UP_P;
final downP:Bool = controls.UI_DOWN_P;
if (upP)
{
@@ -481,10 +558,12 @@ class PauseSubState extends MusicBeatSubState
if (i == currentEntry)
{
currentMenuEntries[currentEntry].callback(this);
HapticUtil.vibrate(0, 0.05, 0.5);
break;
}
changeSelection(i - currentEntry);
HapticUtil.vibrate(0, 0.01, 0.2);
break;
}
@@ -498,16 +577,13 @@ class PauseSubState extends MusicBeatSubState
{
resume(this);
}
// we only want justOpened to be true for 1 single frame, when we first get into the pause menu substate
justOpened = false;
#if FEATURE_DEBUG_FUNCTIONS
// to pause the game and get screenshots easy, press H on pause menu!
if (FlxG.keys.justPressed.H)
{
var visible = !metadata.visible;
metadata.visible = visible;
menuEntryText.visible = visible;
background.visible = visible;
@@ -545,11 +621,20 @@ class PauseSubState extends MusicBeatSubState
// Set the transparency.
text.alpha = isCurrent ? 1.0 : 0.6;
#if mobile
// Set the position.
if (isCurrent && currentEntry != prevEntry)
{
FlxTween.globalManager.cancelTweensOf(text);
text.x = 165;
FlxTween.tween(text, {x: 150}, 0.2, {ease: FlxEase.backInOut});
}
#else
var targetX = FlxMath.remapToRange((entryIndex - currentEntry), 0, 1, 0, 1.3) * 20 + Math.max(90, funkin.ui.FullScreenScaleMode.gameNotchSize.x);
var targetY = FlxMath.remapToRange((entryIndex - currentEntry), 0, 1, 0, 1.3) * 120 + (camera.height * 0.48);
FlxTween.globalManager.cancelTweensOf(text);
FlxTween.tween(text, {x: targetX, y: targetY}, 0.33, {ease: FlxEase.quartOut});
#end
}
}
@@ -649,6 +734,26 @@ class PauseSubState extends MusicBeatSubState
else
{
// Handle visible entries.
#if mobile
// var yPos:Float = (150 * entryIndex) + 100;
// var yPos:Float = (140 * entryIndex) + 150;
var yPos:Float = (105 * entryIndex) + 150;
var text:AtlasText = new AtlasText(110, yPos, entry.text, AtlasFont.BOLD);
text.scrollFactor.set(0, 0);
text.alpha = 0;
for (letter in text)
{
letter.width *= 1.2;
letter.height *= 1.4;
}
menuEntryText.add(text);
FlxTween.tween(text, {x: 150}, 0.4 * (entryIndex + 1), {ease: FlxEase.expoOut});
entry.sprite = text;
#else
var yPos:Float = 70 * entryIndex + 30;
var text:AtlasText = new AtlasText(0, yPos, entry.text, AtlasFont.BOLD);
text.scrollFactor.set(0, 0);
@@ -661,6 +766,7 @@ class PauseSubState extends MusicBeatSubState
menuEntryText.add(text);
entry.sprite = text;
#end
entryIndex++;
}
@@ -681,13 +787,7 @@ class PauseSubState extends MusicBeatSubState
function updateMetadataText():Void
{
metadataPractice.visible = PlayState.instance?.isPracticeMode ?? false;
if (metadata.members[0].y != 548 && metadataPractice.visible)
{
for (text in metadata)
{
text.y -= 32;
}
}
switch (this.currentMode)
{
case Standard | Difficulty:
+47 -10
View File
@@ -10,6 +10,7 @@ import flixel.math.FlxMath;
import flixel.math.FlxPoint;
import flixel.text.FlxText;
import flixel.tweens.FlxTween;
import flixel.tweens.FlxEase;
import flixel.ui.FlxBar;
import flixel.util.FlxColor;
import flixel.util.FlxStringUtil;
@@ -535,6 +536,11 @@ class PlayState extends MusicBeatSubState
* The pause button for the game, only appears in Mobile targets.
*/
var pauseButton:FunkinSprite;
/**
* The pause circle for the game, only appears in Mobile targets.
*/
var pauseCircle:FunkinSprite;
#end
/**
@@ -780,17 +786,27 @@ class PlayState extends MusicBeatSubState
// Create the pause button.
#if mobile
pauseButton = FunkinSprite.createSparrow(0, 0, "fonts/bold");
pauseButton.animation.addByPrefix("idle", "(", 24, true);
pauseButton.animation.play("idle");
pauseButton.color = FlxColor.WHITE;
pauseButton.alpha = 0.65;
pauseButton = FunkinSprite.createSparrow(0, 0, "pauseButton");
pauseButton.animation.addByIndices('idle', 'back', [0], "", 24, false);
pauseButton.animation.addByIndices('hold', 'back', [5], "", 24, false);
pauseButton.animation.addByIndices('confirm', 'back', [
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
], "", 24, false);
pauseButton.scale.set(0.8, 0.8);
pauseButton.updateHitbox();
pauseButton.setPosition((FlxG.width - pauseButton.width) - Math.max(40, FullScreenScaleMode.gameNotchSize.x), 3);
pauseButton.animation.play("idle");
pauseButton.setPosition((FlxG.width - pauseButton.width) - 35, 35);
pauseButton.cameras = [camControls];
pauseButton.width *= 2;
pauseButton.height *= 2;
pauseButton.offset.set(-(pauseButton.width / 4), -(pauseButton.height / 4));
pauseCircle = FunkinSprite.create(0, 0, 'pauseCircle');
pauseCircle.scale.set(0.84, 0.8);
pauseCircle.updateHitbox();
pauseCircle.cameras = [camControls];
pauseCircle.x = ((pauseButton.x + (pauseButton.width / 2)) - (pauseCircle.width / 2));
pauseCircle.y = ((pauseButton.y + (pauseButton.height / 2)) - (pauseCircle.height / 2));
pauseCircle.alpha = 0.1;
add(pauseCircle);
add(pauseButton);
hitbox.forEachAlive(function(hint:FunkinHint) {
hint.deadZones.push(pauseButton);
@@ -1019,7 +1035,14 @@ class PlayState extends MusicBeatSubState
#if mobile
if (justUnpaused)
{
pauseButton.alpha = 0.65;
// pauseButton.alpha = 1;
// pauseCircle.alpha = 0.1;
FlxTween.cancelTweensOf(pauseButton);
FlxTween.cancelTweensOf(pauseCircle);
FlxTween.tween(pauseButton, {alpha: 1}, 0.25, {ease: FlxEase.quartOut});
FlxTween.tween(pauseCircle, {alpha: 0.1}, 0.25, {ease: FlxEase.quartOut});
if (!startingSong) hitbox.visible = true;
}
@@ -1140,6 +1163,7 @@ class PlayState extends MusicBeatSubState
#if mobile
if ((VideoCutscene.isPlaying() || isInCutscene) && !pauseButton.visible) pauseButton.visible = true;
pauseCircle.visible = pauseButton.visible;
#end
justUnpaused = false;
@@ -1155,7 +1179,11 @@ class PlayState extends MusicBeatSubState
Countdown.pauseCountdown();
#if mobile
FlxTween.cancelTweensOf(pauseButton);
FlxTween.cancelTweensOf(pauseCircle);
pauseButton.alpha = 0;
pauseCircle.alpha = 0;
hitbox.visible = false;
#end
var event = new PauseScriptEvent(FlxG.random.bool((1 / 1000) * 100));
@@ -3018,7 +3046,11 @@ class PlayState extends MusicBeatSubState
{
currentConversation.pauseMusic();
#if mobile
FlxTween.cancelTweensOf(pauseButton);
FlxTween.cancelTweensOf(pauseCircle);
pauseButton.alpha = 0;
pauseCircle.alpha = 0;
hitbox.visible = false;
#end
@@ -3038,7 +3070,11 @@ class PlayState extends MusicBeatSubState
{
VideoCutscene.pauseVideo();
#if mobile
FlxTween.cancelTweensOf(pauseButton);
FlxTween.cancelTweensOf(pauseCircle);
pauseButton.alpha = 0;
pauseCircle.alpha = 0;
hitbox.visible = false;
#end
@@ -3080,6 +3116,7 @@ class PlayState extends MusicBeatSubState
#if mobile
// Hide the buttons while the song is ending.
hitbox.visible = pauseButton.visible = false;
pauseCircle.visible = false;
#end
// Check if any events want to prevent the song from ending.